From 5f6f80996291cad62774a313f90e0a49740aa0d0 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 29 May 2024 10:45:22 +0200 Subject: [PATCH 01/10] First version of secret validation app #3141 - basic structure and first version of config model - validation section - categorization section - unit tests and spring boot tests - README with documentation --- gradle/projects.gradle | 3 + sechub-wrapper-secret-validator/README.adoc | 95 ++ sechub-wrapper-secret-validator/build.gradle | 23 + .../validator/SecretValidatorApplication.java | 13 + .../validator/cli/SecretValidatorCLI.java | 45 + .../execution/ResponseValidationService.java | 77 ++ .../execution/SecretValidationResult.java | 31 + .../execution/SecretValidationService.java | 42 + .../execution/SecretValidationStatus.java | 23 + .../SecretValidatorCategorizationService.java | 42 + .../SecretValidatorExecutionContext.java | 72 ++ ...ecretValidatorExecutionContextFactory.java | 90 ++ .../SecretValidatorExecutionService.java | 74 ++ .../SecretValidatorWebRequestService.java | 113 +++ .../model/SecretValidatorCategorization.java | 50 + .../SecretValidatorConfigurationModel.java | 42 + ...SecretValidatorConfigurationModelList.java | 25 + .../model/SecretValidatorRequest.java | 53 + .../model/SecretValidatorRequestHeader.java | 27 + .../model/SecretValidatorResponse.java | 28 + .../SecretValidatorResponseContains.java | 36 + .../SecretValidatorPDSJobResult.java | 28 + .../properties/SecretValidatorProperties.java | 38 + .../validator/support/SarifImporterKeys.java | 31 + .../support/SarifValidationSupport.java | 50 + .../SecretValidatorHttpClientFactory.java | 85 ++ .../cli/SecretValidatorSpringBootTest.java | 60 ++ .../ResponseValidationServiceTest.java | 245 +++++ .../execution/SecretValidationResultTest.java | 39 + .../SecretValidationServiceTest.java | 108 ++ ...retValidatorCategorizationServiceTest.java | 180 ++++ ...tValidatorExecutionContextFactoryTest.java | 158 +++ .../SecretValidatorExecutionServiceTest.java | 280 +++++ .../SecretValidatorWebRequestServiceTest.java | 157 +++ ...etValidatorConfigurationModelListTest.java | 55 + ...tValidatorConfigurationSpringBootTest.java | 39 + .../support/SarifValidationSupportTest.java | 122 +++ .../SecretValidatorHttpClientFactoryTest.java | 35 + .../invalid-files/invalid-sarif.txt | 1 + .../invalid-validator-config.txt | 1 + .../valid-files/test-config.json | 25 + .../valid-files/test-result.txt | 956 ++++++++++++++++++ settings.gradle | 5 +- 43 files changed, 3701 insertions(+), 1 deletion(-) create mode 100644 sechub-wrapper-secret-validator/README.adoc create mode 100644 sechub-wrapper-secret-validator/build.gradle create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/SecretValidatorApplication.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorCLI.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResult.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContext.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactory.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorCategorization.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequestHeader.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponse.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupport.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactory.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResultTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactoryTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-sarif.txt create mode 100644 sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt create mode 100644 sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-config.json create mode 100644 sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt diff --git a/gradle/projects.gradle b/gradle/projects.gradle index 8834099f63..fd00ca4356 100644 --- a/gradle/projects.gradle +++ b/gradle/projects.gradle @@ -46,6 +46,9 @@ projectType = [ to have dependency injection and access to some other spring boot parts */ project(':sechub-wrapper-checkmarx'), project(':sechub-wrapper-prepare'), + + /* special application to validate and categorize results of secret scans */ + project(':sechub-wrapper-secret-validator'), ], diff --git a/sechub-wrapper-secret-validator/README.adoc b/sechub-wrapper-secret-validator/README.adoc new file mode 100644 index 0000000000..24aecb81d2 --- /dev/null +++ b/sechub-wrapper-secret-validator/README.adoc @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +== Secret valdiation Wrapper + +This wrapper is a Spring Boot application, that is supposed to run on PDS solutions running performing secret scan. +After the secret scanning tool is done it will try to validate secrets found and enhance the SARIF report with a custom PropertyBag for each finding location. +It will add a custom severity with the key `secretscan.sechub.severity` and +one of the following values `["info", "unclassified", "low", "medium", "high", "critical"]` to the SARIF PropertyBag which contains a generic map for custom values. +This values can then be used by the `sechub-sereco` module to improve the severity categorization of a finding. + +=== Usage + +==== Start wrapper +The wrapper application is an executable jar and needs no command line arguments. +It can automatically use all +https://mercedes-benz.github.io/sechub/latest/sechub-product-delegation-server.html#launcher-scripts[standard PDS environment variables] +and following special mandatory environment variables: + +---- +SECRET_VALIDATOR_CONFIGFILE +---- + +[IMPORTANT] +==== +This files contains the configuration for each secret type, which basically tells to wrapper how to validate secrets of a certain type. +For each product a custom file is necessary, where you should use the SARIF `ruleId` to identify each configuration. +From the https://mercedes-benz.github.io/sechub/latest/sechub-product-delegation-server.html#launcher-scripts[standard PDS environment variables] +only the `PDS_JOB_RESULT_FILE` is mandatory because without a valid SARIF report from a secret scanning tool no validations can be done. +==== + +===== Configuration file example +```json +{ + "validatorConfigList" : [ { <1> + "ruleId" : "sarif-result-rule-id", <2> + "categorization" : { <3> + "defaultSeverity" : "high", + "validationFailedSeverity" : "medium", + "validationSuccessSeverity" : "critical" + }, + "requests" : [ { <4> + "proxyRequired" : true, + "url" : "https://api.example.com", + "headers" : [ { + "name" : "Authorization", + "valuePrefix" : "Bearer" + } ], + "expectedResponse" : { <5> + "httpStatus" : 200, + "contains" : { + "allOf" : [ "is", "there" ], + "oneOf" : [ "success", "authorized" ] + } + } + } ] + } ] +} +``` +<1> Define a list of configuration, for each type of secret identified by the rule id. +<2> The `ruleId` identifies this configuration so the requests defined in the later section are performed for each finding of this type. +<3> Your `categorization` configuration. If empty no categorization will be performed, otherwise: +- The `defaultSeverity` will be applied if no requests are defined but you for this type of secret. +- The `validationFailedSeverity` will be applied if all validation requests failed for this secret. +- The `validationSuccessSeverity` will be applied if the secret was successfully validated with one of the requests defined. +<4> The `requests` array defines all requests you know how to validate a secret of this certain type. +This is an array because for some secrets you might need to validate against multiple e.g. when you have AWS credentials found with your secret scan. +You might want to be able to check if it is valid for the public AWS or your internal AWS instances if you have some: +- With `proxyRequired` you can specify if the URL can only be accessed using a proxy server. +- With `url` you specify the URL the request will be performed to. +- With `headers` you specify the header `name` and `valuePrefix` if necessary for the secret found. +It is an array because it could be useful in the future. Currently the header is used for the secret because it is assumed to be a token send via HTTP header. +<5> The `expectedResponse` section contains information you expect on a request with a valid secret, +like a specific `httpStatus` code or the response body should contain `allOf` or `oneOf` certain strings. + + + +There exists also some optional variables: + +---- +SECRET_VALIDATOR_TRUSTALLCERTIFICATES +---- + +[TIP] +==== +When `SECRET_VALIDATOR_TRUSTALLCERTIFICATES` set to `true`, certificate errors on validation web requests will be ignored. +This can be useful, if you are in a environment that needs a proxy server to access certain URLs you have in your configuration. +==== + +===== Proxy configuration +Inside the configuration file each request has to configure if a proxy server is required to access this specific URL or not. +The wrapper is implemented to use the default proxy of the system properties. To configure a proxy, launch the application with the following arguments. +For each request it will then be decided if the proxy is needed or not according to the configuration file provided: + +---- +java -Dhttp.proxyHost=localhost -Dhttp.proxyPort=1234 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=1234 -jar secret-validation-wrapper.jar +---- \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/build.gradle b/sechub-wrapper-secret-validator/build.gradle new file mode 100644 index 0000000000..7f2e400e1f --- /dev/null +++ b/sechub-wrapper-secret-validator/build.gradle @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +/*============================================================================ +* Build file for subproject +* +* Root build file: "${rootProject.projectDir}/build.gradle" +* ============================================================================ +*/ +dependencies { + /* runtime */ + implementation project(':sechub-commons-pds') + + implementation library.sarif_210 + implementation library.springboot_starter_validation + + /* test */ + testImplementation project(':sechub-testframework') + + testImplementation spring_boot_dependency.junit_jupiter + testImplementation spring_boot_dependency.junit_jupiter_params + testImplementation spring_boot_dependency.mockito_core +} + +/* TODO janwinz: add versioning for release workflow */ \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/SecretValidatorApplication.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/SecretValidatorApplication.java new file mode 100644 index 0000000000..7cd8f00f64 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/SecretValidatorApplication.java @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SecretValidatorApplication { + + public static void main(String[] args) { + SpringApplication.run(SecretValidatorApplication.class, args); + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorCLI.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorCLI.java new file mode 100644 index 0000000000..f94910142a --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorCLI.java @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.cli; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import com.mercedesbenz.sechub.commons.TextFileWriter; +import com.mercedesbenz.sechub.commons.model.JSONConverter; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidatorExecutionService; +import com.mercedesbenz.sechub.wrapper.secret.validator.properties.SecretValidatorPDSJobResult; + +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +@Profile("!test") +@Component +public class SecretValidatorCLI implements CommandLineRunner { + + private static final Logger LOG = LoggerFactory.getLogger(SecretValidatorCLI.class); + + @Autowired + SecretValidatorExecutionService executionService; + + @Autowired + SecretValidatorPDSJobResult pdsJobResult; + + @Override + public void run(String... args) throws Exception { + LOG.info("Secret validator starting"); + TextFileWriter fileWriter = new TextFileWriter(); + try { + SarifSchema210 report = executionService.execute(); + + String json = JSONConverter.get().toJSON(report, true); + fileWriter.save(pdsJobResult.getFile(), json, true); + } catch (Exception e) { + LOG.error("Execution failed!", e); + System.exit(1); + } + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java new file mode 100644 index 0000000000..e492332395 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.net.http.HttpResponse; + +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorResponse; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorResponseContains; + +@Service +public class ResponseValidationService { + + public boolean isValidResponse(HttpResponse response, SecretValidatorResponse secretValidatorResponse) { + if (response == null || secretValidatorResponse == null) { + return false; + } + int expectedHttpStatus = secretValidatorResponse.getHttpStatus(); + // if no expected HTTP status code was configured inside the config we ignore it + if (expectedHttpStatus > 0) { + // no contains section specified, we return the result of the checked status + // code + if (hasNoContainsSection(secretValidatorResponse.getContains())) { + return expectedHttpStatus == response.statusCode(); + } + return containsExpectedSnippets(secretValidatorResponse.getContains(), response.body()); + } else { + // no contains section specified, we return false, since nothing was specified + // at all to check the response + if (hasNoContainsSection(secretValidatorResponse.getContains())) { + return false; + } + return containsExpectedSnippets(secretValidatorResponse.getContains(), response.body()); + } + } + + private boolean hasNoContainsSection(SecretValidatorResponseContains contains) { + if (contains == null) { + return true; + } + return contains.getAllOf().isEmpty() && contains.getOneOf().isEmpty(); + } + + private boolean containsExpectedSnippets(SecretValidatorResponseContains contains, String body) { + // body should not be null since contains section should be specified at this + // point + if (body == null || contains == null) { + return false; + } + + // at the point where this method gets called we require the contains section to + // be configured + if (hasNoContainsSection(contains)) { + return false; + } + + for (String substring : contains.getAllOf()) { + // all must be present + if (!body.contains(substring)) { + return false; + } + } + if (contains.getOneOf().isEmpty()) { + return true; + } + + for (String substring : contains.getOneOf()) { + // if one is present it is enough at this point + if (body.contains(substring)) { + return true; + } + } + // this should not be reached + return false; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResult.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResult.java new file mode 100644 index 0000000000..87aa0fa3d7 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResult.java @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +public class SecretValidationResult { + + private SecretValidationStatus validationStatus = SecretValidationStatus.NO_VALIDATION_CONFIGURED; + private String validatedByUrl; + + /** + * Get the status after validation of the current validated finding + * + * @return the validation status, never null + */ + public SecretValidationStatus getValidationStatus() { + return validationStatus; + } + + public void setValidationStatus(SecretValidationStatus validationStatus) { + if (validationStatus != null) { + this.validationStatus = validationStatus; + } + } + + public String getValidatedByUrl() { + return validatedByUrl; + } + + public void setValidatedByUrl(String validatedByUrl) { + this.validatedByUrl = validatedByUrl; + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java new file mode 100644 index 0000000000..6a324a39c0 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; + +import de.jcup.sarif_2_1_0.model.ArtifactContent; +import de.jcup.sarif_2_1_0.model.Region; + +@Service +public class SecretValidationService { + + private static final Logger LOG = LoggerFactory.getLogger(SecretValidationService.class); + + @Autowired + SecretValidatorWebRequestService webRequestService; + + public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { + ArtifactContent snippet = findingRegion.getSnippet(); + SecretValidationResult validationResult = new SecretValidationResult(); + if (snippet == null) { + LOG.warn("Cannot validate finding because the SARIF snippet is null."); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + return validationResult; + } + + String snippetText = snippet.getText(); + if (snippetText == null || snippetText.isBlank()) { + LOG.warn("Cannot validate finding because the SARIF snippet text is null or empty."); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + return validationResult; + } + return webRequestService.validateFinding(snippetText, requests, trustAllCertificates); + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java new file mode 100644 index 0000000000..356adff916 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +public enum SecretValidationStatus { + + VALID("The secret was successfully validated via a configured URL!"), + + INVALID("The secret could not be validated via any configured URL!"), + + NO_VALIDATION_CONFIGURED("No validation URLs are configured for this type of secret!"), + + SARIF_SNIPPET_NOT_SET("SARIF finding does not contain a valid snippet to validate!"),; + + private String description; + + private SecretValidationStatus(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java new file mode 100644 index 0000000000..6ac55069c3 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys.*; + +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorCategorization; + +import de.jcup.sarif_2_1_0.model.PropertyBag; +import de.jcup.sarif_2_1_0.model.Region; + +@Service +public class SecretValidatorCategorizationService { + + public void categorizeFindingByRegion(SecretValidationResult validationResult, Region findingRegion, SecretValidatorCategorization categorization) { + if (categorization == null || categorization.isEmpty()) { + return; + } + SecretValidationStatus validationStatus = validationResult.getValidationStatus(); + PropertyBag properties = new PropertyBag(); + + switch (validationStatus) { + case VALID: + properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getValidationSuccessSeverity()); + String validatedByUrl = validationResult.getValidatedByUrl(); + if (validatedByUrl != null) { + properties.setAdditionalProperty(SECRETSCAN_VALIDATED_BY_URL.getKey(), validatedByUrl); + } + break; + case INVALID: + properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getValidationFailedSeverity()); + break; + case NO_VALIDATION_CONFIGURED: + case SARIF_SNIPPET_NOT_SET: + default: + properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getDefaultSeverity()); + } + findingRegion.setProperties(properties); + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContext.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContext.java new file mode 100644 index 0000000000..a2c6a4589a --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContext.java @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModel; + +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +public class SecretValidatorExecutionContext { + + private SarifSchema210 sarifReport; + + private Map validatorConfiguration = new HashMap<>(); + + private boolean trustAllCertificates; + + private SecretValidatorExecutionContext() { + } + + public SarifSchema210 getSarifReport() { + return sarifReport; + } + + public Map getValidatorConfiguration() { + return Collections.unmodifiableMap(validatorConfiguration); + } + + public boolean isTrustAllCertificates() { + return trustAllCertificates; + } + + public static SecretValidatorExecutionContextBuilder builder() { + return new SecretValidatorExecutionContextBuilder(); + } + + public static class SecretValidatorExecutionContextBuilder { + + private SarifSchema210 sarifReport; + + private Map validatorConfiguration = new HashMap<>(); + + private boolean trustAllCertificates; + + public SecretValidatorExecutionContextBuilder setSarifReport(SarifSchema210 report) { + this.sarifReport = report; + return this; + } + + public SecretValidatorExecutionContextBuilder setValidatorConfiguration(Map validatorConfiguration) { + this.validatorConfiguration = validatorConfiguration; + return this; + } + + public SecretValidatorExecutionContextBuilder setTrustAllCertificates(boolean trustAllCertificates) { + this.trustAllCertificates = trustAllCertificates; + return this; + } + + public SecretValidatorExecutionContext build() { + SecretValidatorExecutionContext secretValidatorExecutionContext = new SecretValidatorExecutionContext(); + secretValidatorExecutionContext.sarifReport = this.sarifReport; + secretValidatorExecutionContext.validatorConfiguration = this.validatorConfiguration; + secretValidatorExecutionContext.trustAllCertificates = this.trustAllCertificates; + + return secretValidatorExecutionContext; + } + + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactory.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactory.java new file mode 100644 index 0000000000..1cb1b3069c --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactory.java @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.mercedesbenz.sechub.commons.TextFileReader; +import com.mercedesbenz.sechub.commons.model.JSONConverter; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModel; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModelList; +import com.mercedesbenz.sechub.wrapper.secret.validator.properties.SecretValidatorPDSJobResult; +import com.mercedesbenz.sechub.wrapper.secret.validator.properties.SecretValidatorProperties; + +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +@Component +public class SecretValidatorExecutionContextFactory { + private static final Logger LOG = LoggerFactory.getLogger(SecretValidatorExecutionContextFactory.class); + + @Autowired + SecretValidatorPDSJobResult pdsResult; + + @Autowired + SecretValidatorProperties properties; + + TextFileReader reader = new TextFileReader(); + + public SecretValidatorExecutionContext create() { + LOG.info("Loading SARIF model from secret scan."); + SarifSchema210 report = createSarifReport(pdsResult.getFile()); + + LOG.info("Loading validator configuration for this pds solution."); + Map ruleConfigurations = createRuleConfigurations(properties.getConfigFile()); + + /* @formatter:off */ + SecretValidatorExecutionContext context = + SecretValidatorExecutionContext.builder() + .setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations) + .setTrustAllCertificates(properties.isTrustAllCertificates()) + .build(); + /* @formatter:on */ + return context; + } + + private SarifSchema210 createSarifReport(File pdsResultFile) { + if (!pdsResultFile.exists()) { + throw new IllegalStateException("PDS job result file: " + pdsResultFile + " does not exist!"); + } else if (!pdsResultFile.canRead()) { + throw new IllegalStateException("PDS job result file: " + pdsResultFile + " is not readable!"); + } + + try { + String sarifReportJson = reader.loadTextFile(pdsResultFile); + return JSONConverter.get().fromJSON(SarifSchema210.class, sarifReportJson); + } catch (Exception e) { + throw new IllegalStateException("Creating SARIF report model from: " + pdsResultFile + " failed!", e); + } + } + + private Map createRuleConfigurations(File validatorConfigFile) { + if (!validatorConfigFile.exists()) { + throw new IllegalStateException("Secret validator configuration file: " + validatorConfigFile + " does not exist!"); + } else if (!validatorConfigFile.canRead()) { + throw new IllegalStateException("Secret validator configuration file: " + validatorConfigFile + " is not readable!"); + } + + try { + String validatorConfigJson = reader.loadTextFile(validatorConfigFile); + SecretValidatorConfigurationModelList configurationDataList = JSONConverter.get().fromJSON(SecretValidatorConfigurationModelList.class, + validatorConfigJson); + + Map ruleConfigurations = new HashMap<>(); + for (SecretValidatorConfigurationModel configData : configurationDataList.getValidatorConfigList()) { + ruleConfigurations.put(configData.getRuleId(), configData); + } + return ruleConfigurations; + } catch (Exception e) { + throw new IllegalStateException("Creating secret validator configuration from: " + validatorConfigFile + " failed!", e); + } + + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java new file mode 100644 index 0000000000..fa31f36446 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorCategorization; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModel; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifValidationSupport; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.Region; +import de.jcup.sarif_2_1_0.model.Result; +import de.jcup.sarif_2_1_0.model.Run; +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +@Service +public class SecretValidatorExecutionService { + private static final Logger LOG = LoggerFactory.getLogger(SecretValidatorExecutionService.class); + + @Autowired + SecretValidatorExecutionContextFactory contextFactory; + + @Autowired + SecretValidationService validationService; + + @Autowired + SecretValidatorCategorizationService categorizationService; + + @Autowired + SarifValidationSupport sarifValidationSupport; + + public SarifSchema210 execute() { + SecretValidatorExecutionContext executionContext = contextFactory.create(); + Map validatorConfiguration = executionContext.getValidatorConfiguration(); + + // generally for secret scans it is only one run + List runs = executionContext.getSarifReport().getRuns(); + for (Run run : runs) { + List findings = run.getResults(); + for (Result finding : findings) { + if (!sarifValidationSupport.findingCanBeValidated(finding)) { + continue; + } + SecretValidatorConfigurationModel config = validatorConfiguration.get(finding.getRuleId()); + if (config == null) { + LOG.info("No config found to validate findings of rule: {}", finding.getRuleId()); + continue; + } + SecretValidatorCategorization categorization = config.getCategorization(); + if (categorization == null || categorization.isEmpty()) { + LOG.info("No config found to categorize findings of rule: {}", finding.getRuleId()); + continue; + } + for (Location location : finding.getLocations()) { + if (!sarifValidationSupport.findingLocationCanBeValidated(location)) { + continue; + } + Region findingRegion = location.getPhysicalLocation().getRegion(); + SecretValidationResult validationResult = validationService.validateFindingByRegion(findingRegion, config.getRequests(), + executionContext.isTrustAllCertificates()); + categorizationService.categorizeFindingByRegion(validationResult, findingRegion, config.getCategorization()); + } + } + } + return executionContext.getSarifReport(); + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java new file mode 100644 index 0000000000..963cc0e4cf --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequestHeader; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SecretValidatorHttpClientFactory; + +@Service +public class SecretValidatorWebRequestService { + + private static final Logger LOG = LoggerFactory.getLogger(SecretValidatorWebRequestService.class); + + @Autowired + SecretValidatorHttpClientFactory httpClientFactory; + + @Autowired + ResponseValidationService responseValidationService; + + public SecretValidationResult validateFinding(String snippetText, List requests, boolean trustAllCertificates) { + HttpClient proxyHttpClient = httpClientFactory.createProxyHttpClient(trustAllCertificates); + HttpClient directHttpClient = httpClientFactory.createDirectHttpClient(trustAllCertificates); + + if (snippetText == null || snippetText.isBlank()) { + LOG.warn("Cannot validate finding because the SARIF snippet text is null or empty."); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + return validationResult; + } + if (requests.isEmpty()) { + LOG.info("Configured requests for this finding empty! Finding cannot be validated!"); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.NO_VALIDATION_CONFIGURED); + return validationResult; + } + int validationsPerformed = 0; + for (SecretValidatorRequest request : requests) { + if (request == null) { + LOG.info("Request config is null! Entry will be skipped."); + continue; + } + if (request.getUrl() == null) { + LOG.info("Request config URL is null! Entry will be skipped."); + continue; + } + HttpResponse response = null; + try { + HttpRequest httpRequest = createHttpRequest(snippetText, request); + if (request.isProxyRequired()) { + response = proxyHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + } else { + response = directHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + } + } catch (IOException | InterruptedException e) { + LOG.error("Performing validation request failed!"); + } + validationsPerformed++; + if (responseValidationService.isValidResponse(response, request.getExpectedResponse())) { + LOG.info("Finding is valid!"); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.VALID); + validationResult.setValidatedByUrl(request.getUrl().toString()); + return validationResult; + } + } + if (validationsPerformed < 1) { + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.NO_VALIDATION_CONFIGURED); + return validationResult; + } + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.INVALID); + return validationResult; + } + + private HttpRequest createHttpRequest(String snippetText, SecretValidatorRequest request) { + List headers = new ArrayList<>(); + for (SecretValidatorRequestHeader header : request.getHeaders()) { + String value = snippetText; + if (header.getValuePrefix() != null) { + value = header.getValuePrefix() + " " + snippetText; + } + headers.add(header.getName()); + headers.add(value); + } + String[] headersAsArrays = new String[headers.size()]; + try { + /* @formatter:off */ + return HttpRequest.newBuilder() + .headers(headers.toArray(headersAsArrays)) + .uri(request.getUrl().toURI()) + .GET() + .build(); + /* @formatter:on */ + } catch (URISyntaxException e) { + LOG.error("Request URL {} is invalid!", request.getUrl()); + throw new IllegalArgumentException(e); + } + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorCategorization.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorCategorization.java new file mode 100644 index 0000000000..988d6ed276 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorCategorization.java @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorCategorization { + + private String defaultSeverity; + private String validationFailedSeverity; + private String validationSuccessSeverity; + + public String getDefaultSeverity() { + return defaultSeverity; + } + + public void setDefaultSeverity(String defaultSeverity) { + this.defaultSeverity = defaultSeverity; + } + + public String getValidationFailedSeverity() { + return validationFailedSeverity; + } + + public void setValidationFailedSeverity(String validationFailedSeverity) { + this.validationFailedSeverity = validationFailedSeverity; + } + + public String getValidationSuccessSeverity() { + return validationSuccessSeverity; + } + + public void setValidationSuccessSeverity(String validationSuccessSeverity) { + this.validationSuccessSeverity = validationSuccessSeverity; + } + + /** + * Check if no severities were configured for. + * + * @return true, if all fields are null and therefore not + * configured and false, if any of the fields is set to a value other + * than null. + */ + @JsonIgnore + public boolean isEmpty() { + return defaultSeverity == null && validationFailedSeverity == null && validationSuccessSeverity == null; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java new file mode 100644 index 0000000000..ab2573011a --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorConfigurationModel { + + private String ruleId; + private SecretValidatorCategorization categorization; + private List requests = new ArrayList<>(); + + public String getRuleId() { + return ruleId; + } + + public void setRuleId(String ruleId) { + this.ruleId = ruleId; + } + + public SecretValidatorCategorization getCategorization() { + return categorization; + } + + public void setCategorization(SecretValidatorCategorization categorization) { + this.categorization = categorization; + } + + public List getRequests() { + return Collections.unmodifiableList(requests); + } + + public void setRequests(List requests) { + if (requests != null) { + this.requests = requests; + } + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java new file mode 100644 index 0000000000..ab9da9281b --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorConfigurationModelList { + + private List validatorConfigList = new ArrayList<>(); + + public List getValidatorConfigList() { + return Collections.unmodifiableList(validatorConfigList); + } + + public void setDataList(List validatorConfigList) { + if (validatorConfigList != null) { + this.validatorConfigList = validatorConfigList; + } + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java new file mode 100644 index 0000000000..9a4db101db --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorRequest { + + private URL url; + private boolean proxyRequired; + private List headers = new ArrayList<>(); + private SecretValidatorResponse expectedResponse; + + public URL getUrl() { + return url; + } + + public void setUrl(URL url) { + this.url = url; + } + + public boolean isProxyRequired() { + return proxyRequired; + } + + public void setProxyRequired(boolean proxyRequired) { + this.proxyRequired = proxyRequired; + } + + public List getHeaders() { + return Collections.unmodifiableList(headers); + } + + public void setHeaders(List headers) { + if (headers != null) { + this.headers = headers; + } + } + + public SecretValidatorResponse getExpectedResponse() { + return expectedResponse; + } + + public void setExpectedResponse(SecretValidatorResponse expectedResponse) { + this.expectedResponse = expectedResponse; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequestHeader.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequestHeader.java new file mode 100644 index 0000000000..5435419938 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequestHeader.java @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorRequestHeader { + + private String name; + private String valuePrefix; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValuePrefix() { + return valuePrefix; + } + + public void setValuePrefix(String valuePrefix) { + this.valuePrefix = valuePrefix; + } +} \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponse.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponse.java new file mode 100644 index 0000000000..9f023235c4 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponse.java @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorResponse { + + private int httpStatus; + private SecretValidatorResponseContains contains; + + public int getHttpStatus() { + return httpStatus; + } + + public void setHttpStatus(int httpStatus) { + this.httpStatus = httpStatus; + } + + public SecretValidatorResponseContains getContains() { + return contains; + } + + public void setContains(SecretValidatorResponseContains contains) { + this.contains = contains; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java new file mode 100644 index 0000000000..7ae8fdae0f --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class SecretValidatorResponseContains { + + private List allOf = new ArrayList<>(); + private List oneOf = new ArrayList<>(); + + public List getAllOf() { + return Collections.unmodifiableList(allOf); + } + + public void setAllOf(List allOf) { + if (allOf != null) { + this.allOf = allOf; + } + } + + public List getOneOf() { + return Collections.unmodifiableList(oneOf); + } + + public void setOneOf(List oneOf) { + if (oneOf != null) { + this.oneOf = oneOf; + } + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java new file mode 100644 index 0000000000..7b86405978 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import java.io.File; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import org.springframework.validation.annotation.Validated; + +import jakarta.validation.constraints.NotNull; + +@Validated +@ConfigurationProperties(prefix = "pds.job.result") +@Component +public class SecretValidatorPDSJobResult { + + @NotNull + private File file; + + public File getFile() { + return file; + } + + public void setFile(File file) { + this.file = file; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java new file mode 100644 index 0000000000..96a65fd23a --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import java.io.File; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import org.springframework.validation.annotation.Validated; + +import jakarta.validation.constraints.NotNull; + +@Validated +@ConfigurationProperties(prefix = "secret.validator") +@Component +public class SecretValidatorProperties { + + @NotNull + private File configFile; + + private boolean trustAllCertificates; + + public File getConfigFile() { + return configFile; + } + + public void setConfigFile(File configFile) { + this.configFile = configFile; + } + + public boolean isTrustAllCertificates() { + return trustAllCertificates; + } + + public void setTrustAllCertificates(boolean trustAllCertificates) { + this.trustAllCertificates = trustAllCertificates; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java new file mode 100644 index 0000000000..380edcdb9d --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.support; + +/* + * If this needs to get changed, make sure to change + * com.mercedesbenz.sechub.sereco.importer.SarifImporterKeys accordingly + */ +public enum SarifImporterKeys { + + SECRETSCAN_SECHUB_SEVERITY("secretscan.sechub.severity", "The key for the sechub severity which is more precise than the SARIF Level enum."), + + SECRETSCAN_VALIDATED_BY_URL("secretscan.validated.by.url", "The key for the URL the secret was validated with."), + + ; + + private String key; + private String description; + + private SarifImporterKeys(String key, String description) { + this.key = key; + this.description = description; + } + + public String getKey() { + return key; + } + + public String getDescription() { + return description; + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupport.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupport.java new file mode 100644 index 0000000000..a55ed48903 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupport.java @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.support; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.PhysicalLocation; +import de.jcup.sarif_2_1_0.model.Region; +import de.jcup.sarif_2_1_0.model.Result; + +@Component +public class SarifValidationSupport { + + private static final Logger LOG = LoggerFactory.getLogger(SarifValidationSupport.class); + + public boolean findingCanBeValidated(Result finding) { + if (finding == null) { + LOG.info("Finding entry in SARIF report is null. Finding validation will be skipped."); + return false; + } + List locations = finding.getLocations(); + if (locations == null || locations.isEmpty()) { + LOG.info("Finding locations list in sarif report are null or empty. Finding validation will be skipped."); + return false; + } + return true; + } + + public boolean findingLocationCanBeValidated(Location location) { + if (location == null) { + LOG.info("Finding location entry in SARIF report is null. Finding validation will be skipped."); + return false; + } + PhysicalLocation physicalLocation = location.getPhysicalLocation(); + if (physicalLocation == null) { + LOG.info("Finding physical location entry in SARIF report is null. Finding validation will be skipped."); + return false; + } + Region findingRegion = physicalLocation.getRegion(); + if (findingRegion == null) { + LOG.info("Finding physical location region entry in SARIF report is null. Finding validation will be skipped."); + return false; + } + return true; + } +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactory.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactory.java new file mode 100644 index 0000000000..7b1f5ac56f --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactory.java @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.support; + +import java.net.ProxySelector; +import java.net.http.HttpClient; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.springframework.stereotype.Component; + +@Component +public class SecretValidatorHttpClientFactory { + private static final String TLS = "TLS"; + + public HttpClient createProxyHttpClient(boolean trustAllCertificates) { + if (trustAllCertificates) { + TrustManager pseudoTrustManager = createTrustManagerWhichTrustsEveryBody(); + SSLContext sslContext = createSSLContextForTrustManager(pseudoTrustManager); + /* @formatter:off */ + return HttpClient.newBuilder() + .proxy(ProxySelector.getDefault()) + .sslContext(sslContext) + .build(); + /* @formatter:on */ + } else { + /* @formatter:off */ + return HttpClient.newBuilder() + .proxy(ProxySelector.getDefault()) + .build(); + /* @formatter:on */ + } + } + + public HttpClient createDirectHttpClient(boolean trustAllCertificates) { + if (trustAllCertificates) { + TrustManager pseudoTrustManager = createTrustManagerWhichTrustsEveryBody(); + SSLContext sslContext = createSSLContextForTrustManager(pseudoTrustManager); + /* @formatter:off */ + return HttpClient.newBuilder() + .sslContext(sslContext) + .build(); + /* @formatter:on */ + } else { + return HttpClient.newBuilder().build(); + } + } + + private X509TrustManager createTrustManagerWhichTrustsEveryBody() { + return new X509TrustManager() { + + private X509Certificate[] emptyCertificatesArray = new X509Certificate[] {}; + + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + /* we do not check the client - we trust all */ + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + /* we do not check the server - we trust all */ + } + + public X509Certificate[] getAcceptedIssuers() { + return emptyCertificatesArray; + } + }; + } + + private SSLContext createSSLContextForTrustManager(TrustManager trustManager) { + SSLContext sslContext = null; + try { + sslContext = SSLContext.getInstance(TLS); + sslContext.init(null, new TrustManager[] { trustManager }, null); + + return sslContext; + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new IllegalStateException("Was not able to create trust all context", e); + } + + } +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java new file mode 100644 index 0000000000..5bc1b80591 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.cli; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidatorExecutionService; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.Region; +import de.jcup.sarif_2_1_0.model.Result; +import de.jcup.sarif_2_1_0.model.Run; +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +@EnableConfigurationProperties +@TestPropertySource(properties = { "secret.validator.config-file=src/test/resources/config-test-files/valid-files/test-config.json", + "secret.validator.trust-all-certificates=false", "pds.job.result.file=src/test/resources/config-test-files/valid-files/test-result.txt" }) +@ActiveProfiles("test") +class SecretValidatorSpringBootTest { + + @Autowired + SecretValidatorExecutionService executionService; + + @Test + void execution_service_with_correct_configuration_without_validation_categprizes_findings_with_default_configured() { + /* execute */ + SarifSchema210 report = executionService.execute(); + + /* test */ + Run run = report.getRuns().get(0); + for (Result finding : run.getResults()) { + Location location = finding.getLocations().get(0); + Region region = location.getPhysicalLocation().getRegion(); + Map additionalProperties = region.getProperties().getAdditionalProperties(); + String sechubSeverity = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey()); + String validatedByUrl = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_VALIDATED_BY_URL.getKey()); + + // expected severity is the severity from the validation failed config + assertEquals("medium", sechubSeverity); + + // since it was not validated we expected no value for + // SECRETSCAN_VALIDATED_BY_URL + assertEquals(null, validatedByUrl); + } + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java new file mode 100644 index 0000000000..5bc3fa0d1d --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java @@ -0,0 +1,245 @@ +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorResponse; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorResponseContains; + +class ResponseValidationServiceTest { + + private ResponseValidationService serviceToTest = new ResponseValidationService(); + + @Test + void response_is_null_results_in_validation_is_false() { + /* execute */ + boolean isValid = serviceToTest.isValidResponse(null, new SecretValidatorResponse()); + + /* test */ + assertFalse(isValid); + } + + @Test + void validator_response_config_is_null_results_in_validation_is_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, null); + + /* test */ + assertFalse(isValid); + } + + @ParameterizedTest + @ValueSource(ints = { 200, 302, 404, 500 }) + void validator_response_config_status_code_configured_and_contains_is_null_results_in_http_status_code_check(int responseCode) { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(responseCode); + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + secretValidatorResponse.setHttpStatus(302); + secretValidatorResponse.setContains(null); + + // with this configuration we expect the satuscodes being compared, + // since nothing else is configured inside the SecretValidatorResponse + boolean expectedResponse = response.statusCode() == secretValidatorResponse.getHttpStatus(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, secretValidatorResponse); + + /* test */ + assertEquals(expectedResponse, isValid); + } + + @ParameterizedTest + @ValueSource(ints = { 200, 302, 404, 500 }) + void validator_response_config_status_code_configured_and_contains_is_empty_results_in_http_status_code_check(int responseCode) { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(responseCode); + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + secretValidatorResponse.setHttpStatus(302); + secretValidatorResponse.setContains(new SecretValidatorResponseContains()); + + // with this configuration we expect the satuscodes being compared, + // since nothing else is configured inside the SecretValidatorResponse + boolean expectedResponse = response.statusCode() == secretValidatorResponse.getHttpStatus(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, secretValidatorResponse); + + /* test */ + assertEquals(expectedResponse, isValid); + } + + @Test + void validator_response_config_status_code_not_configured_and_contains_is_null_results_in_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + secretValidatorResponse.setContains(null); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, secretValidatorResponse); + + /* test */ + assertFalse(isValid); + } + + @Test + void validator_response_config_status_code_not_configured_and_contains_is_empty_results_in_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + secretValidatorResponse.setContains(new SecretValidatorResponseContains()); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, secretValidatorResponse); + + /* test */ + assertFalse(isValid); + } + + @Test + void response_body_is_null_with_statuscode_configured_results_in_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn(null); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithAllOfSetup(); + responseConfig.setHttpStatus(200); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertFalse(isValid); + } + + @Test + void response_body_is_null_without_statuscode_configured_results_in_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn(null); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithAllOfSetup(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertFalse(isValid); + } + + @Test + void response_body_contains_all_of_expected_substings_returns_true() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn("OK is authorized"); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithAllOfSetup(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertTrue(isValid); + } + + @Test + void response_body_does_not_contain_all_of_expected_substings_returns_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn("OK"); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithAllOfSetup(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertFalse(isValid); + } + + @Test + void response_body_contains_one_of_expected_substings_returns_true() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn("OK"); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithOneOfSetup(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertTrue(isValid); + } + + @Test + void response_body_does_not_contain_one_of_expected_substings_returns_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(200); + when(response.body()).thenReturn("Authentication successful!"); + SecretValidatorResponse responseConfig = createSecretValidatorResponseWithAllOfSetup(); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, responseConfig); + + /* test */ + assertFalse(isValid); + } + + private SecretValidatorResponse createSecretValidatorResponseWithAllOfSetup() { + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + SecretValidatorResponseContains contains = new SecretValidatorResponseContains(); + List allOf = new ArrayList<>(); + allOf.add("OK"); + allOf.add("authorized"); + + contains.setAllOf(allOf); + secretValidatorResponse.setContains(contains); + + return secretValidatorResponse; + } + + private SecretValidatorResponse createSecretValidatorResponseWithOneOfSetup() { + SecretValidatorResponse secretValidatorResponse = new SecretValidatorResponse(); + SecretValidatorResponseContains contains = new SecretValidatorResponseContains(); + List oneOf = new ArrayList<>(); + oneOf.add("OK"); + oneOf.add("authorized"); + + contains.setOneOf(oneOf); + secretValidatorResponse.setContains(contains); + + return secretValidatorResponse; + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResultTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResultTest.java new file mode 100644 index 0000000000..76a116ba27 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationResultTest.java @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +class SecretValidationResultTest { + + @ParameterizedTest + @EnumSource(SecretValidationStatus.class) + void setting_a_new_value_results_in_the_specified_value_being_set(SecretValidationStatus status) { + /* prepare */ + SecretValidationResult validationResult = new SecretValidationResult(); + + /* execute */ + validationResult.setValidationStatus(status); + + /* test */ + assertEquals(status, validationResult.getValidationStatus()); + + } + + @Test + void setting_null_results_in_the_default_value_staying_set() { + /* prepare */ + SecretValidationResult validationResult = new SecretValidationResult(); + + /* execute */ + validationResult.setValidationStatus(null); + + /* test */ + assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java new file mode 100644 index 0000000000..0b0b66d82e --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; + +import de.jcup.sarif_2_1_0.model.ArtifactContent; +import de.jcup.sarif_2_1_0.model.Region; + +class SecretValidationServiceTest { + + private SecretValidationService serviceToTest; + + private SecretValidatorWebRequestService webRequestService; + + @BeforeEach + void beforeEach() { + serviceToTest = new SecretValidationService(); + + webRequestService = mock(SecretValidatorWebRequestService.class); + serviceToTest.webRequestService = webRequestService; + + } + + @Test + void region_snippet_is_null_returns_expected_validation_result() { + /* prepare */ + Region region = new Region(); + List requests = new ArrayList<>(); + when(webRequestService.validateFinding(null, requests, true)).thenReturn(new SecretValidationResult()); + + /* execute */ + SecretValidationResult validateFindingByRegion = serviceToTest.validateFindingByRegion(region, requests, true); + + /* test */ + verify(webRequestService, never()).validateFinding(null, requests, true); + assertEquals(SecretValidationStatus.SARIF_SNIPPET_NOT_SET, validateFindingByRegion.getValidationStatus()); + + } + + @Test + void region_snippet_text_is_null_returns_expected_validation_result() { + /* prepare */ + Region region = new Region(); + region.setSnippet(new ArtifactContent()); + List requests = new ArrayList<>(); + when(webRequestService.validateFinding(region.getSnippet().getText(), requests, true)).thenReturn(new SecretValidationResult()); + + /* execute */ + SecretValidationResult validateFindingByRegion = serviceToTest.validateFindingByRegion(region, requests, true); + + /* test */ + verify(webRequestService, never()).validateFinding(region.getSnippet().getText(), requests, true); + assertEquals(SecretValidationStatus.SARIF_SNIPPET_NOT_SET, validateFindingByRegion.getValidationStatus()); + + } + + @Test + void region_snippet_text_is_blank_returns_expected_validation_result() { + /* prepare */ + Region region = new Region(); + ArtifactContent snippet = new ArtifactContent(); + snippet.setText(" "); + region.setSnippet(snippet); + List requests = new ArrayList<>(); + when(webRequestService.validateFinding(region.getSnippet().getText(), requests, true)).thenReturn(new SecretValidationResult()); + + /* execute */ + SecretValidationResult validateFindingByRegion = serviceToTest.validateFindingByRegion(region, requests, true); + + /* test */ + verify(webRequestService, never()).validateFinding(region.getSnippet().getText(), requests, true); + assertEquals(SecretValidationStatus.SARIF_SNIPPET_NOT_SET, validateFindingByRegion.getValidationStatus()); + + } + + @Test + void region_snippet_text_is_set_results_in_web_request_service_called_once() { + /* prepare */ + Region region = new Region(); + ArtifactContent snippet = new ArtifactContent(); + snippet.setText("secret"); + region.setSnippet(snippet); + List requests = new ArrayList<>(); + when(webRequestService.validateFinding(region.getSnippet().getText(), requests, true)).thenReturn(new SecretValidationResult()); + + /* execute */ + SecretValidationResult validateFindingByRegion = serviceToTest.validateFindingByRegion(region, requests, true); + + /* test */ + verify(webRequestService, times(1)).validateFinding(region.getSnippet().getText(), requests, true); + assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validateFindingByRegion.getValidationStatus()); + + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java new file mode 100644 index 0000000000..5fe1df1ce0 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.net.MalformedURLException; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorCategorization; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys; + +import de.jcup.sarif_2_1_0.model.PropertyBag; +import de.jcup.sarif_2_1_0.model.Region; + +class SecretValidatorCategorizationServiceTest { + + private SecretValidatorCategorizationService serviceToTest = new SecretValidatorCategorizationService(); + + @Test + void categorization_config_is_null_results_in_property_bag_being_empty() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, null); + + /* test */ + assertNull(findingRegion.getProperties()); + } + + @Test + void categorization_config_is_empty_results_in_property_bag_being_empty() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + assertNull(findingRegion.getProperties()); + } + + @Test + void validation_result_valid_results_in_configured_categorization() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.VALID); + validationResult.setValidatedByUrl("http://api.example.com"); + + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setValidationSuccessSeverity("critical"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(2, additionalProperties.size()); + assertEquals(categorization.getValidationSuccessSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals("http://api.example.com", additionalProperties.get(SarifImporterKeys.SECRETSCAN_VALIDATED_BY_URL.getKey())); + } + + @Test + void validation_result_invalid_results_in_configured_categorization() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.INVALID); + + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setValidationFailedSeverity("low"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(1, additionalProperties.size()); + assertEquals(categorization.getValidationFailedSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + } + + @Test + void validation_result_with_no_validation_configured_results_in_default_categorization() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.NO_VALIDATION_CONFIGURED); + + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setDefaultSeverity("medium"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(1, additionalProperties.size()); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + } + + @Test + void validation_result_with_sarif_snippet_not_set_results_in_default_categorization() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setDefaultSeverity("medium"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(1, additionalProperties.size()); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + } + + @Test + void validation_empty_results_in_default_categorization() { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setDefaultSeverity("medium"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(1, additionalProperties.size()); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + } + + @Test + void validation_result_valid_results_in_severity_value_is_null() throws MalformedURLException { + /* prepare */ + Region findingRegion = new Region(); + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.VALID); + + // we do not configure a successful validation category here + // this should not happen because we create the validation config file step by + // step, + // but we need to make sure this will not fail in any case + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + categorization.setValidationFailedSeverity("low"); + + /* execute */ + serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + + /* test */ + PropertyBag properties = findingRegion.getProperties(); + Map additionalProperties = properties.getAdditionalProperties(); + + assertEquals(1, additionalProperties.size()); + assertNull(additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java new file mode 100644 index 0000000000..083ef07156 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.wrapper.secret.validator.properties.SecretValidatorPDSJobResult; +import com.mercedesbenz.sechub.wrapper.secret.validator.properties.SecretValidatorProperties; + +class SecretValidatorExecutionContextFactoryTest { + + private SecretValidatorExecutionContextFactory factoryToTest; + + @BeforeEach + void beforeEach() { + factoryToTest = new SecretValidatorExecutionContextFactory(); + } + + @Test + void not_existing_pds_job_result_file_throws_exception() { + /* prepare */ + File notExisting = mock(File.class); + when(notExisting.exists()).thenReturn(false); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(notExisting); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("PDS job result file: " + notExisting + " does not exist!", exception.getMessage()); + } + + @Test + void not_readable_pds_job_result_file_throws_exception() { + /* prepare */ + File notReadable = mock(File.class); + when(notReadable.exists()).thenReturn(true); + when(notReadable.canRead()).thenReturn(false); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(notReadable); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("PDS job result file: " + notReadable + " is not readable!", exception.getMessage()); + } + + @Test + void invalid_sarif_pds_job_result_file_throws_exception() { + /* prepare */ + File invalidFile = new File("src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(invalidFile); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("Creating SARIF report model from: " + invalidFile + " failed!", exception.getMessage()); + } + + @Test + void not_existing_secret_validator_config_file_throws_exception() { + /* prepare */ + // we need a valid Sarif report because the pds job result is read first + File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(validFile); + + File notExisting = mock(File.class); + when(notExisting.exists()).thenReturn(false); + SecretValidatorProperties properties = new SecretValidatorProperties(); + properties.setConfigFile(notExisting); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.properties = properties; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("Secret validator configuration file: " + notExisting + " does not exist!", exception.getMessage()); + } + + @Test + void not_readable_secret_validator_config_file_throws_exception() { + /* prepare */ + // we need a valid Sarif report because the pds job result is read first + File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(validFile); + + File notReadable = mock(File.class); + when(notReadable.exists()).thenReturn(true); + when(notReadable.canRead()).thenReturn(false); + SecretValidatorProperties properties = new SecretValidatorProperties(); + properties.setConfigFile(notReadable); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.properties = properties; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("Secret validator configuration file: " + notReadable + " is not readable!", exception.getMessage()); + } + + @Test + void invalid_secret_validator_config_file_throws_exception() { + /* prepare */ + // we need a valid Sarif report because the pds job result is read first + File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(validFile); + + File invalidFile = new File("src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"); + SecretValidatorProperties properties = new SecretValidatorProperties(); + properties.setConfigFile(invalidFile); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.properties = properties; + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); + assertEquals("Creating secret validator configuration from: " + invalidFile + " failed!", exception.getMessage()); + } + + @Test + void valid_files_return_valid_execution_context() { + /* prepare */ + // we need a valid Sarif report because the pds job result is read first + File validSarifReportFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + secretValidatorPDSJobResult.setFile(validSarifReportFile); + + File validSecretValidatorCOnfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); + SecretValidatorProperties properties = new SecretValidatorProperties(); + properties.setConfigFile(validSecretValidatorCOnfigFile); + + factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.properties = properties; + + /* execute */ + SecretValidatorExecutionContext secretValidatorExecutionContext = factoryToTest.create(); + + assertNotNull(secretValidatorExecutionContext); + assertNotNull(secretValidatorExecutionContext.getSarifReport()); + assertEquals(1, secretValidatorExecutionContext.getValidatorConfiguration().size()); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java new file mode 100644 index 0000000000..4a809790bd --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java @@ -0,0 +1,280 @@ +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.commons.model.JSONConverter; +import com.mercedesbenz.sechub.test.TestFileReader; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorCategorization; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModel; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorConfigurationModelList; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifValidationSupport; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.Result; +import de.jcup.sarif_2_1_0.model.Run; +import de.jcup.sarif_2_1_0.model.SarifSchema210; + +class SecretValidatorExecutionServiceTest { + + private SecretValidatorExecutionService serviceToTest; + + private SecretValidatorExecutionContextFactory contextFactory; + private SecretValidationService validationService; + private SecretValidatorCategorizationService categorizationService; + private SarifValidationSupport sarifValidationSupport; + + @BeforeEach + void beforeEach() { + serviceToTest = new SecretValidatorExecutionService(); + + contextFactory = mock(SecretValidatorExecutionContextFactory.class); + validationService = mock(SecretValidationService.class); + categorizationService = mock(SecretValidatorCategorizationService.class); + sarifValidationSupport = mock(SarifValidationSupport.class); + + serviceToTest.contextFactory = contextFactory; + serviceToTest.validationService = validationService; + serviceToTest.categorizationService = categorizationService; + serviceToTest.sarifValidationSupport = sarifValidationSupport; + } + + @Test + void finding_cannot_be_validated_results_in_validation_and_categorization_never_being_called() { + SarifSchema210 report = createEmptySarifReport(); + + @SuppressWarnings("unchecked") + Map ruleConfigurations = mock(Map.class); + when(ruleConfigurations.get(any())).thenReturn(null); + + SecretValidatorExecutionContext executionContext = SecretValidatorExecutionContext.builder().setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations).setTrustAllCertificates(true).build(); + when(contextFactory.create()).thenReturn(executionContext); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(false); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); + } + + @Test + void empty_config_map_results_in_validation_and_categorization_never_being_called() { + /* prepare */ + SarifSchema210 report = createEmptySarifReport(); + + @SuppressWarnings("unchecked") + Map ruleConfigurations = mock(Map.class); + when(ruleConfigurations.get(any())).thenReturn(null); + + SecretValidatorExecutionContext executionContext = SecretValidatorExecutionContext.builder().setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations).setTrustAllCertificates(true).build(); + when(contextFactory.create()).thenReturn(executionContext); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); + } + + @Test + void categorization_of_config_is_null_results_in_validation_and_categorization_never_being_called() { + SarifSchema210 report = createEmptySarifReport(); + + SecretValidatorConfigurationModel config = new SecretValidatorConfigurationModel(); + config.setCategorization(null); + + @SuppressWarnings("unchecked") + Map ruleConfigurations = mock(Map.class); + when(ruleConfigurations.get(any())).thenReturn(config); + + SecretValidatorExecutionContext executionContext = SecretValidatorExecutionContext.builder().setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations).setTrustAllCertificates(true).build(); + when(contextFactory.create()).thenReturn(executionContext); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); + } + + @Test + void categorization_of_config_is_empty_results_in_validation_and_categorization_never_being_called() { + SarifSchema210 report = createEmptySarifReport(); + + SecretValidatorConfigurationModel config = new SecretValidatorConfigurationModel(); + SecretValidatorCategorization categorization = new SecretValidatorCategorization(); + config.setCategorization(categorization); + + @SuppressWarnings("unchecked") + Map ruleConfigurations = mock(Map.class); + when(ruleConfigurations.get(any())).thenReturn(config); + + SecretValidatorExecutionContext executionContext = SecretValidatorExecutionContext.builder().setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations).setTrustAllCertificates(true).build(); + when(contextFactory.create()).thenReturn(executionContext); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); + } + + @Test + void finding_location_cannot_be_validated_results_in_validation_and_categorization_never_being_called() { + SarifSchema210 report = createEmptySarifReport(); + + SecretValidatorConfigurationModel config = new SecretValidatorConfigurationModel(); + SecretValidatorCategorization categorization = mock(SecretValidatorCategorization.class); + categorization.setDefaultSeverity("high"); + config.setCategorization(categorization); + + @SuppressWarnings("unchecked") + Map ruleConfigurations = mock(Map.class); + when(ruleConfigurations.get(any())).thenReturn(config); + + SecretValidatorExecutionContext executionContext = SecretValidatorExecutionContext.builder().setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations).setTrustAllCertificates(true).build(); + when(contextFactory.create()).thenReturn(executionContext); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); + when(sarifValidationSupport.findingLocationCanBeValidated(any())).thenReturn(false); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); + verify(sarifValidationSupport, times(1)).findingLocationCanBeValidated(any()); + } + + @Test + void valid_config_and_valid_sarif_report_results_in_validation_and_categorization_being_called_for_configured_rule() { + /* prepare */ + SecretValidatorExecutionContext executionContext = createValidExecutionContext(); + when(contextFactory.create()).thenReturn(executionContext); + + SecretValidationResult secretValidationResult = new SecretValidationResult(); + when(validationService.validateFindingByRegion(any(), any(), anyBoolean())).thenReturn(secretValidationResult); + + doNothing().when(categorizationService).categorizeFindingByRegion(any(), any(), any()); + + when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); + when(sarifValidationSupport.findingLocationCanBeValidated(any())).thenReturn(true); + + /* execute */ + serviceToTest.execute(); + + /* test */ + verify(contextFactory, times(1)).create(); + verify(validationService, times(6)).validateFindingByRegion(any(), any(), anyBoolean()); + verify(categorizationService, times(6)).categorizeFindingByRegion(any(), any(), any()); + verify(sarifValidationSupport, times(6)).findingCanBeValidated(any()); + verify(sarifValidationSupport, times(6)).findingLocationCanBeValidated(any()); + } + + private SecretValidatorExecutionContext createValidExecutionContext() { + SarifSchema210 report = createSarifReport(new File("src/test/resources/config-test-files/valid-files/test-result.txt")); + + Map ruleConfigurations = createRuleConfigurations( + new File("src/test/resources/config-test-files/valid-files/test-config.json")); + + /* @formatter:off */ + return SecretValidatorExecutionContext.builder() + .setTrustAllCertificates(true) + .setSarifReport(report) + .setValidatorConfiguration(ruleConfigurations) + .build(); + /* @formatter:on */ + } + + private SarifSchema210 createSarifReport(File file) { + try { + String sarifReportJson = TestFileReader.loadTextFile(file); + return JSONConverter.get().fromJSON(SarifSchema210.class, sarifReportJson); + } catch (Exception e) { + throw new IllegalStateException("Creating SARIF report model from: " + file + " failed!", e); + } + } + + private Map createRuleConfigurations(File file) { + try { + String validatorConfigJson = TestFileReader.loadTextFile(file); + SecretValidatorConfigurationModelList configurationDataList = JSONConverter.get().fromJSON(SecretValidatorConfigurationModelList.class, + validatorConfigJson); + + Map ruleConfigurations = new HashMap<>(); + for (SecretValidatorConfigurationModel configData : configurationDataList.getValidatorConfigList()) { + ruleConfigurations.put(configData.getRuleId(), configData); + } + return ruleConfigurations; + } catch (Exception e) { + throw new IllegalStateException("Creating secret validator configuration from: " + file + " failed!", e); + } + } + + private SarifSchema210 createEmptySarifReport() { + List runs = new ArrayList<>(); + + Run run = new Run(); + + List results = new ArrayList<>(); + Result result = new Result(); + + ArrayList locations = new ArrayList<>(); + locations.add(new Location()); + + result.setLocations(locations); + results.add(result); + run.setResults(results); + ; + runs.add(run); + + SarifSchema210 report = new SarifSchema210(); + report.setRuns(runs); + + return report; + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java new file mode 100644 index 0000000000..71b0677310 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.http.HttpClient; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequestHeader; +import com.mercedesbenz.sechub.wrapper.secret.validator.support.SecretValidatorHttpClientFactory; + +class SecretValidatorWebRequestServiceTest { + + private SecretValidatorWebRequestService serviceTotest; + + private SecretValidatorHttpClientFactory httpClientFactory; + private ResponseValidationService responseValidationService; + + @BeforeEach + void beforeEach() { + serviceTotest = new SecretValidatorWebRequestService(); + httpClientFactory = new SecretValidatorHttpClientFactory(); + + httpClientFactory = mock(SecretValidatorHttpClientFactory.class); + responseValidationService = mock(ResponseValidationService.class); + + serviceTotest.httpClientFactory = httpClientFactory; + serviceTotest.responseValidationService = responseValidationService; + } + + @Test + void no_finding_snippet_text_available_results_in_finding_being_skipped_from_validation() { + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding(null, new ArrayList<>(), true); + + /* test */ + assertEquals(SecretValidationStatus.SARIF_SNIPPET_NOT_SET, validationResult.getValidationStatus()); + } + + @Test + void no_requests_defined_results_in_finding_being_skipped_from_validation() { + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding("not-empty", new ArrayList<>(), true); + + /* test */ + assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + } + + @Test + void request_config_inside_list_is_null_results_request_will_be_skipped() { + /* prepare */ + ArrayList requests = new ArrayList<>(); + requests.add(null); + + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding("not-empty", requests, true); + + /* test */ + // no validation request was performed ends up with the following status, only + // if at least 1 request was performed, the finding could be marked as invalid. + assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + } + + @Test + void request_url_is_null_results_request_will_be_skipped() { + /* prepare */ + ArrayList requests = new ArrayList<>(); + requests.add(new SecretValidatorRequest()); + + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding("no-empty", requests, true); + + /* test */ + // no validation request was performed ends up with the following status, only + // if at least 1 request was performed, the finding could be marked as invalid. + assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void proxy_required_calls_the_correct_http_client_results_validation_result(boolean expectedValidation) throws IOException, InterruptedException { + /* prepare */ + List requests = createListOfRequests(true); + + HttpClient proxyHttpClient = mock(HttpClient.class); + when(proxyHttpClient.send(any(), any())).thenReturn(null); + + when(httpClientFactory.createProxyHttpClient(anyBoolean())).thenReturn(proxyHttpClient); + + when(responseValidationService.isValidResponse(any(), any())).thenReturn(expectedValidation); + + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding("no-empty", requests, true); + + /* test */ + if (expectedValidation) { + assertEquals(SecretValidationStatus.VALID, validationResult.getValidationStatus()); + assertEquals("http://example.com", validationResult.getValidatedByUrl()); + } else { + assertEquals(SecretValidationStatus.INVALID, validationResult.getValidationStatus()); + } + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void no_proxy_required_calls_the_correct_http_client_results_validation_result(boolean expectedValidation) throws IOException, InterruptedException { + /* prepare */ + List requests = createListOfRequests(false); + + HttpClient directHttpClient = mock(HttpClient.class); + when(directHttpClient.send(any(), any())).thenReturn(null); + + when(httpClientFactory.createDirectHttpClient(anyBoolean())).thenReturn(directHttpClient); + + when(responseValidationService.isValidResponse(any(), any())).thenReturn(expectedValidation); + + /* execute */ + SecretValidationResult validationResult = serviceTotest.validateFinding("no-empty", requests, true); + + /* test */ + if (expectedValidation) { + assertEquals(SecretValidationStatus.VALID, validationResult.getValidationStatus()); + assertEquals("http://example.com", validationResult.getValidatedByUrl()); + } else { + assertEquals(SecretValidationStatus.INVALID, validationResult.getValidationStatus()); + } + } + + private List createListOfRequests(boolean proxyRequired) throws MalformedURLException { + ArrayList requests = new ArrayList<>(); + SecretValidatorRequest secretValidatorRequest = new SecretValidatorRequest(); + secretValidatorRequest.setProxyRequired(proxyRequired); + secretValidatorRequest.setUrl(new URL("http://example.com")); + List headers = new ArrayList<>(); + SecretValidatorRequestHeader header = new SecretValidatorRequestHeader(); + header.setName("Authorization"); + headers.add(header); + secretValidatorRequest.setHeaders(headers); + requests.add(secretValidatorRequest); + return requests; + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java new file mode 100644 index 0000000000..d443ad6705 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.commons.model.JSONConverter; + +class SecretValidatorConfigurationModelListTest { + + @Test + void test() { + /* prepare */ + String json = """ + { + "validatorConfigList" : [ { + "ruleId" : "rule-id", + "categorization" : { + "defaultSeverity" : "high", + "validationFailedSeverity" : "medium", + "validationSuccessSeverity" : "critical" + }, + "requests" : [ { + "url" : "https://api.example.com", + "proxyRequired" : true, + "headers" : [ { + "name" : "Authorization", + "valuePrefix" : "Bearer" + } ], + "expectedResponse" : { + "httpStatus" : 200, + "contains" : { + "allOf" : [ "is", "there" ], + "oneOf" : [ "success" ] + } + } + } ] + } ] + } + """; + + String expected = "{\"validatorConfigList\":[{\"ruleId\":\"rule-id\",\"categorization\":{\"defaultSeverity\":\"high\",\"validationFailedSeverity\":\"medium\",\"validationSuccessSeverity\":\"critical\"}," + + "\"requests\":[{\"url\":\"https://api.example.com\",\"proxyRequired\":true,\"headers\":[{\"name\":\"Authorization\",\"valuePrefix\":\"Bearer\"}]," + + "\"expectedResponse\":{\"httpStatus\":200,\"contains\":{\"allOf\":[\"is\",\"there\"],\"oneOf\":[\"success\"]}}}]}]}"; + + /* execute */ + SecretValidatorConfigurationModelList fromJson = JSONConverter.get().fromJSON(SecretValidatorConfigurationModelList.class, json); + String toJson = JSONConverter.get().toJSON(fromJson); + + /* test */ + assertEquals(expected, toJson); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java new file mode 100644 index 0000000000..2d303778f9 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@SpringBootTest(classes = { SecretValidatorProperties.class, SecretValidatorPDSJobResult.class }) +@ExtendWith(SpringExtension.class) +@EnableConfigurationProperties +@TestPropertySource(properties = { "secret.validator.config-file=src/test/resources/config-test-files/valid-files/test-config.json", + "secret.validator.trust-all-certificates=false", "pds.job.result.file=src/test/resources/config-test-files/valid-files/test-result.txt" }) +class SecretValidatorConfigurationSpringBootTest { + + @Autowired + private SecretValidatorProperties properties; + + @Autowired + private SecretValidatorPDSJobResult pdsJobResult; + + @Test + void properties_are_created_correctly() { + /* test */ + + // check if all SecretValidatorProperties are as expected + assertFalse(properties.isTrustAllCertificates()); + assertEquals("src/test/resources/config-test-files/valid-files/test-config.json", properties.getConfigFile().toString()); + + // check if the PDS job result file is as expected + assertEquals("src/test/resources/config-test-files/valid-files/test-result.txt", pdsJobResult.getFile().toString()); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java new file mode 100644 index 0000000000..1b944bc0fd --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java @@ -0,0 +1,122 @@ +package com.mercedesbenz.sechub.wrapper.secret.validator.support; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.PhysicalLocation; +import de.jcup.sarif_2_1_0.model.Region; +import de.jcup.sarif_2_1_0.model.Result; + +class SarifValidationSupportTest { + + private SarifValidationSupport supportToTest = new SarifValidationSupport(); + + @Test + void finding_null_returns_false() { + /* execute */ + boolean findingCanBeValidated = supportToTest.findingCanBeValidated(null); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_locations_is_null_returns_false() { + /* prepare */ + Result finding = new Result(); + finding.setLocations(null); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingCanBeValidated(finding); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_locations_is_empty_returns_false() { + /* prepare */ + Result finding = new Result(); + finding.setLocations(new ArrayList<>()); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingCanBeValidated(finding); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_locations_conatins_one_location_object_returns_true() { + /* prepare */ + List locations = new ArrayList<>(); + locations.add(new Location()); + Result finding = new Result(); + finding.setLocations(locations); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingCanBeValidated(finding); + + /* test */ + assertTrue(findingCanBeValidated); + } + + @Test + void finding_location_is_null_returns_false() { + /* execute */ + boolean findingCanBeValidated = supportToTest.findingLocationCanBeValidated(null); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_location_physical_location_is_null_returns_false() { + /* prepare */ + Location location = new Location(); + location.setPhysicalLocation(null); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingLocationCanBeValidated(location); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_location_physical_location_region_is_null_returns_false() { + /* prepare */ + PhysicalLocation physicalLocation = new PhysicalLocation(); + physicalLocation.setRegion(null); + Location location = new Location(); + location.setPhysicalLocation(physicalLocation); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingLocationCanBeValidated(location); + + /* test */ + assertFalse(findingCanBeValidated); + } + + @Test + void finding_location_physical_location_region_is_not_null_returns_false() { + /* prepare */ + PhysicalLocation physicalLocation = new PhysicalLocation(); + physicalLocation.setRegion(new Region()); + Location location = new Location(); + location.setPhysicalLocation(physicalLocation); + + /* execute */ + boolean findingCanBeValidated = supportToTest.findingLocationCanBeValidated(location); + + /* test */ + assertTrue(findingCanBeValidated); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactoryTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactoryTest.java new file mode 100644 index 0000000000..b577f34141 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SecretValidatorHttpClientFactoryTest.java @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.support; + +import static org.junit.Assert.assertTrue; + +import java.net.http.HttpClient; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class SecretValidatorHttpClientFactoryTest { + + private SecretValidatorHttpClientFactory factoryToTest = new SecretValidatorHttpClientFactory(); + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void create_proxy_http_client_returns_expected_http_client(boolean trustAllCertificates) { + /* execute */ + HttpClient proxyHttpClient = factoryToTest.createProxyHttpClient(trustAllCertificates); + + /* test */ + assertTrue(proxyHttpClient.proxy().isPresent()); + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void create_direct_http_client_returns_expected_http_client(boolean trustAllCertificates) { + /* execute */ + HttpClient proxyHttpClient = factoryToTest.createDirectHttpClient(trustAllCertificates); + + /* test */ + assertTrue(proxyHttpClient.proxy().isEmpty()); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-sarif.txt b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-sarif.txt new file mode 100644 index 0000000000..fb11c48106 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-sarif.txt @@ -0,0 +1 @@ +not valid sarif \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt new file mode 100644 index 0000000000..a6621a3896 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt @@ -0,0 +1 @@ +invalid file \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-config.json b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-config.json new file mode 100644 index 0000000000..9bdf28c27e --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-config.json @@ -0,0 +1,25 @@ +{ + "validatorConfigList" : [ { + "ruleId" : "generic-api-key", + "categorization" : { + "defaultSeverity" : "high", + "validationFailedSeverity" : "medium", + "validationSuccessSeverity" : "critical" + }, + "requests" : [ { + "proxyRequired" : false, + "url" : "https://localhost", + "headers" : [ { + "name" : "Authorization", + "valuePrefix" : "Bearer" + } ], + "expectedResponse" : { + "httpStatus" : 200, + "contains" : { + "allOf" : [ "is", "there" ], + "oneOf" : [ "success" ] + } + } + } ] + } ] +} \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt new file mode 100644 index 0000000000..ba37047594 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt @@ -0,0 +1,956 @@ +{ + "$schema" : "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json", + "version" : "2.1.0", + "runs" : [ { + "tool" : { + "driver" : { + "name" : "gitleaks", + "semanticVersion" : "v8.0.0", + "rules" : [ { + "id" : "adafruit-api-key", + "name" : "Adafruit API Key", + "shortDescription" : { + "text" : "(?i)(?:adafruit)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-id", + "name" : "Adobe Client ID (Oauth Web)", + "shortDescription" : { + "text" : "(?i)(?:adobe)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-secret", + "name" : "Adobe Client Secret", + "shortDescription" : { + "text" : "(?i)\\b((p8e-)(?i)[a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "age secret key", + "name" : "Age secret key", + "shortDescription" : { + "text" : "AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}" + } + }, { + "id" : "airtable-api-key", + "name" : "Airtable API Key", + "shortDescription" : { + "text" : "(?i)(?:airtable)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{17})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "algolia-api-key", + "name" : "Algolia API Key", + "shortDescription" : { + "text" : "(?i)(?:algolia)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-access-key-id", + "name" : "Alibaba AccessKey ID", + "shortDescription" : { + "text" : "(?i)\\b((LTAI)(?i)[a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-secret-key", + "name" : "Alibaba Secret Key", + "shortDescription" : { + "text" : "(?i)(?:alibaba)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-id", + "name" : "Asana Client ID", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-secret", + "name" : "Asana Client Secret", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "atlassian-api-token", + "name" : "Atlassian API token", + "shortDescription" : { + "text" : "(?i)(?:atlassian|confluence|jira)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "aws-access-token", + "name" : "AWS", + "shortDescription" : { + "text" : "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" + } + }, { + "id" : "bitbucket-client-id", + "name" : "BitBucket Client ID", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bitbucket-client-secret", + "name" : "BitBucket Client Secret", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-access-key", + "name" : "Bittrex Access Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-secret-key", + "name" : "Bittrex Secret Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "beamer-api-token", + "name" : "Beamer API token", + "shortDescription" : { + "text" : "(?i)(?:beamer)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(b_[a-z0-9=_\\-]{44})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "codecov-access-token", + "name" : "Codecov Access Token", + "shortDescription" : { + "text" : "(?i)(?:codecov)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "coinbase-access-token", + "name" : "Coinbase Access Token", + "shortDescription" : { + "text" : "(?i)(?:coinbase)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "clojars-api-token", + "name" : "Clojars API token", + "shortDescription" : { + "text" : "(?i)(CLOJARS_)[a-z0-9]{60}" + } + }, { + "id" : "confluent-access-token", + "name" : "Confluent Access Token", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "confluent-secret-key", + "name" : "Confluent Secret Key", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "contentful-delivery-api-token", + "name" : "Contentful delivery API token", + "shortDescription" : { + "text" : "(?i)(?:contentful)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "databricks-api-token", + "name" : "Databricks API token", + "shortDescription" : { + "text" : "(?i)\\b(dapi[a-h0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "datadog-access-token", + "name" : "Datadog Access Token", + "shortDescription" : { + "text" : "(?i)(?:datadog)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-api-token", + "name" : "Discord API key", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-id", + "name" : "Discord client ID", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{18})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-secret", + "name" : "Discord client secret", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "doppler-api-token", + "name" : "Doppler API token", + "shortDescription" : { + "text" : "(dp\\.pt\\.)(?i)[a-z0-9]{43}" + } + }, { + "id" : "dropbox-api-token", + "name" : "Dropbox API secret", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{15})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-long-lived-api-token", + "name" : "Dropbox long lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\\-_=]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-short-lived-api-token", + "name" : "Dropbox short lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(sl\\.[a-z0-9\\-=_]{135})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "droneci-access-token", + "name" : "Droneci Access Token", + "shortDescription" : { + "text" : "(?i)(?:droneci)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "duffel-api-token", + "name" : "Duffel API token", + "shortDescription" : { + "text" : "duffel_(test|live)_(?i)[a-z0-9_\\-=]{43}" + } + }, { + "id" : "dynatrace-api-token", + "name" : "Dynatrace API token", + "shortDescription" : { + "text" : "dt0c01\\.(?i)[a-z0-9]{24}\\.[a-z0-9]{64}" + } + }, { + "id" : "easypost-api-token", + "name" : "EasyPost API token", + "shortDescription" : { + "text" : "EZAK(?i)[a-z0-9]{54}" + } + }, { + "id" : "easypost-test-api-token", + "name" : "EasyPost test API token", + "shortDescription" : { + "text" : "EZTK(?i)[a-z0-9]{54}" + } + }, { + "id" : "etsy-access-token", + "name" : "Etsy Access Token", + "shortDescription" : { + "text" : "(?i)(?:etsy)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "facebook", + "name" : "facebook", + "shortDescription" : { + "text" : "(?i)(?:facebook)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "fastly-api-token", + "name" : "Fastly API key", + "shortDescription" : { + "text" : "(?i)(?:fastly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-client-secret", + "name" : "Finicity Client Secret", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-api-token", + "name" : "Finicity API token", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flickr-access-token", + "name" : "Flickr Access Token", + "shortDescription" : { + "text" : "(?i)(?:flickr)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finnhub-access-token", + "name" : "Finnhub Access Token", + "shortDescription" : { + "text" : "(?i)(?:finnhub)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flutterwave-public-key", + "name" : "Finicity Public Key", + "shortDescription" : { + "text" : "FLWPUBK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-secret-key", + "name" : "Flutterwave Secret Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-encryption-key", + "name" : "Flutterwave Encryption Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{12}" + } + }, { + "id" : "frameio-api-token", + "name" : "Frame.io API token", + "shortDescription" : { + "text" : "fio-u-(?i)[a-z0-9\\-_=]{64}" + } + }, { + "id" : "freshbooks-access-token", + "name" : "Freshbooks Access Token", + "shortDescription" : { + "text" : "(?i)(?:freshbooks)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gocardless-api-token", + "name" : "GoCardless API token", + "shortDescription" : { + "text" : "(?i)(?:gocardless)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(live_(?i)[a-z0-9\\-_=]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gcp-api-key", + "name" : "GCP API key", + "shortDescription" : { + "text" : "(?i)\\b(AIza[0-9A-Za-z\\\\-_]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "github-pat", + "name" : "GitHub Personal Access Token", + "shortDescription" : { + "text" : "ghp_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-oauth", + "name" : "GitHub OAuth Access Token", + "shortDescription" : { + "text" : "gho_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-app-token", + "name" : "GitHub App Token", + "shortDescription" : { + "text" : "(ghu|ghs)_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-refresh-token", + "name" : "GitHub Refresh Token", + "shortDescription" : { + "text" : "ghr_[0-9a-zA-Z]{36}" + } + }, { + "id" : "gitlab-pat", + "name" : "Gitlab Personal Access Token", + "shortDescription" : { + "text" : "glpat-[0-9a-zA-Z\\-\\_]{20}" + } + }, { + "id" : "gitter-access-token", + "name" : "Gitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:gitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hashicorp-tf-api-token", + "name" : "HashiCorp Terraform user/org API token", + "shortDescription" : { + "text" : "(?i)[a-z0-9]{14}\\.atlasv1\\.[a-z0-9\\-_=]{60,70}" + } + }, { + "id" : "heroku-api-key", + "name" : "Heroku API Key", + "shortDescription" : { + "text" : "(?i)(?:heroku)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hubspot-api-key", + "name" : "HubSpot API Token", + "shortDescription" : { + "text" : "(?i)(?:hubspot)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "intercom-api-key", + "name" : "Intercom API Token", + "shortDescription" : { + "text" : "(?i)(?:intercom)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{60})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kraken-access-token", + "name" : "Kraken Access Token", + "shortDescription" : { + "text" : "(?i)(?:kraken)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9\\/=_\\+\\-]{80,90})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-access-token", + "name" : "Kucoin Access Token", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-secret-key", + "name" : "Kucoin Secret Key", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "launchdarkly-access-token", + "name" : "Launchdarkly Access Token", + "shortDescription" : { + "text" : "(?i)(?:launchdarkly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linear-api-key", + "name" : "Linear API Token", + "shortDescription" : { + "text" : "lin_api_(?i)[a-z0-9]{40}" + } + }, { + "id" : "linear-client-secret", + "name" : "Linear Client Secret", + "shortDescription" : { + "text" : "(?i)(?:linear)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-id", + "name" : "LinkedIn Client ID", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-secret", + "name" : "LinkedIn Client secret", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-api-key", + "name" : "Lob API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-pub-api-key", + "name" : "Lob Publishable API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailchimp-api-key", + "name" : "Mailchimp API key", + "shortDescription" : { + "text" : "(?i)(?:mailchimp)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32}-us20)(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-pub-key", + "name" : "Mailgun public validation key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-private-api-token", + "name" : "Mailgun private API token", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(key-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-signing-key", + "name" : "Mailgun webhook signing key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mapbox-api-token", + "name" : "MapBox API token", + "shortDescription" : { + "text" : "(?i)(?:mapbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pk\\.[a-z0-9]{60}\\.[a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mattermost-access-token", + "name" : "Mattermost Access Token", + "shortDescription" : { + "text" : "(?i)(?:mattermost)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{26})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-api-token", + "name" : "MessageBird API token", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-client-id", + "name" : "MessageBird client ID", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "netlify-access-token", + "name" : "Netlify Access Token", + "shortDescription" : { + "text" : "(?i)(?:netlify)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40,46})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-key", + "name" : "New Relic user API Key", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-id", + "name" : "New Relic user API ID", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-browser-api-token", + "name" : "New Relic ingest browser API token", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "npm-access-token", + "name" : "npm access token", + "shortDescription" : { + "text" : "(?i)\\b(npm_[a-z0-9]{36})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "nytimes-access-token", + "name" : "Nytimes Access Token", + "shortDescription" : { + "text" : "(?i)(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "okta-access-token", + "name" : "Okta Access Token", + "shortDescription" : { + "text" : "(?i)(?:okta)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{42})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-client-id", + "name" : "Plaid Client ID", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-secret-key", + "name" : "Plaid Secret key", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-api-token", + "name" : "Plaid API Token", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-password", + "name" : "PlanetScale password", + "shortDescription" : { + "text" : "(?i)\\b(pscale_pw_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-api-token", + "name" : "PlanetScale API token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_tkn_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-oauth-token", + "name" : "PlanetScale OAuth token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_oauth_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "postman-api-token", + "name" : "Postman API token", + "shortDescription" : { + "text" : "(?i)\\b(PMAK-(?i)[a-f0-9]{24}\\-[a-f0-9]{34})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "private-key", + "name" : "Private Key", + "shortDescription" : { + "text" : "(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY-----[\\s\\S-]*KEY----" + } + }, { + "id" : "pulumi-api-token", + "name" : "Pulumi API token", + "shortDescription" : { + "text" : "(?i)\\b(pul-[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "pypi-upload-token", + "name" : "PyPI upload token", + "shortDescription" : { + "text" : "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\\-_]{50,1000}" + } + }, { + "id" : "rubygems-api-token", + "name" : "Rubygem API token", + "shortDescription" : { + "text" : "(?i)\\b(rubygems_[a-f0-9]{48})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "rapidapi-access-token", + "name" : "RapidAPI Access Token", + "shortDescription" : { + "text" : "(?i)(?:rapidapi)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-id", + "name" : "Sendbird Access ID", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-token", + "name" : "Sendbird Access Token", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendgrid-api-token", + "name" : "SendGrid API token", + "shortDescription" : { + "text" : "(?i)\\b(SG\\.(?i)[a-z0-9=_\\-\\.]{66})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendinblue-api-token", + "name" : "Sendinblue API token", + "shortDescription" : { + "text" : "(?i)\\b(xkeysib-[a-f0-9]{64}\\-(?i)[a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sentry-access-token", + "name" : "Sentry Access Token", + "shortDescription" : { + "text" : "(?i)(?:sentry)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shippo-api-token", + "name" : "Shippo API token", + "shortDescription" : { + "text" : "(?i)\\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shopify-access-token", + "name" : "Shopify access token", + "shortDescription" : { + "text" : "shpat_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-custom-access-token", + "name" : "Shopify custom access token", + "shortDescription" : { + "text" : "shpca_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-private-app-access-token", + "name" : "Shopify private app access token", + "shortDescription" : { + "text" : "shppa_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-shared-secret", + "name" : "Shopify shared secret", + "shortDescription" : { + "text" : "shpss_[a-fA-F0-9]{32}" + } + }, { + "id" : "slack-access-token", + "name" : "Slack token", + "shortDescription" : { + "text" : "xox[baprs]-([0-9a-zA-Z]{10,48})" + } + }, { + "id" : "slack-web-hook", + "name" : "Slack Webhook", + "shortDescription" : { + "text" : "https:\\/\\/hooks.slack.com\\/services\\/[A-Za-z0-9+\\/]{44,46}" + } + }, { + "id" : "stripe-access-token", + "name" : "Stripe", + "shortDescription" : { + "text" : "(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}" + } + }, { + "id" : "square-access-token", + "name" : "Square Access Token", + "shortDescription" : { + "text" : "(?i)\\b(sq0atp-[0-9A-Za-z\\-_]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "squarespace-access-token", + "name" : "Squarespace Access Token", + "shortDescription" : { + "text" : "(?i)(?:squarespace)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-id", + "name" : "SumoLogic Access ID", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-token", + "name" : "SumoLogic Access Token", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "travisci-access-token", + "name" : "Travis CI Access Token", + "shortDescription" : { + "text" : "(?i)(?:travis)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twilio-api-key", + "name" : "Twilio API Key", + "shortDescription" : { + "text" : "SK[0-9a-fA-F]{32}" + } + }, { + "id" : "twitch-api-token", + "name" : "Twitch API token", + "shortDescription" : { + "text" : "(?i)(?:twitch)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-key", + "name" : "Twitter API Key", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-secret", + "name" : "Twitter API Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-token", + "name" : "Twitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{15,25}-[a-zA-Z0-9]{20,40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-secret", + "name" : "Twitter Access Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{45})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-bearer-token", + "name" : "Twitter Bearer Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(A{22}[a-zA-Z0-9%]{80,100})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "typeform-api-token", + "name" : "Typeform API token", + "shortDescription" : { + "text" : "(?i)(?:typeform)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(tfp_[a-z0-9\\-_\\.=]{59})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-api-key", + "name" : "Yandex API Key", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(AQVN[A-Za-z0-9_\\-]{35,38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-aws-access-token", + "name" : "Yandex AWS Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(YC[a-zA-Z0-9_\\-]{38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-access-token", + "name" : "Yandex Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(t1\\.[A-Z0-9a-z_-]+[=]{0,2}\\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "zendesk-secret-key", + "name" : "Zendesk Secret Key", + "shortDescription" : { + "text" : "(?i)(?:zendesk)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "generic-api-key", + "name" : "Generic API Key", + "shortDescription" : { + "text" : "(?i)(?:key|api|token|secret|client|passwd|password|auth)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-z\\-_.=]{10,150})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + } ] + } + }, + "results" : [ { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/docker-compose.yml." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/docker-compose.yml" + }, + "region" : { + "startLine" : 12, + "startColumn" : 14, + "endLine" : 13, + "endColumn" : 1, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/src/api/application/config/database.php." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/src/api/application/config/database.php" + }, + "region" : { + "startLine" : 80, + "startColumn" : 7, + "endLine" : 80, + "endColumn" : 61, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx" + }, + "region" : { + "startLine" : 32, + "startColumn" : 14, + "endLine" : 32, + "endColumn" : 56, + "snippet" : { + "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx" + }, + "region" : { + "startLine" : 31, + "startColumn" : 14, + "endLine" : 31, + "endColumn" : 56, + "snippet" : { + "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/iOS/Source Code/Podfile.lock." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/iOS/Source Code/Podfile.lock" + }, + "region" : { + "startLine" : 23, + "startColumn" : 4, + "endLine" : 24, + "endColumn" : 1, + "snippet" : { + "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock" + }, + "region" : { + "startLine" : 23, + "startColumn" : 4, + "endLine" : 24, + "endColumn" : 1, + "snippet" : { + "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + } ] + } ] +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index e541f0c97e..6da99471bf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -88,7 +88,10 @@ include 'sechub-cli', 'sechub-wrapper-prepare', /* webui */ -'sechub-webui-solution' +'sechub-webui-solution', + +/* secret validator */ +'sechub-wrapper-secret-validator' String buildStage = System.getProperty("sechub.build.stage"); From a16097af7266b41e4c614676eadfaffd87e83c49 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Mon, 8 Jul 2024 13:17:09 +0200 Subject: [PATCH 02/10] Extend SarifV1JSONImporter to enable import of custom gitleaks properties #3276 - extend workaround classes with te ability to resolve secret validation wrapper custom severities - add necessary changes to SarifV1JSONImporter and added test cases with test report files --- .../GitleaksSarifImportWorkaround.java | 40 +- .../SarifImportProductWorkaround.java | 4 + .../SarifImportProductWorkaroundSupport.java | 10 + .../sereco/importer/SarifImporterKeys.java | 31 + .../sereco/importer/SarifV1JSONImporter.java | 13 +- .../importer/SarifV1JSONImporterTest.java | 85 ++ ...invalid-validator-severity-properties.json | 850 +++++++++++++++ ....0-with-validator-severity-properties.json | 974 ++++++++++++++++++ 8 files changed, 1999 insertions(+), 8 deletions(-) create mode 100644 sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java create mode 100644 sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json create mode 100644 sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java index bbc6ca0908..a21e41bbe4 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java @@ -1,16 +1,12 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.sereco.importer; +import java.util.List; import java.util.Map; import org.springframework.stereotype.Component; -import de.jcup.sarif_2_1_0.model.PartialFingerprints; -import de.jcup.sarif_2_1_0.model.ReportingDescriptor; -import de.jcup.sarif_2_1_0.model.Result; -import de.jcup.sarif_2_1_0.model.Run; -import de.jcup.sarif_2_1_0.model.Tool; -import de.jcup.sarif_2_1_0.model.ToolComponent; +import de.jcup.sarif_2_1_0.model.*; @Component public class GitleaksSarifImportWorkaround implements SarifImportProductWorkaround { @@ -42,6 +38,38 @@ public String resolveFindingRevisionId(Result result, Run run) { return null; } + @Override + public String resolveCustomSechubSeverity(Result result, Run run) { + if (result == null) { + return null; + } + if (!isGitleaksRun(run)) { + return null; + } + List locations = result.getLocations(); + if (locations == null || locations.isEmpty()) { + return null; + } + PhysicalLocation physicalLocation = locations.get(0).getPhysicalLocation(); + if (physicalLocation == null) { + return null; + } + Region region = physicalLocation.getRegion(); + if (region == null) { + return null; + } + PropertyBag properties = region.getProperties(); + if (properties == null) { + return null; + } + Map additionalProperties = properties.getAdditionalProperties(); + if (additionalProperties == null) { + return null; + } + String severityKey = SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey(); + return (String) additionalProperties.get(severityKey); + } + private boolean isGitleaksRun(Run run) { if (run == null) { return false; diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java index f4fdb73be4..9e3e460719 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java @@ -22,4 +22,8 @@ public default String resolveType(ReportingDescriptor rule, Run run) { public default String resolveFindingRevisionId(Result result, Run run) { return null; } + + public default String resolveCustomSechubSeverity(Result result, Run run) { + return null; + } } diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java index c88da22c92..7bb20f5072 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java @@ -58,6 +58,16 @@ private R visitAllWorkaroundsAndUseFirstResultNotNull(E element, Run run, return null; } + public String resolveCustomSechubSeverity(Result result, Run run) { + return visitAllWorkaroundsAndUseFirstResultNotNull(result, run, new WorkaroundVisitor() { + + @Override + public String visit(Result element, Run run, SarifImportProductWorkaround workaround) { + return workaround.resolveCustomSechubSeverity(result, run); + } + }); + } + public interface WorkaroundVisitor { public R visit(E element, Run run, SarifImportProductWorkaround workaround); diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java new file mode 100644 index 0000000000..cee7ee8df1 --- /dev/null +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.sereco.importer; + +/* + * If this needs to get changed, make sure to change + * com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys accordingly + */ +public enum SarifImporterKeys { + + SECRETSCAN_SECHUB_SEVERITY("secretscan.sechub.severity", "The key for the sechub severity which is more precise than the SARIF Level enum."), + + SECRETSCAN_VALIDATED_BY_URL("secretscan.validated.by.url", "The key for the URL the secret was validated with."), + + ; + + private String key; + private String description; + + private SarifImporterKeys(String key, String description) { + this.key = key; + this.description = description; + } + + public String getKey() { + return key; + } + + public String getDescription() { + return description; + } +} diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java index ab1205a593..32389bbcfb 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java @@ -285,8 +285,13 @@ private void handleWebRequest(Result result, SerecoWeb serecoWeb) { } private SerecoSeverity resolveSeverity(Result result, Run run) { - Level level = sarifSchema210LogicSupport.resolveLevel(result, run); - return mapToSeverity(level); + String customSecHubSeverity = workaroundSupport.resolveCustomSechubSeverity(result, run); + SerecoSeverity serecoSeverity = severityFromString(customSecHubSeverity); + if (serecoSeverity == null) { + Level level = sarifSchema210LogicSupport.resolveLevel(result, run); + return mapToSeverity(level); + } + return serecoSeverity; } private class ResultData { @@ -523,6 +528,10 @@ private SerecoSeverity mapToSeverity(Level level) { } } + private SerecoSeverity severityFromString(String customSecHubSeverity) { + return SerecoSeverity.fromString(customSecHubSeverity); + } + @Override public boolean isAbleToImportForProduct(ImportParameter param) { /* first we do the simple check... */ diff --git a/sechub-sereco/src/test/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporterTest.java b/sechub-sereco/src/test/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporterTest.java index 000af5dca5..ab90d5f2e2 100644 --- a/sechub-sereco/src/test/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporterTest.java +++ b/sechub-sereco/src/test/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporterTest.java @@ -36,6 +36,8 @@ class SarifV1JSONImporterTest { private static String sarif_2_1_0_gosec2_9_5_example5_cosdescan; private static String sarif_2_1_0_sarif_2_1_0_gitleaks_8_0; private static String sarif_2_1_0_sarif_2_1_0_gitleaks_8_0_one_finding_with_revision_id; + private static String sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties; + private static String sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties; private SarifV1JSONImporter importerToTest; @@ -51,6 +53,9 @@ public static void before() { sarif_2_1_0_owasp_zap = loadSarifTestFile("sarif_2.1.0_owasp_zap.json"); sarif_2_1_0_sarif_2_1_0_gitleaks_8_0 = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0.json"); sarif_2_1_0_sarif_2_1_0_gitleaks_8_0_one_finding_with_revision_id = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0-one-finding-with-revision.json"); + sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties = loadSarifTestFile("sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json"); + sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties = loadSarifTestFile( + "sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json"); } @BeforeEach @@ -319,6 +324,86 @@ void gitleaks_8_0_simple_example_secretscan__can_be_imported_and_revision_inform /* @formatter:on */ } + @Test + void sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties__can_be_imported_and_severities_are_available() throws Exception { + /* prepare */ + importerToTest.workaroundSupport.workarounds.add(new GitleaksSarifImportWorkaround()); + SerecoMetaData result = importerToTest.importResult(sarif_2_1_0_gitleaks_8_0_with_validator_severity_properties, ScanType.SECRET_SCAN); + + /* execute */ + List vulnerabilities = result.getVulnerabilities(); + + /* test */ + /* @formatter:off */ + assertVulnerabilities(vulnerabilities). + hasVulnerabilities(6). + verifyVulnerability(). + withSeverity(SerecoSeverity.INFO). + withCodeLocation("UnSAFE_Bank/Backend/docker-compose.yml", 12, 14). + containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.UNCLASSIFIED). + withCodeLocation("UnSAFE_Bank/Backend/src/api/application/config/database.php", 80, 7). + containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.LOW). + withCodeLocation("UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx", 32, 14). + containingSource("9bbc0d79e686e847bc305c9bd4cc2ea6"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.MEDIUM). + withCodeLocation("UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx", 31, 14). + containingSource("9bbc0d79e686e847bc305c9bd4cc2ea6"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.HIGH). + withCodeLocation("UnSAFE_Bank/iOS/Source Code/Podfile.lock", 23, 4). + containingSource("b3816fddcf28aa29d94b10ec305cd52be14c472b"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.CRITICAL). + withCodeLocation("UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock", 23, 4). + containingSource("b3816fddcf28aa29d94b10ec305cd52be14c472b"). + done(). + isContained(); + /* @formatter:on */ + } + + @Test + void sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties__can_be_imported_and_severities_are_set_to_sarif_default() throws Exception { + /* prepare */ + importerToTest.workaroundSupport.workarounds.add(new GitleaksSarifImportWorkaround()); + SerecoMetaData result = importerToTest.importResult(sarif_2_1_0_gitleaks_8_0_with_invalid_validator_severity_properties, ScanType.SECRET_SCAN); + + /* execute */ + List vulnerabilities = result.getVulnerabilities(); + + /* test */ + /* @formatter:off */ + assertVulnerabilities(vulnerabilities). + hasVulnerabilities(2). + verifyVulnerability(). + withSeverity(SerecoSeverity.MEDIUM). + withCodeLocation("UnSAFE_Bank/Backend/docker-compose.yml", 12, 14). + containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd"). + done(). + isContained(). + verifyVulnerability(). + withSeverity(SerecoSeverity.MEDIUM). + withCodeLocation("UnSAFE_Bank/Backend/src/api/application/config/database.php", 80, 7). + containingSource("531486b2bf646636a6a1bba61e78ec4a4a54efbd"). + done(). + isContained(); + /* @formatter:on */ + } + @Test void brakeman_sarif_report_can_be_imported() { /* prepare */ diff --git a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json new file mode 100644 index 0000000000..41b8a849e4 --- /dev/null +++ b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json @@ -0,0 +1,850 @@ +{ + "$schema" : "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json", + "version" : "2.1.0", + "runs" : [ { + "tool" : { + "driver" : { + "name" : "gitleaks", + "semanticVersion" : "v8.0.0", + "rules" : [ { + "id" : "adafruit-api-key", + "name" : "Adafruit API Key", + "shortDescription" : { + "text" : "(?i)(?:adafruit)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-id", + "name" : "Adobe Client ID (Oauth Web)", + "shortDescription" : { + "text" : "(?i)(?:adobe)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-secret", + "name" : "Adobe Client Secret", + "shortDescription" : { + "text" : "(?i)\\b((p8e-)(?i)[a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "age secret key", + "name" : "Age secret key", + "shortDescription" : { + "text" : "AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}" + } + }, { + "id" : "airtable-api-key", + "name" : "Airtable API Key", + "shortDescription" : { + "text" : "(?i)(?:airtable)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{17})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "algolia-api-key", + "name" : "Algolia API Key", + "shortDescription" : { + "text" : "(?i)(?:algolia)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-access-key-id", + "name" : "Alibaba AccessKey ID", + "shortDescription" : { + "text" : "(?i)\\b((LTAI)(?i)[a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-secret-key", + "name" : "Alibaba Secret Key", + "shortDescription" : { + "text" : "(?i)(?:alibaba)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-id", + "name" : "Asana Client ID", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-secret", + "name" : "Asana Client Secret", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "atlassian-api-token", + "name" : "Atlassian API token", + "shortDescription" : { + "text" : "(?i)(?:atlassian|confluence|jira)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "aws-access-token", + "name" : "AWS", + "shortDescription" : { + "text" : "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" + } + }, { + "id" : "bitbucket-client-id", + "name" : "BitBucket Client ID", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bitbucket-client-secret", + "name" : "BitBucket Client Secret", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-access-key", + "name" : "Bittrex Access Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-secret-key", + "name" : "Bittrex Secret Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "beamer-api-token", + "name" : "Beamer API token", + "shortDescription" : { + "text" : "(?i)(?:beamer)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(b_[a-z0-9=_\\-]{44})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "codecov-access-token", + "name" : "Codecov Access Token", + "shortDescription" : { + "text" : "(?i)(?:codecov)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "coinbase-access-token", + "name" : "Coinbase Access Token", + "shortDescription" : { + "text" : "(?i)(?:coinbase)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "clojars-api-token", + "name" : "Clojars API token", + "shortDescription" : { + "text" : "(?i)(CLOJARS_)[a-z0-9]{60}" + } + }, { + "id" : "confluent-access-token", + "name" : "Confluent Access Token", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "confluent-secret-key", + "name" : "Confluent Secret Key", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "contentful-delivery-api-token", + "name" : "Contentful delivery API token", + "shortDescription" : { + "text" : "(?i)(?:contentful)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "databricks-api-token", + "name" : "Databricks API token", + "shortDescription" : { + "text" : "(?i)\\b(dapi[a-h0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "datadog-access-token", + "name" : "Datadog Access Token", + "shortDescription" : { + "text" : "(?i)(?:datadog)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-api-token", + "name" : "Discord API key", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-id", + "name" : "Discord client ID", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{18})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-secret", + "name" : "Discord client secret", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "doppler-api-token", + "name" : "Doppler API token", + "shortDescription" : { + "text" : "(dp\\.pt\\.)(?i)[a-z0-9]{43}" + } + }, { + "id" : "dropbox-api-token", + "name" : "Dropbox API secret", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{15})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-long-lived-api-token", + "name" : "Dropbox long lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\\-_=]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-short-lived-api-token", + "name" : "Dropbox short lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(sl\\.[a-z0-9\\-=_]{135})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "droneci-access-token", + "name" : "Droneci Access Token", + "shortDescription" : { + "text" : "(?i)(?:droneci)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "duffel-api-token", + "name" : "Duffel API token", + "shortDescription" : { + "text" : "duffel_(test|live)_(?i)[a-z0-9_\\-=]{43}" + } + }, { + "id" : "dynatrace-api-token", + "name" : "Dynatrace API token", + "shortDescription" : { + "text" : "dt0c01\\.(?i)[a-z0-9]{24}\\.[a-z0-9]{64}" + } + }, { + "id" : "easypost-api-token", + "name" : "EasyPost API token", + "shortDescription" : { + "text" : "EZAK(?i)[a-z0-9]{54}" + } + }, { + "id" : "easypost-test-api-token", + "name" : "EasyPost test API token", + "shortDescription" : { + "text" : "EZTK(?i)[a-z0-9]{54}" + } + }, { + "id" : "etsy-access-token", + "name" : "Etsy Access Token", + "shortDescription" : { + "text" : "(?i)(?:etsy)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "facebook", + "name" : "facebook", + "shortDescription" : { + "text" : "(?i)(?:facebook)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "fastly-api-token", + "name" : "Fastly API key", + "shortDescription" : { + "text" : "(?i)(?:fastly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-client-secret", + "name" : "Finicity Client Secret", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-api-token", + "name" : "Finicity API token", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flickr-access-token", + "name" : "Flickr Access Token", + "shortDescription" : { + "text" : "(?i)(?:flickr)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finnhub-access-token", + "name" : "Finnhub Access Token", + "shortDescription" : { + "text" : "(?i)(?:finnhub)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flutterwave-public-key", + "name" : "Finicity Public Key", + "shortDescription" : { + "text" : "FLWPUBK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-secret-key", + "name" : "Flutterwave Secret Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-encryption-key", + "name" : "Flutterwave Encryption Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{12}" + } + }, { + "id" : "frameio-api-token", + "name" : "Frame.io API token", + "shortDescription" : { + "text" : "fio-u-(?i)[a-z0-9\\-_=]{64}" + } + }, { + "id" : "freshbooks-access-token", + "name" : "Freshbooks Access Token", + "shortDescription" : { + "text" : "(?i)(?:freshbooks)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gocardless-api-token", + "name" : "GoCardless API token", + "shortDescription" : { + "text" : "(?i)(?:gocardless)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(live_(?i)[a-z0-9\\-_=]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gcp-api-key", + "name" : "GCP API key", + "shortDescription" : { + "text" : "(?i)\\b(AIza[0-9A-Za-z\\\\-_]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "github-pat", + "name" : "GitHub Personal Access Token", + "shortDescription" : { + "text" : "ghp_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-oauth", + "name" : "GitHub OAuth Access Token", + "shortDescription" : { + "text" : "gho_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-app-token", + "name" : "GitHub App Token", + "shortDescription" : { + "text" : "(ghu|ghs)_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-refresh-token", + "name" : "GitHub Refresh Token", + "shortDescription" : { + "text" : "ghr_[0-9a-zA-Z]{36}" + } + }, { + "id" : "gitlab-pat", + "name" : "Gitlab Personal Access Token", + "shortDescription" : { + "text" : "glpat-[0-9a-zA-Z\\-\\_]{20}" + } + }, { + "id" : "gitter-access-token", + "name" : "Gitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:gitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hashicorp-tf-api-token", + "name" : "HashiCorp Terraform user/org API token", + "shortDescription" : { + "text" : "(?i)[a-z0-9]{14}\\.atlasv1\\.[a-z0-9\\-_=]{60,70}" + } + }, { + "id" : "heroku-api-key", + "name" : "Heroku API Key", + "shortDescription" : { + "text" : "(?i)(?:heroku)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hubspot-api-key", + "name" : "HubSpot API Token", + "shortDescription" : { + "text" : "(?i)(?:hubspot)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "intercom-api-key", + "name" : "Intercom API Token", + "shortDescription" : { + "text" : "(?i)(?:intercom)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{60})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kraken-access-token", + "name" : "Kraken Access Token", + "shortDescription" : { + "text" : "(?i)(?:kraken)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9\\/=_\\+\\-]{80,90})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-access-token", + "name" : "Kucoin Access Token", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-secret-key", + "name" : "Kucoin Secret Key", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "launchdarkly-access-token", + "name" : "Launchdarkly Access Token", + "shortDescription" : { + "text" : "(?i)(?:launchdarkly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linear-api-key", + "name" : "Linear API Token", + "shortDescription" : { + "text" : "lin_api_(?i)[a-z0-9]{40}" + } + }, { + "id" : "linear-client-secret", + "name" : "Linear Client Secret", + "shortDescription" : { + "text" : "(?i)(?:linear)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-id", + "name" : "LinkedIn Client ID", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-secret", + "name" : "LinkedIn Client secret", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-api-key", + "name" : "Lob API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-pub-api-key", + "name" : "Lob Publishable API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailchimp-api-key", + "name" : "Mailchimp API key", + "shortDescription" : { + "text" : "(?i)(?:mailchimp)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32}-us20)(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-pub-key", + "name" : "Mailgun public validation key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-private-api-token", + "name" : "Mailgun private API token", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(key-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-signing-key", + "name" : "Mailgun webhook signing key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mapbox-api-token", + "name" : "MapBox API token", + "shortDescription" : { + "text" : "(?i)(?:mapbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pk\\.[a-z0-9]{60}\\.[a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mattermost-access-token", + "name" : "Mattermost Access Token", + "shortDescription" : { + "text" : "(?i)(?:mattermost)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{26})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-api-token", + "name" : "MessageBird API token", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-client-id", + "name" : "MessageBird client ID", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "netlify-access-token", + "name" : "Netlify Access Token", + "shortDescription" : { + "text" : "(?i)(?:netlify)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40,46})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-key", + "name" : "New Relic user API Key", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-id", + "name" : "New Relic user API ID", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-browser-api-token", + "name" : "New Relic ingest browser API token", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "npm-access-token", + "name" : "npm access token", + "shortDescription" : { + "text" : "(?i)\\b(npm_[a-z0-9]{36})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "nytimes-access-token", + "name" : "Nytimes Access Token", + "shortDescription" : { + "text" : "(?i)(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "okta-access-token", + "name" : "Okta Access Token", + "shortDescription" : { + "text" : "(?i)(?:okta)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{42})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-client-id", + "name" : "Plaid Client ID", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-secret-key", + "name" : "Plaid Secret key", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-api-token", + "name" : "Plaid API Token", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-password", + "name" : "PlanetScale password", + "shortDescription" : { + "text" : "(?i)\\b(pscale_pw_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-api-token", + "name" : "PlanetScale API token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_tkn_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-oauth-token", + "name" : "PlanetScale OAuth token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_oauth_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "postman-api-token", + "name" : "Postman API token", + "shortDescription" : { + "text" : "(?i)\\b(PMAK-(?i)[a-f0-9]{24}\\-[a-f0-9]{34})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "private-key", + "name" : "Private Key", + "shortDescription" : { + "text" : "(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY-----[\\s\\S-]*KEY----" + } + }, { + "id" : "pulumi-api-token", + "name" : "Pulumi API token", + "shortDescription" : { + "text" : "(?i)\\b(pul-[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "pypi-upload-token", + "name" : "PyPI upload token", + "shortDescription" : { + "text" : "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\\-_]{50,1000}" + } + }, { + "id" : "rubygems-api-token", + "name" : "Rubygem API token", + "shortDescription" : { + "text" : "(?i)\\b(rubygems_[a-f0-9]{48})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "rapidapi-access-token", + "name" : "RapidAPI Access Token", + "shortDescription" : { + "text" : "(?i)(?:rapidapi)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-id", + "name" : "Sendbird Access ID", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-token", + "name" : "Sendbird Access Token", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendgrid-api-token", + "name" : "SendGrid API token", + "shortDescription" : { + "text" : "(?i)\\b(SG\\.(?i)[a-z0-9=_\\-\\.]{66})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendinblue-api-token", + "name" : "Sendinblue API token", + "shortDescription" : { + "text" : "(?i)\\b(xkeysib-[a-f0-9]{64}\\-(?i)[a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sentry-access-token", + "name" : "Sentry Access Token", + "shortDescription" : { + "text" : "(?i)(?:sentry)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shippo-api-token", + "name" : "Shippo API token", + "shortDescription" : { + "text" : "(?i)\\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shopify-access-token", + "name" : "Shopify access token", + "shortDescription" : { + "text" : "shpat_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-custom-access-token", + "name" : "Shopify custom access token", + "shortDescription" : { + "text" : "shpca_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-private-app-access-token", + "name" : "Shopify private app access token", + "shortDescription" : { + "text" : "shppa_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-shared-secret", + "name" : "Shopify shared secret", + "shortDescription" : { + "text" : "shpss_[a-fA-F0-9]{32}" + } + }, { + "id" : "slack-access-token", + "name" : "Slack token", + "shortDescription" : { + "text" : "xox[baprs]-([0-9a-zA-Z]{10,48})" + } + }, { + "id" : "slack-web-hook", + "name" : "Slack Webhook", + "shortDescription" : { + "text" : "https:\\/\\/hooks.slack.com\\/services\\/[A-Za-z0-9+\\/]{44,46}" + } + }, { + "id" : "stripe-access-token", + "name" : "Stripe", + "shortDescription" : { + "text" : "(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}" + } + }, { + "id" : "square-access-token", + "name" : "Square Access Token", + "shortDescription" : { + "text" : "(?i)\\b(sq0atp-[0-9A-Za-z\\-_]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "squarespace-access-token", + "name" : "Squarespace Access Token", + "shortDescription" : { + "text" : "(?i)(?:squarespace)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-id", + "name" : "SumoLogic Access ID", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-token", + "name" : "SumoLogic Access Token", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "travisci-access-token", + "name" : "Travis CI Access Token", + "shortDescription" : { + "text" : "(?i)(?:travis)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twilio-api-key", + "name" : "Twilio API Key", + "shortDescription" : { + "text" : "SK[0-9a-fA-F]{32}" + } + }, { + "id" : "twitch-api-token", + "name" : "Twitch API token", + "shortDescription" : { + "text" : "(?i)(?:twitch)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-key", + "name" : "Twitter API Key", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-secret", + "name" : "Twitter API Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-token", + "name" : "Twitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{15,25}-[a-zA-Z0-9]{20,40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-secret", + "name" : "Twitter Access Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{45})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-bearer-token", + "name" : "Twitter Bearer Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(A{22}[a-zA-Z0-9%]{80,100})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "typeform-api-token", + "name" : "Typeform API token", + "shortDescription" : { + "text" : "(?i)(?:typeform)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(tfp_[a-z0-9\\-_\\.=]{59})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-api-key", + "name" : "Yandex API Key", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(AQVN[A-Za-z0-9_\\-]{35,38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-aws-access-token", + "name" : "Yandex AWS Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(YC[a-zA-Z0-9_\\-]{38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-access-token", + "name" : "Yandex Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(t1\\.[A-Z0-9a-z_-]+[=]{0,2}\\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "zendesk-secret-key", + "name" : "Zendesk Secret Key", + "shortDescription" : { + "text" : "(?i)(?:zendesk)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "generic-api-key", + "name" : "Generic API Key", + "shortDescription" : { + "text" : "(?i)(?:key|api|token|secret|client|passwd|password|auth)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-z\\-_.=]{10,150})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + } ] + } + }, + "results" : [ { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/docker-compose.yml." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/docker-compose.yml" + }, + "region" : { + "startLine" : 12, + "startColumn" : 14, + "endLine" : 13, + "endColumn" : 1, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sechub.severity" : "invalid-value" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/src/api/application/config/database.php." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/src/api/application/config/database.php" + }, + "region" : { + "startLine" : 80, + "startColumn" : 7, + "endLine" : 80, + "endColumn" : 61, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sechub.severity" : "another-invalid-value-1234" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + } ] + } ] +} \ No newline at end of file diff --git a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json new file mode 100644 index 0000000000..5d99a890f8 --- /dev/null +++ b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json @@ -0,0 +1,974 @@ +{ + "$schema" : "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json", + "version" : "2.1.0", + "runs" : [ { + "tool" : { + "driver" : { + "name" : "gitleaks", + "semanticVersion" : "v8.0.0", + "rules" : [ { + "id" : "adafruit-api-key", + "name" : "Adafruit API Key", + "shortDescription" : { + "text" : "(?i)(?:adafruit)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-id", + "name" : "Adobe Client ID (Oauth Web)", + "shortDescription" : { + "text" : "(?i)(?:adobe)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "adobe-client-secret", + "name" : "Adobe Client Secret", + "shortDescription" : { + "text" : "(?i)\\b((p8e-)(?i)[a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "age secret key", + "name" : "Age secret key", + "shortDescription" : { + "text" : "AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}" + } + }, { + "id" : "airtable-api-key", + "name" : "Airtable API Key", + "shortDescription" : { + "text" : "(?i)(?:airtable)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{17})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "algolia-api-key", + "name" : "Algolia API Key", + "shortDescription" : { + "text" : "(?i)(?:algolia)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-access-key-id", + "name" : "Alibaba AccessKey ID", + "shortDescription" : { + "text" : "(?i)\\b((LTAI)(?i)[a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "alibaba-secret-key", + "name" : "Alibaba Secret Key", + "shortDescription" : { + "text" : "(?i)(?:alibaba)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-id", + "name" : "Asana Client ID", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "asana-client-secret", + "name" : "Asana Client Secret", + "shortDescription" : { + "text" : "(?i)(?:asana)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "atlassian-api-token", + "name" : "Atlassian API token", + "shortDescription" : { + "text" : "(?i)(?:atlassian|confluence|jira)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "aws-access-token", + "name" : "AWS", + "shortDescription" : { + "text" : "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" + } + }, { + "id" : "bitbucket-client-id", + "name" : "BitBucket Client ID", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bitbucket-client-secret", + "name" : "BitBucket Client Secret", + "shortDescription" : { + "text" : "(?i)(?:bitbucket)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-access-key", + "name" : "Bittrex Access Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "bittrex-secret-key", + "name" : "Bittrex Secret Key", + "shortDescription" : { + "text" : "(?i)(?:bittrex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "beamer-api-token", + "name" : "Beamer API token", + "shortDescription" : { + "text" : "(?i)(?:beamer)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(b_[a-z0-9=_\\-]{44})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "codecov-access-token", + "name" : "Codecov Access Token", + "shortDescription" : { + "text" : "(?i)(?:codecov)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "coinbase-access-token", + "name" : "Coinbase Access Token", + "shortDescription" : { + "text" : "(?i)(?:coinbase)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "clojars-api-token", + "name" : "Clojars API token", + "shortDescription" : { + "text" : "(?i)(CLOJARS_)[a-z0-9]{60}" + } + }, { + "id" : "confluent-access-token", + "name" : "Confluent Access Token", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "confluent-secret-key", + "name" : "Confluent Secret Key", + "shortDescription" : { + "text" : "(?i)(?:confluent)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "contentful-delivery-api-token", + "name" : "Contentful delivery API token", + "shortDescription" : { + "text" : "(?i)(?:contentful)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "databricks-api-token", + "name" : "Databricks API token", + "shortDescription" : { + "text" : "(?i)\\b(dapi[a-h0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "datadog-access-token", + "name" : "Datadog Access Token", + "shortDescription" : { + "text" : "(?i)(?:datadog)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-api-token", + "name" : "Discord API key", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-id", + "name" : "Discord client ID", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{18})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "discord-client-secret", + "name" : "Discord client secret", + "shortDescription" : { + "text" : "(?i)(?:discord)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "doppler-api-token", + "name" : "Doppler API token", + "shortDescription" : { + "text" : "(dp\\.pt\\.)(?i)[a-z0-9]{43}" + } + }, { + "id" : "dropbox-api-token", + "name" : "Dropbox API secret", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{15})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-long-lived-api-token", + "name" : "Dropbox long lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\\-_=]{43})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "dropbox-short-lived-api-token", + "name" : "Dropbox short lived API token", + "shortDescription" : { + "text" : "(?i)(?:dropbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(sl\\.[a-z0-9\\-=_]{135})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "droneci-access-token", + "name" : "Droneci Access Token", + "shortDescription" : { + "text" : "(?i)(?:droneci)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "duffel-api-token", + "name" : "Duffel API token", + "shortDescription" : { + "text" : "duffel_(test|live)_(?i)[a-z0-9_\\-=]{43}" + } + }, { + "id" : "dynatrace-api-token", + "name" : "Dynatrace API token", + "shortDescription" : { + "text" : "dt0c01\\.(?i)[a-z0-9]{24}\\.[a-z0-9]{64}" + } + }, { + "id" : "easypost-api-token", + "name" : "EasyPost API token", + "shortDescription" : { + "text" : "EZAK(?i)[a-z0-9]{54}" + } + }, { + "id" : "easypost-test-api-token", + "name" : "EasyPost test API token", + "shortDescription" : { + "text" : "EZTK(?i)[a-z0-9]{54}" + } + }, { + "id" : "etsy-access-token", + "name" : "Etsy Access Token", + "shortDescription" : { + "text" : "(?i)(?:etsy)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "facebook", + "name" : "facebook", + "shortDescription" : { + "text" : "(?i)(?:facebook)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "fastly-api-token", + "name" : "Fastly API key", + "shortDescription" : { + "text" : "(?i)(?:fastly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-client-secret", + "name" : "Finicity Client Secret", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finicity-api-token", + "name" : "Finicity API token", + "shortDescription" : { + "text" : "(?i)(?:finicity)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flickr-access-token", + "name" : "Flickr Access Token", + "shortDescription" : { + "text" : "(?i)(?:flickr)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "finnhub-access-token", + "name" : "Finnhub Access Token", + "shortDescription" : { + "text" : "(?i)(?:finnhub)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{20})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "flutterwave-public-key", + "name" : "Finicity Public Key", + "shortDescription" : { + "text" : "FLWPUBK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-secret-key", + "name" : "Flutterwave Secret Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{32}-X" + } + }, { + "id" : "flutterwave-encryption-key", + "name" : "Flutterwave Encryption Key", + "shortDescription" : { + "text" : "FLWSECK_TEST-(?i)[a-h0-9]{12}" + } + }, { + "id" : "frameio-api-token", + "name" : "Frame.io API token", + "shortDescription" : { + "text" : "fio-u-(?i)[a-z0-9\\-_=]{64}" + } + }, { + "id" : "freshbooks-access-token", + "name" : "Freshbooks Access Token", + "shortDescription" : { + "text" : "(?i)(?:freshbooks)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gocardless-api-token", + "name" : "GoCardless API token", + "shortDescription" : { + "text" : "(?i)(?:gocardless)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(live_(?i)[a-z0-9\\-_=]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "gcp-api-key", + "name" : "GCP API key", + "shortDescription" : { + "text" : "(?i)\\b(AIza[0-9A-Za-z\\\\-_]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "github-pat", + "name" : "GitHub Personal Access Token", + "shortDescription" : { + "text" : "ghp_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-oauth", + "name" : "GitHub OAuth Access Token", + "shortDescription" : { + "text" : "gho_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-app-token", + "name" : "GitHub App Token", + "shortDescription" : { + "text" : "(ghu|ghs)_[0-9a-zA-Z]{36}" + } + }, { + "id" : "github-refresh-token", + "name" : "GitHub Refresh Token", + "shortDescription" : { + "text" : "ghr_[0-9a-zA-Z]{36}" + } + }, { + "id" : "gitlab-pat", + "name" : "Gitlab Personal Access Token", + "shortDescription" : { + "text" : "glpat-[0-9a-zA-Z\\-\\_]{20}" + } + }, { + "id" : "gitter-access-token", + "name" : "Gitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:gitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hashicorp-tf-api-token", + "name" : "HashiCorp Terraform user/org API token", + "shortDescription" : { + "text" : "(?i)[a-z0-9]{14}\\.atlasv1\\.[a-z0-9\\-_=]{60,70}" + } + }, { + "id" : "heroku-api-key", + "name" : "Heroku API Key", + "shortDescription" : { + "text" : "(?i)(?:heroku)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "hubspot-api-key", + "name" : "HubSpot API Token", + "shortDescription" : { + "text" : "(?i)(?:hubspot)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "intercom-api-key", + "name" : "Intercom API Token", + "shortDescription" : { + "text" : "(?i)(?:intercom)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{60})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kraken-access-token", + "name" : "Kraken Access Token", + "shortDescription" : { + "text" : "(?i)(?:kraken)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9\\/=_\\+\\-]{80,90})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-access-token", + "name" : "Kucoin Access Token", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "kucoin-secret-key", + "name" : "Kucoin Secret Key", + "shortDescription" : { + "text" : "(?i)(?:kucoin)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "launchdarkly-access-token", + "name" : "Launchdarkly Access Token", + "shortDescription" : { + "text" : "(?i)(?:launchdarkly)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linear-api-key", + "name" : "Linear API Token", + "shortDescription" : { + "text" : "lin_api_(?i)[a-z0-9]{40}" + } + }, { + "id" : "linear-client-secret", + "name" : "Linear Client Secret", + "shortDescription" : { + "text" : "(?i)(?:linear)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-id", + "name" : "LinkedIn Client ID", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "linkedin-client-secret", + "name" : "LinkedIn Client secret", + "shortDescription" : { + "text" : "(?i)(?:linkedin|linked-in)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-api-key", + "name" : "Lob API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "lob-pub-api-key", + "name" : "Lob Publishable API Key", + "shortDescription" : { + "text" : "(?i)(?:lob)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailchimp-api-key", + "name" : "Mailchimp API key", + "shortDescription" : { + "text" : "(?i)(?:mailchimp)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{32}-us20)(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-pub-key", + "name" : "Mailgun public validation key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-private-api-token", + "name" : "Mailgun private API token", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(key-[a-f0-9]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mailgun-signing-key", + "name" : "Mailgun webhook signing key", + "shortDescription" : { + "text" : "(?i)(?:mailgun)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mapbox-api-token", + "name" : "MapBox API token", + "shortDescription" : { + "text" : "(?i)(?:mapbox)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(pk\\.[a-z0-9]{60}\\.[a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "mattermost-access-token", + "name" : "Mattermost Access Token", + "shortDescription" : { + "text" : "(?i)(?:mattermost)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{26})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-api-token", + "name" : "MessageBird API token", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "messagebird-client-id", + "name" : "MessageBird client ID", + "shortDescription" : { + "text" : "(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "netlify-access-token", + "name" : "Netlify Access Token", + "shortDescription" : { + "text" : "(?i)(?:netlify)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{40,46})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-key", + "name" : "New Relic user API Key", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-user-api-id", + "name" : "New Relic user API ID", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "new-relic-browser-api-token", + "name" : "New Relic ingest browser API token", + "shortDescription" : { + "text" : "(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "npm-access-token", + "name" : "npm access token", + "shortDescription" : { + "text" : "(?i)\\b(npm_[a-z0-9]{36})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "nytimes-access-token", + "name" : "Nytimes Access Token", + "shortDescription" : { + "text" : "(?i)(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{32})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "okta-access-token", + "name" : "Okta Access Token", + "shortDescription" : { + "text" : "(?i)(?:okta)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9=_\\-]{42})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-client-id", + "name" : "Plaid Client ID", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{24})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-secret-key", + "name" : "Plaid Secret key", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "plaid-api-token", + "name" : "Plaid API Token", + "shortDescription" : { + "text" : "(?i)(?:plaid)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-password", + "name" : "PlanetScale password", + "shortDescription" : { + "text" : "(?i)\\b(pscale_pw_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-api-token", + "name" : "PlanetScale API token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_tkn_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "planetscale-oauth-token", + "name" : "PlanetScale OAuth token", + "shortDescription" : { + "text" : "(?i)\\b(pscale_oauth_(?i)[a-z0-9=\\-_\\.]{32,64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "postman-api-token", + "name" : "Postman API token", + "shortDescription" : { + "text" : "(?i)\\b(PMAK-(?i)[a-f0-9]{24}\\-[a-f0-9]{34})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "private-key", + "name" : "Private Key", + "shortDescription" : { + "text" : "(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY-----[\\s\\S-]*KEY----" + } + }, { + "id" : "pulumi-api-token", + "name" : "Pulumi API token", + "shortDescription" : { + "text" : "(?i)\\b(pul-[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "pypi-upload-token", + "name" : "PyPI upload token", + "shortDescription" : { + "text" : "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\\-_]{50,1000}" + } + }, { + "id" : "rubygems-api-token", + "name" : "Rubygem API token", + "shortDescription" : { + "text" : "(?i)\\b(rubygems_[a-f0-9]{48})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "rapidapi-access-token", + "name" : "RapidAPI Access Token", + "shortDescription" : { + "text" : "(?i)(?:rapidapi)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9_-]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-id", + "name" : "Sendbird Access ID", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendbird-access-token", + "name" : "Sendbird Access Token", + "shortDescription" : { + "text" : "(?i)(?:sendbird)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendgrid-api-token", + "name" : "SendGrid API token", + "shortDescription" : { + "text" : "(?i)\\b(SG\\.(?i)[a-z0-9=_\\-\\.]{66})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sendinblue-api-token", + "name" : "Sendinblue API token", + "shortDescription" : { + "text" : "(?i)\\b(xkeysib-[a-f0-9]{64}\\-(?i)[a-z0-9]{16})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sentry-access-token", + "name" : "Sentry Access Token", + "shortDescription" : { + "text" : "(?i)(?:sentry)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shippo-api-token", + "name" : "Shippo API token", + "shortDescription" : { + "text" : "(?i)\\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "shopify-access-token", + "name" : "Shopify access token", + "shortDescription" : { + "text" : "shpat_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-custom-access-token", + "name" : "Shopify custom access token", + "shortDescription" : { + "text" : "shpca_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-private-app-access-token", + "name" : "Shopify private app access token", + "shortDescription" : { + "text" : "shppa_[a-fA-F0-9]{32}" + } + }, { + "id" : "shopify-shared-secret", + "name" : "Shopify shared secret", + "shortDescription" : { + "text" : "shpss_[a-fA-F0-9]{32}" + } + }, { + "id" : "slack-access-token", + "name" : "Slack token", + "shortDescription" : { + "text" : "xox[baprs]-([0-9a-zA-Z]{10,48})" + } + }, { + "id" : "slack-web-hook", + "name" : "Slack Webhook", + "shortDescription" : { + "text" : "https:\\/\\/hooks.slack.com\\/services\\/[A-Za-z0-9+\\/]{44,46}" + } + }, { + "id" : "stripe-access-token", + "name" : "Stripe", + "shortDescription" : { + "text" : "(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}" + } + }, { + "id" : "square-access-token", + "name" : "Square Access Token", + "shortDescription" : { + "text" : "(?i)\\b(sq0atp-[0-9A-Za-z\\-_]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "squarespace-access-token", + "name" : "Squarespace Access Token", + "shortDescription" : { + "text" : "(?i)(?:squarespace)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-id", + "name" : "SumoLogic Access ID", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{14})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "sumologic-access-token", + "name" : "SumoLogic Access Token", + "shortDescription" : { + "text" : "(?i)(?:sumo)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{64})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "travisci-access-token", + "name" : "Travis CI Access Token", + "shortDescription" : { + "text" : "(?i)(?:travis)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{22})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twilio-api-key", + "name" : "Twilio API Key", + "shortDescription" : { + "text" : "SK[0-9a-fA-F]{32}" + } + }, { + "id" : "twitch-api-token", + "name" : "Twitch API token", + "shortDescription" : { + "text" : "(?i)(?:twitch)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{30})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-key", + "name" : "Twitter API Key", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{25})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-api-secret", + "name" : "Twitter API Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{50})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-token", + "name" : "Twitter Access Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9]{15,25}-[a-zA-Z0-9]{20,40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-access-secret", + "name" : "Twitter Access Secret", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{45})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "twitter-bearer-token", + "name" : "Twitter Bearer Token", + "shortDescription" : { + "text" : "(?i)(?:twitter)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(A{22}[a-zA-Z0-9%]{80,100})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "typeform-api-token", + "name" : "Typeform API token", + "shortDescription" : { + "text" : "(?i)(?:typeform)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(tfp_[a-z0-9\\-_\\.=]{59})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-api-key", + "name" : "Yandex API Key", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(AQVN[A-Za-z0-9_\\-]{35,38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-aws-access-token", + "name" : "Yandex AWS Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(YC[a-zA-Z0-9_\\-]{38})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "yandex-access-token", + "name" : "Yandex Access Token", + "shortDescription" : { + "text" : "(?i)(?:yandex)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}(t1\\.[A-Z0-9a-z_-]+[=]{0,2}\\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "zendesk-secret-key", + "name" : "Zendesk Secret Key", + "shortDescription" : { + "text" : "(?i)(?:zendesk)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-z0-9]{40})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + }, { + "id" : "generic-api-key", + "name" : "Generic API Key", + "shortDescription" : { + "text" : "(?i)(?:key|api|token|secret|client|passwd|password|auth)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|>|:=|\\|\\|:|<=|=>|:)(?:'|\\\"|\\s|=|\\x60){0,5}([0-9a-z\\-_.=]{10,150})(?:['|\\\"|\\n|\\r|\\s|\\x60]|$)" + } + } ] + } + }, + "results" : [ { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/docker-compose.yml." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/docker-compose.yml" + }, + "region" : { + "startLine" : 12, + "startColumn" : 14, + "endLine" : 13, + "endColumn" : 1, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sechub.severity" : "info" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/src/api/application/config/database.php." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/src/api/application/config/database.php" + }, + "region" : { + "startLine" : 80, + "startColumn" : 7, + "endLine" : 80, + "endColumn" : 61, + "snippet" : { + "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sechub.severity" : "unclassified" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/web/src/app/thunks/Authentication/ForgotPassword/handleForgotPasswordGetOTPThunk.tsx" + }, + "region" : { + "startLine" : 32, + "startColumn" : 14, + "endLine" : 32, + "endColumn" : 56, + "snippet" : { + "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + }, + "properties" : { + "secretscan.sechub.severity" : "low" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/Backend/web/src/app/thunks/OTP/handleGetOTPThunk.tsx" + }, + "region" : { + "startLine" : 31, + "startColumn" : 14, + "endLine" : 31, + "endColumn" : 56, + "snippet" : { + "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + }, + "properties" : { + "secretscan.sechub.severity" : "medium" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/iOS/Source Code/Podfile.lock." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/iOS/Source Code/Podfile.lock" + }, + "region" : { + "startLine" : 23, + "startColumn" : 4, + "endLine" : 24, + "endColumn" : 1, + "snippet" : { + "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + }, + "properties" : { + "secretscan.sechub.severity" : "high" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + }, { + "ruleId" : "generic-api-key", + "message" : { + "text" : "generic-api-key has detected secret for file UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock." + }, + "locations" : [ { + "physicalLocation" : { + "artifactLocation" : { + "uri" : "UnSAFE_Bank/iOS/Source Code/Pods/Manifest.lock" + }, + "region" : { + "startLine" : 23, + "startColumn" : 4, + "endLine" : 24, + "endColumn" : 1, + "snippet" : { + "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + }, + "properties" : { + "secretscan.sechub.severity" : "critical" + } + } + } + } ], + "partialFingerprints" : { + "commitSha" : "", + "email" : "", + "author" : "", + "date" : "", + "commitMessage" : "" + } + } ] + } ] +} \ No newline at end of file From 16ca2945cc30b8497e54e8024e47ad4cf8c0aca9 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 17 Jul 2024 08:11:55 +0200 Subject: [PATCH 03/10] PR review changes #3280 - fix typos - improve documentation - change sereco Sarif import to use enum instead of strings - simplify response validation service and add unit test - refactor categorization with better readability - split execution service into multiple methods - split validation web request service into multiple methods - improve spring boot with custom assert method - improve setters for list fields of configuration model - improve readability of execution context factory test --- .../GitleaksSarifImportWorkaround.java | 18 ++- .../SarifImportProductWorkaround.java | 4 +- .../SarifImportProductWorkaroundSupport.java | 10 +- .../sereco/importer/SarifV1JSONImporter.java | 7 +- sechub-wrapper-secret-validator/README.adoc | 32 ++--- .../execution/ResponseValidationService.java | 42 ++++--- .../execution/SecretValidationStatus.java | 2 + .../SecretValidatorExecutionService.java | 52 +++++---- .../SecretValidatorWebRequestService.java | 109 +++++++++++------- ...erecoSeveritySarifEnhancementService.java} | 4 +- .../SecretValidatorConfigurationModel.java | 13 ++- ...SecretValidatorConfigurationModelList.java | 15 ++- .../model/SecretValidatorRequest.java | 13 ++- .../SecretValidatorResponseContains.java | 26 ++++- .../cli/SecretValidatorSpringBootTest.java | 27 ++--- .../ResponseValidationServiceTest.java | 16 ++- ...tValidatorExecutionContextFactoryTest.java | 73 +++++------- .../SecretValidatorExecutionServiceTest.java | 20 ++-- .../SecretValidatorWebRequestServiceTest.java | 11 +- ...oSeveritySarifEnhancementServiceTest.java} | 20 ++-- ...etValidatorConfigurationModelListTest.java | 2 +- 21 files changed, 308 insertions(+), 208 deletions(-) rename sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/{SecretValidatorCategorizationService.java => SerecoSeveritySarifEnhancementService.java} (88%) rename sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/{SecretValidatorCategorizationServiceTest.java => SerecoSeveritySarifEnhancementServiceTest.java} (88%) diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java index a21e41bbe4..7d9857c198 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java @@ -6,7 +6,18 @@ import org.springframework.stereotype.Component; -import de.jcup.sarif_2_1_0.model.*; +import com.mercedesbenz.sechub.sereco.metadata.SerecoSeverity; + +import de.jcup.sarif_2_1_0.model.Location; +import de.jcup.sarif_2_1_0.model.PartialFingerprints; +import de.jcup.sarif_2_1_0.model.PhysicalLocation; +import de.jcup.sarif_2_1_0.model.PropertyBag; +import de.jcup.sarif_2_1_0.model.Region; +import de.jcup.sarif_2_1_0.model.ReportingDescriptor; +import de.jcup.sarif_2_1_0.model.Result; +import de.jcup.sarif_2_1_0.model.Run; +import de.jcup.sarif_2_1_0.model.Tool; +import de.jcup.sarif_2_1_0.model.ToolComponent; @Component public class GitleaksSarifImportWorkaround implements SarifImportProductWorkaround { @@ -39,7 +50,7 @@ public String resolveFindingRevisionId(Result result, Run run) { } @Override - public String resolveCustomSechubSeverity(Result result, Run run) { + public SerecoSeverity resolveCustomSerecoSeverity(Result result, Run run) { if (result == null) { return null; } @@ -67,7 +78,8 @@ public String resolveCustomSechubSeverity(Result result, Run run) { return null; } String severityKey = SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey(); - return (String) additionalProperties.get(severityKey); + String severityValue = (String) additionalProperties.get(severityKey); + return SerecoSeverity.fromString(severityValue); } private boolean isGitleaksRun(Run run) { diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java index 9e3e460719..d53b5ca2de 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaround.java @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.sereco.importer; +import com.mercedesbenz.sechub.sereco.metadata.SerecoSeverity; + import de.jcup.sarif_2_1_0.model.ReportingDescriptor; import de.jcup.sarif_2_1_0.model.Result; import de.jcup.sarif_2_1_0.model.Run; @@ -23,7 +25,7 @@ public default String resolveFindingRevisionId(Result result, Run run) { return null; } - public default String resolveCustomSechubSeverity(Result result, Run run) { + public default SerecoSeverity resolveCustomSerecoSeverity(Result result, Run run) { return null; } } diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java index 7bb20f5072..1598b54808 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImportProductWorkaroundSupport.java @@ -7,6 +7,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.mercedesbenz.sechub.sereco.metadata.SerecoSeverity; + import de.jcup.sarif_2_1_0.model.ReportingDescriptor; import de.jcup.sarif_2_1_0.model.Result; import de.jcup.sarif_2_1_0.model.Run; @@ -58,12 +60,12 @@ private R visitAllWorkaroundsAndUseFirstResultNotNull(E element, Run run, return null; } - public String resolveCustomSechubSeverity(Result result, Run run) { - return visitAllWorkaroundsAndUseFirstResultNotNull(result, run, new WorkaroundVisitor() { + public SerecoSeverity resolveCustomSechubSeverity(Result result, Run run) { + return visitAllWorkaroundsAndUseFirstResultNotNull(result, run, new WorkaroundVisitor() { @Override - public String visit(Result element, Run run, SarifImportProductWorkaround workaround) { - return workaround.resolveCustomSechubSeverity(result, run); + public SerecoSeverity visit(Result element, Run run, SarifImportProductWorkaround workaround) { + return workaround.resolveCustomSerecoSeverity(result, run); } }); } diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java index 32389bbcfb..e95b956b90 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifV1JSONImporter.java @@ -285,8 +285,7 @@ private void handleWebRequest(Result result, SerecoWeb serecoWeb) { } private SerecoSeverity resolveSeverity(Result result, Run run) { - String customSecHubSeverity = workaroundSupport.resolveCustomSechubSeverity(result, run); - SerecoSeverity serecoSeverity = severityFromString(customSecHubSeverity); + SerecoSeverity serecoSeverity = workaroundSupport.resolveCustomSechubSeverity(result, run); if (serecoSeverity == null) { Level level = sarifSchema210LogicSupport.resolveLevel(result, run); return mapToSeverity(level); @@ -528,10 +527,6 @@ private SerecoSeverity mapToSeverity(Level level) { } } - private SerecoSeverity severityFromString(String customSecHubSeverity) { - return SerecoSeverity.fromString(customSecHubSeverity); - } - @Override public boolean isAbleToImportForProduct(ImportParameter param) { /* first we do the simple check... */ diff --git a/sechub-wrapper-secret-validator/README.adoc b/sechub-wrapper-secret-validator/README.adoc index 24aecb81d2..842ed2b029 100644 --- a/sechub-wrapper-secret-validator/README.adoc +++ b/sechub-wrapper-secret-validator/README.adoc @@ -4,8 +4,8 @@ This wrapper is a Spring Boot application, that is supposed to run on PDS solutions running performing secret scan. After the secret scanning tool is done it will try to validate secrets found and enhance the SARIF report with a custom PropertyBag for each finding location. It will add a custom severity with the key `secretscan.sechub.severity` and -one of the following values `["info", "unclassified", "low", "medium", "high", "critical"]` to the SARIF PropertyBag which contains a generic map for custom values. -This values can then be used by the `sechub-sereco` module to improve the severity categorization of a finding. +one of the following values `["info", "unclassified", "low", "medium", "high", "critical"]` to a SARIF PropertyBag which contains a generic map for custom values. +This values can then be used by the `sechub-sereco` module to improve the severity categorization of a finding. We add this custom severities with a `PropertyBag` because the SARIF default called `Level` does not support `CRITICAL`. === Usage @@ -13,7 +13,7 @@ This values can then be used by the `sechub-sereco` module to improve the severi The wrapper application is an executable jar and needs no command line arguments. It can automatically use all https://mercedes-benz.github.io/sechub/latest/sechub-product-delegation-server.html#launcher-scripts[standard PDS environment variables] -and following special mandatory environment variables: +and following special mandatory environment variable: ---- SECRET_VALIDATOR_CONFIGFILE @@ -21,8 +21,8 @@ SECRET_VALIDATOR_CONFIGFILE [IMPORTANT] ==== -This files contains the configuration for each secret type, which basically tells to wrapper how to validate secrets of a certain type. -For each product a custom file is necessary, where you should use the SARIF `ruleId` to identify each configuration. +The file, which must be configured by `SECRET_VALIDATOR_CONFIGFILE`, contains the configuration for each secret type, which basically tells the wrapper application how to validate secrets of a certain type. +For each product a custom file is necessary, where some kind of finding identifier should be used, like the SARIF `ruleId` to identify each configuration. From the https://mercedes-benz.github.io/sechub/latest/sechub-product-delegation-server.html#launcher-scripts[standard PDS environment variables] only the `PDS_JOB_RESULT_FILE` is mandatory because without a valid SARIF report from a secret scanning tool no validations can be done. ==== @@ -55,20 +55,20 @@ only the `PDS_JOB_RESULT_FILE` is mandatory because without a valid SARIF report } ] } ``` -<1> Define a list of configuration, for each type of secret identified by the rule id. +<1> Define a list of configuration entries. One entry represents a type of secret identified by a dedicated rule id. <2> The `ruleId` identifies this configuration so the requests defined in the later section are performed for each finding of this type. -<3> Your `categorization` configuration. If empty no categorization will be performed, otherwise: -- The `defaultSeverity` will be applied if no requests are defined but you for this type of secret. +<3> The `categorization` configuration. If empty no categorization will be performed, otherwise: +- The `defaultSeverity` will be applied if there are no requests defined for this type of secret. - The `validationFailedSeverity` will be applied if all validation requests failed for this secret. - The `validationSuccessSeverity` will be applied if the secret was successfully validated with one of the requests defined. -<4> The `requests` array defines all requests you know how to validate a secret of this certain type. -This is an array because for some secrets you might need to validate against multiple e.g. when you have AWS credentials found with your secret scan. -You might want to be able to check if it is valid for the public AWS or your internal AWS instances if you have some: -- With `proxyRequired` you can specify if the URL can only be accessed using a proxy server. -- With `url` you specify the URL the request will be performed to. -- With `headers` you specify the header `name` and `valuePrefix` if necessary for the secret found. +<4> The `requests` array defines all known requests to validate a secret of this certain type. +This is an array because for some secrets it might be necessary to validate against multiple servers e.g. when a company uses multiple AWS instances. +It might be necessary to perform validation requests to all possible AWS instances to check if a secret is valid for any of them: +- `proxyRequired` specifies if the URL can only be accessed using a proxy server. +- `url` specifies the URL the request will be performed to. +- `headers` specifies the header `name` and `valuePrefix` if necessary for the secret found. It is an array because it could be useful in the future. Currently the header is used for the secret because it is assumed to be a token send via HTTP header. -<5> The `expectedResponse` section contains information you expect on a request with a valid secret, +<5> The `expectedResponse` section contains information expected on a request with a valid secret, like a specific `httpStatus` code or the response body should contain `allOf` or `oneOf` certain strings. @@ -82,7 +82,7 @@ SECRET_VALIDATOR_TRUSTALLCERTIFICATES [TIP] ==== When `SECRET_VALIDATOR_TRUSTALLCERTIFICATES` set to `true`, certificate errors on validation web requests will be ignored. -This can be useful, if you are in a environment that needs a proxy server to access certain URLs you have in your configuration. +This can be useful, in certain situations or setups. ==== ===== Proxy configuration diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java index e492332395..a2eb3a71a4 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationService.java @@ -16,22 +16,27 @@ public boolean isValidResponse(HttpResponse response, SecretValidatorRes return false; } int expectedHttpStatus = secretValidatorResponse.getHttpStatus(); - // if no expected HTTP status code was configured inside the config we ignore it + SecretValidatorResponseContains containsSection = secretValidatorResponse.getContains(); + + // if the expected status is not set and no contains section is set, the secret + // cannot be validated + if (expectedHttpStatus <= 0 && hasNoContainsSection(containsSection)) { + return false; + } + + // no contains section set, so we use the status code + if (hasNoContainsSection(containsSection)) { + return expectedHttpStatus == response.statusCode(); + } + + // contains section and expected status code set, both must be valid if (expectedHttpStatus > 0) { - // no contains section specified, we return the result of the checked status - // code - if (hasNoContainsSection(secretValidatorResponse.getContains())) { - return expectedHttpStatus == response.statusCode(); - } - return containsExpectedSnippets(secretValidatorResponse.getContains(), response.body()); - } else { - // no contains section specified, we return false, since nothing was specified - // at all to check the response - if (hasNoContainsSection(secretValidatorResponse.getContains())) { - return false; - } - return containsExpectedSnippets(secretValidatorResponse.getContains(), response.body()); + boolean valid = expectedHttpStatus == response.statusCode(); + return valid && containsExpectedSnippets(containsSection, response.body()); } + + // fallback if only a contains section was configured + return containsExpectedSnippets(containsSection, response.body()); } private boolean hasNoContainsSection(SecretValidatorResponseContains contains) { @@ -42,18 +47,11 @@ private boolean hasNoContainsSection(SecretValidatorResponseContains contains) { } private boolean containsExpectedSnippets(SecretValidatorResponseContains contains, String body) { - // body should not be null since contains section should be specified at this - // point + // body and contains section should be specified at this point if (body == null || contains == null) { return false; } - // at the point where this method gets called we require the contains section to - // be configured - if (hasNoContainsSection(contains)) { - return false; - } - for (String substring : contains.getAllOf()) { // all must be present if (!body.contains(substring)) { diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java index 356adff916..d7a2538292 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationStatus.java @@ -9,6 +9,8 @@ public enum SecretValidationStatus { NO_VALIDATION_CONFIGURED("No validation URLs are configured for this type of secret!"), + ALL_VALIDATION_REQUESTS_FAILED("All request to validate a secret failed, due to network or connection errors!"), + SARIF_SNIPPET_NOT_SET("SARIF finding does not contain a valid snippet to validate!"),; private String description; diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java index fa31f36446..6ff9d4b38b 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java @@ -30,7 +30,7 @@ public class SecretValidatorExecutionService { SecretValidationService validationService; @Autowired - SecretValidatorCategorizationService categorizationService; + SerecoSeveritySarifEnhancementService sarifEnhancementService; @Autowired SarifValidationSupport sarifValidationSupport; @@ -44,31 +44,41 @@ public SarifSchema210 execute() { for (Run run : runs) { List findings = run.getResults(); for (Result finding : findings) { - if (!sarifValidationSupport.findingCanBeValidated(finding)) { - continue; - } SecretValidatorConfigurationModel config = validatorConfiguration.get(finding.getRuleId()); - if (config == null) { - LOG.info("No config found to validate findings of rule: {}", finding.getRuleId()); - continue; - } - SecretValidatorCategorization categorization = config.getCategorization(); - if (categorization == null || categorization.isEmpty()) { - LOG.info("No config found to categorize findings of rule: {}", finding.getRuleId()); - continue; - } - for (Location location : finding.getLocations()) { - if (!sarifValidationSupport.findingLocationCanBeValidated(location)) { - continue; - } - Region findingRegion = location.getPhysicalLocation().getRegion(); - SecretValidationResult validationResult = validationService.validateFindingByRegion(findingRegion, config.getRequests(), - executionContext.isTrustAllCertificates()); - categorizationService.categorizeFindingByRegion(validationResult, findingRegion, config.getCategorization()); + if (isValidationPossible(config, finding)) { + validateFindingAndEnhanceSarif(executionContext, config, finding); } } } return executionContext.getSarifReport(); } + private boolean isValidationPossible(SecretValidatorConfigurationModel config, Result finding) { + if (!sarifValidationSupport.findingCanBeValidated(finding)) { + return false; + } + if (config == null) { + LOG.info("No config found to validate findings of rule: {}", finding.getRuleId()); + return false; + } + SecretValidatorCategorization categorization = config.getCategorization(); + if (categorization == null || categorization.isEmpty()) { + LOG.info("No config found to categorize findings of rule: {}", finding.getRuleId()); + return false; + } + return true; + } + + private void validateFindingAndEnhanceSarif(SecretValidatorExecutionContext executionContext, SecretValidatorConfigurationModel config, Result finding) { + for (Location location : finding.getLocations()) { + if (!sarifValidationSupport.findingLocationCanBeValidated(location)) { + continue; + } + Region findingRegion = location.getPhysicalLocation().getRegion(); + SecretValidationResult validationResult = validationService.validateFindingByRegion(findingRegion, config.getRequests(), + executionContext.isTrustAllCertificates()); + sarifEnhancementService.addSerecoSeverityInfo(validationResult, findingRegion, config.getCategorization()); + } + } + } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java index 963cc0e4cf..ad529498af 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.net.URL; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; @@ -30,59 +31,70 @@ public class SecretValidatorWebRequestService { ResponseValidationService responseValidationService; public SecretValidationResult validateFinding(String snippetText, List requests, boolean trustAllCertificates) { + SecretValidationResult validationResult = assertValidParams(snippetText, requests); + if (validationResult != null) { + return validationResult; + } + HttpClient proxyHttpClient = httpClientFactory.createProxyHttpClient(trustAllCertificates); HttpClient directHttpClient = httpClientFactory.createDirectHttpClient(trustAllCertificates); + HttpResponse response = null; + for (SecretValidatorRequest request : requests) { + + if (isRequestValid(request)) { + response = createAndExecuteHttpRequest(snippetText, proxyHttpClient, directHttpClient, request); + if (responseValidationService.isValidResponse(response, request.getExpectedResponse())) { + LOG.info("Finding is valid!"); + return createValidationResult(SecretValidationStatus.VALID, request.getUrl()); + } + } + } + if (response == null) { + return createValidationResult(SecretValidationStatus.ALL_VALIDATION_REQUESTS_FAILED); + } + return createValidationResult(SecretValidationStatus.INVALID); + } + + private SecretValidationResult assertValidParams(String snippetText, List requests) { if (snippetText == null || snippetText.isBlank()) { LOG.warn("Cannot validate finding because the SARIF snippet text is null or empty."); - SecretValidationResult validationResult = new SecretValidationResult(); - validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); - return validationResult; + return createValidationResult(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); } + if (requests.isEmpty()) { LOG.info("Configured requests for this finding empty! Finding cannot be validated!"); - SecretValidationResult validationResult = new SecretValidationResult(); - validationResult.setValidationStatus(SecretValidationStatus.NO_VALIDATION_CONFIGURED); - return validationResult; + return createValidationResult(SecretValidationStatus.NO_VALIDATION_CONFIGURED); } - int validationsPerformed = 0; - for (SecretValidatorRequest request : requests) { - if (request == null) { - LOG.info("Request config is null! Entry will be skipped."); - continue; - } - if (request.getUrl() == null) { - LOG.info("Request config URL is null! Entry will be skipped."); - continue; - } - HttpResponse response = null; - try { - HttpRequest httpRequest = createHttpRequest(snippetText, request); - if (request.isProxyRequired()) { - response = proxyHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - } else { - response = directHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); - } - } catch (IOException | InterruptedException e) { - LOG.error("Performing validation request failed!"); - } - validationsPerformed++; - if (responseValidationService.isValidResponse(response, request.getExpectedResponse())) { - LOG.info("Finding is valid!"); - SecretValidationResult validationResult = new SecretValidationResult(); - validationResult.setValidationStatus(SecretValidationStatus.VALID); - validationResult.setValidatedByUrl(request.getUrl().toString()); - return validationResult; - } + return null; + } + + private boolean isRequestValid(SecretValidatorRequest request) { + if (request == null) { + LOG.info("Request config is null! Entry will be skipped."); + return false; } - if (validationsPerformed < 1) { - SecretValidationResult validationResult = new SecretValidationResult(); - validationResult.setValidationStatus(SecretValidationStatus.NO_VALIDATION_CONFIGURED); - return validationResult; + if (request.getUrl() == null) { + LOG.info("Request config URL is null! Entry will be skipped."); + return false; } - SecretValidationResult validationResult = new SecretValidationResult(); - validationResult.setValidationStatus(SecretValidationStatus.INVALID); - return validationResult; + return true; + } + + private HttpResponse createAndExecuteHttpRequest(String snippetText, HttpClient proxyHttpClient, HttpClient directHttpClient, + SecretValidatorRequest request) { + HttpResponse response = null; + try { + HttpRequest httpRequest = createHttpRequest(snippetText, request); + if (request.isProxyRequired()) { + response = proxyHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + } else { + response = directHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + } + } catch (IOException | InterruptedException e) { + LOG.error("Performing validation request failed!"); + } + return response; } private HttpRequest createHttpRequest(String snippetText, SecretValidatorRequest request) { @@ -110,4 +122,17 @@ private HttpRequest createHttpRequest(String snippetText, SecretValidatorRequest } } + private SecretValidationResult createValidationResult(SecretValidationStatus validationStatus) { + return createValidationResult(validationStatus, null); + } + + private SecretValidationResult createValidationResult(SecretValidationStatus validationStatus, URL secretWasValidFor) { + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(validationStatus); + if (secretWasValidFor != null) { + validationResult.setValidatedByUrl(secretWasValidFor.toString()); + } + return validationResult; + } + } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java similarity index 88% rename from sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java rename to sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java index 6ac55069c3..649a80711e 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java @@ -11,9 +11,9 @@ import de.jcup.sarif_2_1_0.model.Region; @Service -public class SecretValidatorCategorizationService { +public class SerecoSeveritySarifEnhancementService { - public void categorizeFindingByRegion(SecretValidationResult validationResult, Region findingRegion, SecretValidatorCategorization categorization) { + public void addSerecoSeverityInfo(SecretValidationResult validationResult, Region findingRegion, SecretValidatorCategorization categorization) { if (categorization == null || categorization.isEmpty()) { return; } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java index ab2573011a..f941a25eff 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModel.java @@ -34,9 +34,18 @@ public List getRequests() { return Collections.unmodifiableList(requests); } + /** + * Every time this setter is called the list will be cleared, but it can never + * be null. In case the parameter is null the list, the list will stay empty, + * but never null. + * + * @param requests + */ public void setRequests(List requests) { - if (requests != null) { - this.requests = requests; + this.requests.clear(); + if (requests == null) { + return; } + this.requests.addAll(requests); } } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java index ab9da9281b..0a2185cccc 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelList.java @@ -16,10 +16,19 @@ public List getValidatorConfigList() { return Collections.unmodifiableList(validatorConfigList); } - public void setDataList(List validatorConfigList) { - if (validatorConfigList != null) { - this.validatorConfigList = validatorConfigList; + /** + * Every time this setter is called the list will be cleared, but it can never + * be null. In case the parameter is null the list, the list will stay empty, + * but never null. + * + * @param validatorConfigList + */ + public void setValidatorConfigList(List validatorConfigList) { + this.validatorConfigList.clear(); + if (validatorConfigList == null) { + return; } + this.validatorConfigList.addAll(validatorConfigList); } } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java index 9a4db101db..b5a6a837dd 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorRequest.java @@ -36,10 +36,19 @@ public List getHeaders() { return Collections.unmodifiableList(headers); } + /** + * Every time this setter is called the list will be cleared, but it can never + * be null. In case the parameter is null the list, the list will stay empty, + * but never null. + * + * @param headers + */ public void setHeaders(List headers) { - if (headers != null) { - this.headers = headers; + this.headers.clear(); + if (headers == null) { + return; } + this.headers.addAll(headers); } public SecretValidatorResponse getExpectedResponse() { diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java index 7ae8fdae0f..ad55ee71b3 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorResponseContains.java @@ -17,20 +17,38 @@ public List getAllOf() { return Collections.unmodifiableList(allOf); } + /** + * Every time this setter is called the list will be cleared, but it can never + * be null. In case the parameter is null the list, the list will stay empty, + * but never null. + * + * @param allOf + */ public void setAllOf(List allOf) { - if (allOf != null) { - this.allOf = allOf; + this.allOf.clear(); + if (allOf == null) { + return; } + this.allOf.addAll(allOf); } public List getOneOf() { return Collections.unmodifiableList(oneOf); } + /** + * Every time this setter is called the list will be cleared, but it can never + * be null. In case the parameter is null the list, the list will stay empty, + * but never null. + * + * @param oneOf + */ public void setOneOf(List oneOf) { - if (oneOf != null) { - this.oneOf = oneOf; + this.oneOf.clear(); + if (oneOf == null) { + return; } + this.oneOf.addAll(oneOf); } } diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java index 5bc1b80591..da83fcfd35 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java @@ -35,26 +35,27 @@ class SecretValidatorSpringBootTest { SecretValidatorExecutionService executionService; @Test - void execution_service_with_correct_configuration_without_validation_categprizes_findings_with_default_configured() { + void execution_service_with_correct_configuration_without_validation_categorizes_findings_with_default_configured() { /* execute */ SarifSchema210 report = executionService.execute(); /* test */ Run run = report.getRuns().get(0); for (Result finding : run.getResults()) { - Location location = finding.getLocations().get(0); - Region region = location.getPhysicalLocation().getRegion(); - Map additionalProperties = region.getProperties().getAdditionalProperties(); - String sechubSeverity = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey()); - String validatedByUrl = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_VALIDATED_BY_URL.getKey()); - - // expected severity is the severity from the validation failed config - assertEquals("medium", sechubSeverity); - - // since it was not validated we expected no value for - // SECRETSCAN_VALIDATED_BY_URL - assertEquals(null, validatedByUrl); + // since all validation requests fail the default categorization of the config + // file will be used which is high + assertFindHasSerecoSeverity("high", finding); } } + private void assertFindHasSerecoSeverity(String expectedSerecoSeverity, Result finding) { + Location location = finding.getLocations().get(0); + Region region = location.getPhysicalLocation().getRegion(); + Map additionalProperties = region.getProperties().getAdditionalProperties(); + String serecoSeverity = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey()); + + assertEquals(expectedSerecoSeverity, serecoSeverity); + + } + } diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java index 5bc3fa0d1d..1b697102a1 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java @@ -43,6 +43,20 @@ void validator_response_config_is_null_results_in_validation_is_false() { assertFalse(isValid); } + @Test + void validator_response_config_is_not_configured_results_in_validation_is_false() { + /* prepare */ + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(response.statusCode()).thenReturn(0); + + /* execute */ + boolean isValid = serviceToTest.isValidResponse(response, new SecretValidatorResponse()); + + /* test */ + assertFalse(isValid); + } + @ParameterizedTest @ValueSource(ints = { 200, 302, 404, 500 }) void validator_response_config_status_code_configured_and_contains_is_null_results_in_http_status_code_check(int responseCode) { @@ -54,7 +68,7 @@ void validator_response_config_status_code_configured_and_contains_is_null_resul secretValidatorResponse.setHttpStatus(302); secretValidatorResponse.setContains(null); - // with this configuration we expect the satuscodes being compared, + // with this configuration we expect the statuscodes being compared, // since nothing else is configured inside the SecretValidatorResponse boolean expectedResponse = response.statusCode() == secretValidatorResponse.getHttpStatus(); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java index 083ef07156..181a9285ab 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java @@ -19,9 +19,31 @@ class SecretValidatorExecutionContextFactoryTest { private SecretValidatorExecutionContextFactory factoryToTest; + private SecretValidatorPDSJobResult invalidsecretValidatorPDSJobResult; + private SecretValidatorPDSJobResult validSecretValidatorPDSJobResult; + private SecretValidatorProperties invalidProperties; + private SecretValidatorProperties validProperties; + + private static final File invalidSarifFile = new File("src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"); + private static final File invalidConfigFile = new File("src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"); + private static final File validSarifFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + private static final File validConfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); + @BeforeEach void beforeEach() { factoryToTest = new SecretValidatorExecutionContextFactory(); + + invalidsecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + invalidsecretValidatorPDSJobResult.setFile(invalidSarifFile); + + invalidProperties = new SecretValidatorProperties(); + invalidProperties.setConfigFile(invalidConfigFile); + + validSecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); + validSecretValidatorPDSJobResult.setFile(validSarifFile); + + validProperties = new SecretValidatorProperties(); + validProperties.setConfigFile(validConfigFile); } @Test @@ -58,31 +80,22 @@ void not_readable_pds_job_result_file_throws_exception() { @Test void invalid_sarif_pds_job_result_file_throws_exception() { /* prepare */ - File invalidFile = new File("src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(invalidFile); - - factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.pdsResult = invalidsecretValidatorPDSJobResult; /* execute + test */ IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("Creating SARIF report model from: " + invalidFile + " failed!", exception.getMessage()); + assertEquals("Creating SARIF report model from: " + invalidsecretValidatorPDSJobResult.getFile() + " failed!", exception.getMessage()); } @Test void not_existing_secret_validator_config_file_throws_exception() { /* prepare */ - // we need a valid Sarif report because the pds job result is read first - File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(validFile); - File notExisting = mock(File.class); when(notExisting.exists()).thenReturn(false); SecretValidatorProperties properties = new SecretValidatorProperties(); properties.setConfigFile(notExisting); - factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.pdsResult = validSecretValidatorPDSJobResult; factoryToTest.properties = properties; /* execute + test */ @@ -93,18 +106,13 @@ void not_existing_secret_validator_config_file_throws_exception() { @Test void not_readable_secret_validator_config_file_throws_exception() { /* prepare */ - // we need a valid Sarif report because the pds job result is read first - File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(validFile); - File notReadable = mock(File.class); when(notReadable.exists()).thenReturn(true); when(notReadable.canRead()).thenReturn(false); SecretValidatorProperties properties = new SecretValidatorProperties(); properties.setConfigFile(notReadable); - factoryToTest.pdsResult = secretValidatorPDSJobResult; + factoryToTest.pdsResult = validSecretValidatorPDSJobResult; factoryToTest.properties = properties; /* execute + test */ @@ -115,41 +123,24 @@ void not_readable_secret_validator_config_file_throws_exception() { @Test void invalid_secret_validator_config_file_throws_exception() { /* prepare */ - // we need a valid Sarif report because the pds job result is read first - File validFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(validFile); - - File invalidFile = new File("src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"); - SecretValidatorProperties properties = new SecretValidatorProperties(); - properties.setConfigFile(invalidFile); - - factoryToTest.pdsResult = secretValidatorPDSJobResult; - factoryToTest.properties = properties; + factoryToTest.pdsResult = validSecretValidatorPDSJobResult; + factoryToTest.properties = invalidProperties; /* execute + test */ IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("Creating secret validator configuration from: " + invalidFile + " failed!", exception.getMessage()); + assertEquals("Creating secret validator configuration from: " + invalidProperties.getConfigFile() + " failed!", exception.getMessage()); } @Test void valid_files_return_valid_execution_context() { /* prepare */ - // we need a valid Sarif report because the pds job result is read first - File validSarifReportFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(validSarifReportFile); - - File validSecretValidatorCOnfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); - SecretValidatorProperties properties = new SecretValidatorProperties(); - properties.setConfigFile(validSecretValidatorCOnfigFile); - - factoryToTest.pdsResult = secretValidatorPDSJobResult; - factoryToTest.properties = properties; + factoryToTest.pdsResult = validSecretValidatorPDSJobResult; + factoryToTest.properties = validProperties; /* execute */ SecretValidatorExecutionContext secretValidatorExecutionContext = factoryToTest.create(); + /* test */ assertNotNull(secretValidatorExecutionContext); assertNotNull(secretValidatorExecutionContext.getSarifReport()); assertEquals(1, secretValidatorExecutionContext.getValidatorConfiguration().size()); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java index 4a809790bd..0172e5f199 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java @@ -36,7 +36,7 @@ class SecretValidatorExecutionServiceTest { private SecretValidatorExecutionContextFactory contextFactory; private SecretValidationService validationService; - private SecretValidatorCategorizationService categorizationService; + private SerecoSeveritySarifEnhancementService sarifEnhancementService; private SarifValidationSupport sarifValidationSupport; @BeforeEach @@ -45,12 +45,12 @@ void beforeEach() { contextFactory = mock(SecretValidatorExecutionContextFactory.class); validationService = mock(SecretValidationService.class); - categorizationService = mock(SecretValidatorCategorizationService.class); + sarifEnhancementService = mock(SerecoSeveritySarifEnhancementService.class); sarifValidationSupport = mock(SarifValidationSupport.class); serviceToTest.contextFactory = contextFactory; serviceToTest.validationService = validationService; - serviceToTest.categorizationService = categorizationService; + serviceToTest.sarifEnhancementService = sarifEnhancementService; serviceToTest.sarifValidationSupport = sarifValidationSupport; } @@ -74,7 +74,7 @@ void finding_cannot_be_validated_results_in_validation_and_categorization_never_ /* test */ verify(contextFactory, times(1)).create(); verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, never()).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); } @@ -99,7 +99,7 @@ void empty_config_map_results_in_validation_and_categorization_never_being_calle /* test */ verify(contextFactory, times(1)).create(); verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, never()).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); } @@ -126,7 +126,7 @@ void categorization_of_config_is_null_results_in_validation_and_categorization_n /* test */ verify(contextFactory, times(1)).create(); verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, never()).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); } @@ -154,7 +154,7 @@ void categorization_of_config_is_empty_results_in_validation_and_categorization_ /* test */ verify(contextFactory, times(1)).create(); verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, never()).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); } @@ -184,7 +184,7 @@ void finding_location_cannot_be_validated_results_in_validation_and_categorizati /* test */ verify(contextFactory, times(1)).create(); verify(validationService, never()).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, never()).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, never()).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(1)).findingCanBeValidated(any()); verify(sarifValidationSupport, times(1)).findingLocationCanBeValidated(any()); } @@ -198,7 +198,7 @@ void valid_config_and_valid_sarif_report_results_in_validation_and_categorizatio SecretValidationResult secretValidationResult = new SecretValidationResult(); when(validationService.validateFindingByRegion(any(), any(), anyBoolean())).thenReturn(secretValidationResult); - doNothing().when(categorizationService).categorizeFindingByRegion(any(), any(), any()); + doNothing().when(sarifEnhancementService).addSerecoSeverityInfo(any(), any(), any()); when(sarifValidationSupport.findingCanBeValidated(any())).thenReturn(true); when(sarifValidationSupport.findingLocationCanBeValidated(any())).thenReturn(true); @@ -209,7 +209,7 @@ void valid_config_and_valid_sarif_report_results_in_validation_and_categorizatio /* test */ verify(contextFactory, times(1)).create(); verify(validationService, times(6)).validateFindingByRegion(any(), any(), anyBoolean()); - verify(categorizationService, times(6)).categorizeFindingByRegion(any(), any(), any()); + verify(sarifEnhancementService, times(6)).addSerecoSeverityInfo(any(), any(), any()); verify(sarifValidationSupport, times(6)).findingCanBeValidated(any()); verify(sarifValidationSupport, times(6)).findingLocationCanBeValidated(any()); } diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java index 71b0677310..3c951cbd2a 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestServiceTest.java @@ -11,6 +11,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.http.HttpClient; +import java.net.http.HttpResponse; import java.util.ArrayList; import java.util.List; @@ -72,7 +73,7 @@ void request_config_inside_list_is_null_results_request_will_be_skipped() { /* test */ // no validation request was performed ends up with the following status, only // if at least 1 request was performed, the finding could be marked as invalid. - assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + assertEquals(SecretValidationStatus.ALL_VALIDATION_REQUESTS_FAILED, validationResult.getValidationStatus()); } @Test @@ -87,7 +88,7 @@ void request_url_is_null_results_request_will_be_skipped() { /* test */ // no validation request was performed ends up with the following status, only // if at least 1 request was performed, the finding could be marked as invalid. - assertEquals(SecretValidationStatus.NO_VALIDATION_CONFIGURED, validationResult.getValidationStatus()); + assertEquals(SecretValidationStatus.ALL_VALIDATION_REQUESTS_FAILED, validationResult.getValidationStatus()); } @ParameterizedTest @@ -111,7 +112,7 @@ void proxy_required_calls_the_correct_http_client_results_validation_result(bool assertEquals(SecretValidationStatus.VALID, validationResult.getValidationStatus()); assertEquals("http://example.com", validationResult.getValidatedByUrl()); } else { - assertEquals(SecretValidationStatus.INVALID, validationResult.getValidationStatus()); + assertEquals(SecretValidationStatus.ALL_VALIDATION_REQUESTS_FAILED, validationResult.getValidationStatus()); } } @@ -122,7 +123,9 @@ void no_proxy_required_calls_the_correct_http_client_results_validation_result(b List requests = createListOfRequests(false); HttpClient directHttpClient = mock(HttpClient.class); - when(directHttpClient.send(any(), any())).thenReturn(null); + @SuppressWarnings("unchecked") + HttpResponse response = mock(HttpResponse.class); + when(directHttpClient.send(any(), any())).thenReturn(response); when(httpClientFactory.createDirectHttpClient(anyBoolean())).thenReturn(directHttpClient); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java similarity index 88% rename from sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java rename to sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java index 5fe1df1ce0..572341545f 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorCategorizationServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java @@ -15,9 +15,9 @@ import de.jcup.sarif_2_1_0.model.PropertyBag; import de.jcup.sarif_2_1_0.model.Region; -class SecretValidatorCategorizationServiceTest { +class SerecoSeveritySarifEnhancementServiceTest { - private SecretValidatorCategorizationService serviceToTest = new SecretValidatorCategorizationService(); + private SerecoSeveritySarifEnhancementService serviceToTest = new SerecoSeveritySarifEnhancementService(); @Test void categorization_config_is_null_results_in_property_bag_being_empty() { @@ -26,7 +26,7 @@ void categorization_config_is_null_results_in_property_bag_being_empty() { SecretValidationResult validationResult = new SecretValidationResult(); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, null); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, null); /* test */ assertNull(findingRegion.getProperties()); @@ -40,7 +40,7 @@ void categorization_config_is_empty_results_in_property_bag_being_empty() { SecretValidatorCategorization categorization = new SecretValidatorCategorization(); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ assertNull(findingRegion.getProperties()); @@ -58,7 +58,7 @@ void validation_result_valid_results_in_configured_categorization() { categorization.setValidationSuccessSeverity("critical"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); @@ -80,7 +80,7 @@ void validation_result_invalid_results_in_configured_categorization() { categorization.setValidationFailedSeverity("low"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); @@ -101,7 +101,7 @@ void validation_result_with_no_validation_configured_results_in_default_categori categorization.setDefaultSeverity("medium"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); @@ -122,7 +122,7 @@ void validation_result_with_sarif_snippet_not_set_results_in_default_categorizat categorization.setDefaultSeverity("medium"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); @@ -142,7 +142,7 @@ void validation_empty_results_in_default_categorization() { categorization.setDefaultSeverity("medium"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); @@ -167,7 +167,7 @@ void validation_result_valid_results_in_severity_value_is_null() throws Malforme categorization.setValidationFailedSeverity("low"); /* execute */ - serviceToTest.categorizeFindingByRegion(validationResult, findingRegion, categorization); + serviceToTest.addSerecoSeverityInfo(validationResult, findingRegion, categorization); /* test */ PropertyBag properties = findingRegion.getProperties(); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java index d443ad6705..c038acc6a6 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/model/SecretValidatorConfigurationModelListTest.java @@ -10,7 +10,7 @@ class SecretValidatorConfigurationModelListTest { @Test - void test() { + void json_converter_can_handle_model_in_expected_way() { /* prepare */ String json = """ { From d3f04aee17f1a122ecbc02d07a3bd0baf33f574d Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 17 Jul 2024 15:50:43 +0200 Subject: [PATCH 04/10] Update gradle files after merge conflict #3280 --- gradle/projects.gradle | 1 - settings.gradle | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gradle/projects.gradle b/gradle/projects.gradle index aa8782ac19..096ef85abb 100644 --- a/gradle/projects.gradle +++ b/gradle/projects.gradle @@ -55,7 +55,6 @@ projectType = [ /* special application to validate and categorize results of secret scans */ project(':sechub-wrapper-secret-validator'), - ], /* adapter projects - have simple spring dependencies, but know only sechub-adapter as base */ diff --git a/settings.gradle b/settings.gradle index b343a5bdcf..3eb2e1a6ad 100644 --- a/settings.gradle +++ b/settings.gradle @@ -89,7 +89,10 @@ include 'sechub-cli', // Wrapper prepare 'sechub-wrapper-prepare', -/* secret validator */ +// Wrapper Xray +'sechub-wrapper-xray', + +// secret validator 'sechub-wrapper-secret-validator', /* System Test */ From 4a6e21631c9154167ceb410302df4537ce8b7be9 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Thu, 18 Jul 2024 12:49:10 +0200 Subject: [PATCH 05/10] PR review changes part two #3280 - fix naming of sarif custom property key - add integrationtest profile to secret validator wrapper application and implement another validation module that is only available with the integrationtest profile. This module does not perform real web requests - extend existing integrationtest with a call to the secret validator wrapper application by using the the gitleaks.sh from the pds gitleaks --- gradle/projects.gradle | 4 +- .../pds-solutions-gitleaks-mocked.sh | 16 +++++++- .../resources/pds-config-integrationtest.json | 2 +- .../PDSSolutionMockModeScenario21IntTest.java | 16 +++++++- .../gitleaks/docker/mocks/mock.sarif.json | 31 +++++++++++++++ .../gitleaks/docker/scripts/gitleaks.sh | 14 ++++++- ...chub-wrapper-secret-validation-config.json | 21 ++++++++++ .../GitleaksSarifImportWorkaround.java | 2 +- .../sereco/importer/SarifImporterKeys.java | 4 +- ...invalid-validator-severity-properties.json | 4 +- ....0-with-validator-severity-properties.json | 12 +++--- sechub-wrapper-secret-validator/README.adoc | 10 ++++- sechub-wrapper-secret-validator/build.gradle | 25 +++++++++++- ...ntegrationTestSecretValidationService.java | 39 +++++++++++++++++++ .../execution/SecretValidationModul.java | 14 +++++++ .../execution/SecretValidationService.java | 5 ++- .../SecretValidatorExecutionService.java | 2 +- .../SecretValidatorSpringProfiles.java | 8 ++++ ...SerecoSeveritySarifEnhancementService.java | 7 ++-- .../validator/support/SarifImporterKeys.java | 2 +- .../cli/SecretValidatorSpringBootTest.java | 2 +- ...coSeveritySarifEnhancementServiceTest.java | 12 +++--- .../valid-files/test-result.txt | 18 +++++++++ 23 files changed, 237 insertions(+), 33 deletions(-) create mode 100644 sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorSpringProfiles.java diff --git a/gradle/projects.gradle b/gradle/projects.gradle index 096ef85abb..9d967e330e 100644 --- a/gradle/projects.gradle +++ b/gradle/projects.gradle @@ -53,7 +53,6 @@ projectType = [ project(':sechub-wrapper-checkmarx'), project(':sechub-wrapper-prepare'), - /* special application to validate and categorize results of secret scans */ project(':sechub-wrapper-secret-validator'), ], @@ -99,7 +98,8 @@ projectType = [ project(':sechub-pds'), project(':sechub-wrapper-checkmarx'), project(':sechub-wrapper-prepare'), - project(':sechub-webui') + project(':sechub-webui'), + project(':sechub-wrapper-secret-validator'), ], springBootWebUIProjects:[ diff --git a/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh b/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh index 96096aea6f..c94aa8cf95 100755 --- a/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh +++ b/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh @@ -9,4 +9,18 @@ echo "PDS solutions GITLEAKS mock starting" cp "./../sechub-pds-solutions/gitleaks/docker/mocks/mock.sarif.json" "$PDS_JOB_RESULT_FILE" warnMessage "mocked result" -infoMessage "product:gitleaks" \ No newline at end of file +infoMessage "product:gitleaks" + +# Here we test the sechub wrapper secret validator application with the results of "mock.sarif.json" +export PDS_INTEGRATIONTEST_ENABLED=true +export TOOL_FOLDER=./../sechub-integrationtest/build/pds-tools + +# Export the config file necessary for the sechub wrapper secret validator application +# Besides the config file the wrapper application will automatically use the PDS_JOB_RESULT_FILE, +# which is already available in this context +export SECRET_VALIDATOR_CONFIGFILE="./../sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json" + +# Uses the original gitleaks.sh script from the pds gitleaks +# Since 'PDS_INTEGRATIONTEST_ENABLED=true' gitleaks will no be executed. +# The wrapper application starts with the 'integrationtest' profile and will not perform real web reuqests +source ./../sechub-pds-solutions/gitleaks/docker/scripts/gitleaks.sh diff --git a/sechub-integrationtest/src/main/resources/pds-config-integrationtest.json b/sechub-integrationtest/src/main/resources/pds-config-integrationtest.json index 08ffe92609..9b4651eaf0 100644 --- a/sechub-integrationtest/src/main/resources/pds-config-integrationtest.json +++ b/sechub-integrationtest/src/main/resources/pds-config-integrationtest.json @@ -229,7 +229,7 @@ }, { "id" : "PDS_SOLUTION_GITLEAKS_MOCKED", "path" : "./../sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh", - "scanType" : "secretSCan", + "scanType" : "secretScan", "description" : "Returns mock data, but from real product" }, { "id" : "PDS_SOLUTION_ZAP_MOCKED", diff --git a/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario21/PDSSolutionMockModeScenario21IntTest.java b/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario21/PDSSolutionMockModeScenario21IntTest.java index 9151ba3af6..c15c848939 100644 --- a/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario21/PDSSolutionMockModeScenario21IntTest.java +++ b/sechub-integrationtest/src/test/java/com/mercedesbenz/sechub/integrationtest/scenario21/PDSSolutionMockModeScenario21IntTest.java @@ -32,6 +32,8 @@ import com.mercedesbenz.sechub.commons.model.SecHubSourceDataConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubStatus; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; +import com.mercedesbenz.sechub.commons.model.Severity; +import com.mercedesbenz.sechub.commons.model.TrafficLight; import com.mercedesbenz.sechub.integrationtest.api.IntegrationTestSetup; import com.mercedesbenz.sechub.integrationtest.api.TestAPI; import com.mercedesbenz.sechub.integrationtest.api.TestProject; @@ -72,7 +74,16 @@ public void pds_solution_scancode_spdx_mocked_report_in_json_and_html_available( @Test public void pds_solution_gitleaks_mocked_report_in_json_and_html_available() throws Exception { - executePDSSolutionJobAndStoreReports(ScanType.SECRET_SCAN, PROJECT_6, "gitleaks"); + SecHubReportModel report = executePDSSolutionJobAndStoreReports(ScanType.SECRET_SCAN, PROJECT_6, "gitleaks"); + /* @formatter:off */ + assertReportUnordered(report.toJSON()) + .hasTrafficLight(TrafficLight.RED) + .finding() + .severity(Severity.CRITICAL) + .scanType(ScanType.SECRET_SCAN) + .description("github-pat has detected secret for file UnSAFE_Bank/iOS/Source Code/Pods/README.adoc.") + .isContained(); + /* @formatter:on */ } @Test @@ -100,7 +111,7 @@ public void pds_solution_findsecuritybugs_mocked_report_in_json_and_html_availab executePDSSolutionJobAndStoreReports(ScanType.CODE_SCAN, PROJECT_10, "findsecuritybugs"); } - private void executePDSSolutionJobAndStoreReports(ScanType scanType, TestProject project, String solutionName) { + private SecHubReportModel executePDSSolutionJobAndStoreReports(ScanType scanType, TestProject project, String solutionName) { SecHubConfigurationModel model = createTestModelFor(scanType, project); UUID jobUUID = as(USER_1).createJobAndReturnJobUUID(project, model); @@ -162,6 +173,7 @@ private void executePDSSolutionJobAndStoreReports(ScanType scanType, TestProject String spdxReport = as(USER_1).getSpdxReport(project, jobUUID); storeTestReport(reportName + ".spdx.json", spdxReport); } + return report; } private SecHubConfigurationModel createTestModelFor(ScanType type, TestProject project) { diff --git a/sechub-pds-solutions/gitleaks/docker/mocks/mock.sarif.json b/sechub-pds-solutions/gitleaks/docker/mocks/mock.sarif.json index ff14dd1ba2..8ecc795b6c 100644 --- a/sechub-pds-solutions/gitleaks/docker/mocks/mock.sarif.json +++ b/sechub-pds-solutions/gitleaks/docker/mocks/mock.sarif.json @@ -1100,6 +1100,37 @@ "date": "", "commitMessage": "" } + }, + { + "message": { + "text": "github-pat has detected secret for file UnSAFE_Bank/iOS/Source Code/Pods/README.adoc." + }, + "ruleId": "github-pat", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "UnSAFE_Bank/iOS/Source Code/Pods/README.adoc" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "endLine": 1, + "endColumn": 40, + "snippet": { + "text": "invalid-token" + } + } + } + } + ], + "partialFingerprints": { + "commitSha": "", + "email": "", + "author": "", + "date": "", + "commitMessage": "" + } } ] } diff --git a/sechub-pds-solutions/gitleaks/docker/scripts/gitleaks.sh b/sechub-pds-solutions/gitleaks/docker/scripts/gitleaks.sh index b732badf39..d3d30dc4df 100755 --- a/sechub-pds-solutions/gitleaks/docker/scripts/gitleaks.sh +++ b/sechub-pds-solutions/gitleaks/docker/scripts/gitleaks.sh @@ -1,6 +1,18 @@ -#!/bin/sh +#!/usr/bin/bash # SPDX-License-Identifier: MIT +declare -r secretvalidation_wrapper="$TOOL_FOLDER/sechub-wrapper-secret-validator.jar" + +if [[ "$PDS_INTEGRATIONTEST_ENABLED" = "true" ]]; then + echo "Integrationtest will be performed. Gitleaks will not be executed." + + # Execute the wrapper using the 'integrationtest' profile + java -jar "-Dspring.profiles.active=integrationtest" "$secretvalidation_wrapper" + + exit $? +fi + + . "$SCRIPT_FOLDER/common.sh" echo "Look for potential .git folder to perform history scan." diff --git a/sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json b/sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json new file mode 100644 index 0000000000..a12961f402 --- /dev/null +++ b/sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json @@ -0,0 +1,21 @@ +{ + "validatorConfigList" : [ { + "ruleId" : "github-pat", + "categorization" : { + "defaultSeverity" : "high", + "validationFailedSeverity" : "medium", + "validationSuccessSeverity" : "critical" + }, + "requests" : [ { + "proxyRequired" : true, + "url" : "https://api.github.com", + "headers" : [ { + "name" : "Authorization", + "valuePrefix" : "token" + } ], + "expectedResponse" : { + "httpStatus" : 200 + } + } ] + } ] +} \ No newline at end of file diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java index 7d9857c198..131ace6d91 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/GitleaksSarifImportWorkaround.java @@ -77,7 +77,7 @@ public SerecoSeverity resolveCustomSerecoSeverity(Result result, Run run) { if (additionalProperties == null) { return null; } - String severityKey = SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey(); + String severityKey = SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey(); String severityValue = (String) additionalProperties.get(severityKey); return SerecoSeverity.fromString(severityValue); } diff --git a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java index cee7ee8df1..dfb9c7da73 100644 --- a/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java +++ b/sechub-sereco/src/main/java/com/mercedesbenz/sechub/sereco/importer/SarifImporterKeys.java @@ -3,11 +3,11 @@ /* * If this needs to get changed, make sure to change - * com.mercedesbenz.sechub.wrapper.secret.validator.support.SarifImporterKeys accordingly + * com.mercedesbenz.sechub.sereco.importer.SarifImporterKeys accordingly */ public enum SarifImporterKeys { - SECRETSCAN_SECHUB_SEVERITY("secretscan.sechub.severity", "The key for the sechub severity which is more precise than the SARIF Level enum."), + SECRETSCAN_SERECO_SEVERITY("secretscan.sereco.severity", "The key for the sereco severity which is more precise than the SARIF Level enum."), SECRETSCAN_VALIDATED_BY_URL("secretscan.validated.by.url", "The key for the URL the secret was validated with."), diff --git a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json index 41b8a849e4..4d77229fce 100644 --- a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json +++ b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-invalid-validator-severity-properties.json @@ -802,7 +802,7 @@ "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" }, "properties" : { - "secretscan.sechub.severity" : "invalid-value" + "secretscan.sereco.severity" : "invalid-value" } } } @@ -833,7 +833,7 @@ "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" }, "properties" : { - "secretscan.sechub.severity" : "another-invalid-value-1234" + "secretscan.sereco.severity" : "another-invalid-value-1234" } } } diff --git a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json index 5d99a890f8..346bf7be33 100644 --- a/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json +++ b/sechub-sereco/src/test/resources/sarif/sarif_2.1.0_gitleaks_8.0-with-validator-severity-properties.json @@ -802,7 +802,7 @@ "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" }, "properties" : { - "secretscan.sechub.severity" : "info" + "secretscan.sereco.severity" : "info" } } } @@ -833,7 +833,7 @@ "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" }, "properties" : { - "secretscan.sechub.severity" : "unclassified" + "secretscan.sereco.severity" : "unclassified" } } } @@ -864,7 +864,7 @@ "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" }, "properties" : { - "secretscan.sechub.severity" : "low" + "secretscan.sereco.severity" : "low" } } } @@ -895,7 +895,7 @@ "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" }, "properties" : { - "secretscan.sechub.severity" : "medium" + "secretscan.sereco.severity" : "medium" } } } @@ -926,7 +926,7 @@ "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" }, "properties" : { - "secretscan.sechub.severity" : "high" + "secretscan.sereco.severity" : "high" } } } @@ -957,7 +957,7 @@ "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" }, "properties" : { - "secretscan.sechub.severity" : "critical" + "secretscan.sereco.severity" : "critical" } } } diff --git a/sechub-wrapper-secret-validator/README.adoc b/sechub-wrapper-secret-validator/README.adoc index 842ed2b029..553b4973bd 100644 --- a/sechub-wrapper-secret-validator/README.adoc +++ b/sechub-wrapper-secret-validator/README.adoc @@ -92,4 +92,12 @@ For each request it will then be decided if the proxy is needed or not according ---- java -Dhttp.proxyHost=localhost -Dhttp.proxyPort=1234 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=1234 -jar secret-validation-wrapper.jar ----- \ No newline at end of file +---- + +==== Testing the wrapper +For testing purposes there is another implementation present which is only available and used if the wrapper is started with the `integrationtest` profile: +---- +java -Dspring.profiles.active=integrationtest -jar secret-validation-wrapper.jar +---- +If the `integrationtest` profile is used the application will flag all findings in the SARIF report as valid, that has a none empty list of requests configured. +In case no requests are configured the finding will be flagged as invalid. \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/build.gradle b/sechub-wrapper-secret-validator/build.gradle index 7f2e400e1f..fb4956f952 100644 --- a/sechub-wrapper-secret-validator/build.gradle +++ b/sechub-wrapper-secret-validator/build.gradle @@ -20,4 +20,27 @@ dependencies { testImplementation spring_boot_dependency.mockito_core } -/* TODO janwinz: add versioning for release workflow */ \ No newline at end of file +// TODO Jan 2024-07-17: version = versionData.getSecretValidatorWrapperVersion() + +bootJar { + + doLast { + /* Here we copy the created wrapper jar as "sechub-wrapper-secret-validator.jar" into the + * pds-tools folder inside the sechub-integrationtest gradle subproject. + * + * This enables integration test script to use the solution secret-validator.sh script + * and just set as tool folder: ${project.buildDir}/pds-tools + */ + File integratonTestLaunchFile = new File("${rootProject.projectDir}/sechub-integrationtest/build/pds-tools/sechub-wrapper-secret-validator.jar") + + if (integratonTestLaunchFile.exists()){ + java.nio.file.Files.delete(integratonTestLaunchFile.toPath()) + }else{ + integratonTestLaunchFile.getParentFile().mkdirs(); + } + + File buildFile = new File("${project.buildDir}/libs/sechub-wrapper-secret-validator-${project.version}.jar") + java.nio.file.Files.copy(buildFile.toPath(),integratonTestLaunchFile.toPath()) + } + +} \ No newline at end of file diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java new file mode 100644 index 0000000000..d6bce5dd66 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.List; + +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; + +import de.jcup.sarif_2_1_0.model.Region; + +/** + * This service is only available and used if the application is started with + * the {@link SecretValidatorSpringProfiles.INTEGRATIONTEST} profile. It returns + * findings as invalid if the list of requests passed to the + * validateFindingByRegion(...) method is null or + * empty. If the requests list contains at least one entry the finding is + * returned as valid. + * + */ +@Profile(SecretValidatorSpringProfiles.INTEGRATIONTEST) +@Service +public class IntegrationTestSecretValidationService implements SecretValidationModul { + + @Override + public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { + if (requests == null || requests.isEmpty()) { + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.INVALID); + return validationResult; + } + + SecretValidationResult validationResult = new SecretValidationResult(); + validationResult.setValidationStatus(SecretValidationStatus.VALID); + return validationResult; + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java new file mode 100644 index 0000000000..57cdc4b8b2 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.List; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; + +import de.jcup.sarif_2_1_0.model.Region; + +public interface SecretValidationModul { + + SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates); + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java index 6a324a39c0..2ebe7bfe52 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; @@ -13,14 +14,16 @@ import de.jcup.sarif_2_1_0.model.ArtifactContent; import de.jcup.sarif_2_1_0.model.Region; +@Profile("!" + SecretValidatorSpringProfiles.INTEGRATIONTEST) @Service -public class SecretValidationService { +public class SecretValidationService implements SecretValidationModul { private static final Logger LOG = LoggerFactory.getLogger(SecretValidationService.class); @Autowired SecretValidatorWebRequestService webRequestService; + @Override public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { ArtifactContent snippet = findingRegion.getSnippet(); SecretValidationResult validationResult = new SecretValidationResult(); diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java index 6ff9d4b38b..8d706a8fc1 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java @@ -27,7 +27,7 @@ public class SecretValidatorExecutionService { SecretValidatorExecutionContextFactory contextFactory; @Autowired - SecretValidationService validationService; + SecretValidationModul validationService; @Autowired SerecoSeveritySarifEnhancementService sarifEnhancementService; diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorSpringProfiles.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorSpringProfiles.java new file mode 100644 index 0000000000..6e400c15a6 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorSpringProfiles.java @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +public class SecretValidatorSpringProfiles { + + public static final String INTEGRATIONTEST = "integrationtest"; + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java index 649a80711e..b7415b8fc6 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementService.java @@ -22,19 +22,20 @@ public void addSerecoSeverityInfo(SecretValidationResult validationResult, Regio switch (validationStatus) { case VALID: - properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getValidationSuccessSeverity()); + properties.setAdditionalProperty(SECRETSCAN_SERECO_SEVERITY.getKey(), categorization.getValidationSuccessSeverity()); String validatedByUrl = validationResult.getValidatedByUrl(); if (validatedByUrl != null) { properties.setAdditionalProperty(SECRETSCAN_VALIDATED_BY_URL.getKey(), validatedByUrl); } break; case INVALID: - properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getValidationFailedSeverity()); + properties.setAdditionalProperty(SECRETSCAN_SERECO_SEVERITY.getKey(), categorization.getValidationFailedSeverity()); break; case NO_VALIDATION_CONFIGURED: case SARIF_SNIPPET_NOT_SET: + case ALL_VALIDATION_REQUESTS_FAILED: default: - properties.setAdditionalProperty(SECRETSCAN_SECHUB_SEVERITY.getKey(), categorization.getDefaultSeverity()); + properties.setAdditionalProperty(SECRETSCAN_SERECO_SEVERITY.getKey(), categorization.getDefaultSeverity()); } findingRegion.setProperties(properties); } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java index 380edcdb9d..0e9c6caf49 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifImporterKeys.java @@ -7,7 +7,7 @@ */ public enum SarifImporterKeys { - SECRETSCAN_SECHUB_SEVERITY("secretscan.sechub.severity", "The key for the sechub severity which is more precise than the SARIF Level enum."), + SECRETSCAN_SERECO_SEVERITY("secretscan.sereco.severity", "The key for the sereco severity which is more precise than the SARIF Level enum."), SECRETSCAN_VALIDATED_BY_URL("secretscan.validated.by.url", "The key for the URL the secret was validated with."), diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java index da83fcfd35..bfede6e691 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java @@ -52,7 +52,7 @@ private void assertFindHasSerecoSeverity(String expectedSerecoSeverity, Result f Location location = finding.getLocations().get(0); Region region = location.getPhysicalLocation().getRegion(); Map additionalProperties = region.getProperties().getAdditionalProperties(); - String serecoSeverity = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey()); + String serecoSeverity = (String) additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey()); assertEquals(expectedSerecoSeverity, serecoSeverity); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java index 572341545f..3dcca39b51 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SerecoSeveritySarifEnhancementServiceTest.java @@ -65,7 +65,7 @@ void validation_result_valid_results_in_configured_categorization() { Map additionalProperties = properties.getAdditionalProperties(); assertEquals(2, additionalProperties.size()); - assertEquals(categorization.getValidationSuccessSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals(categorization.getValidationSuccessSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); assertEquals("http://api.example.com", additionalProperties.get(SarifImporterKeys.SECRETSCAN_VALIDATED_BY_URL.getKey())); } @@ -87,7 +87,7 @@ void validation_result_invalid_results_in_configured_categorization() { Map additionalProperties = properties.getAdditionalProperties(); assertEquals(1, additionalProperties.size()); - assertEquals(categorization.getValidationFailedSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals(categorization.getValidationFailedSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); } @Test @@ -108,7 +108,7 @@ void validation_result_with_no_validation_configured_results_in_default_categori Map additionalProperties = properties.getAdditionalProperties(); assertEquals(1, additionalProperties.size()); - assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); } @Test @@ -129,7 +129,7 @@ void validation_result_with_sarif_snippet_not_set_results_in_default_categorizat Map additionalProperties = properties.getAdditionalProperties(); assertEquals(1, additionalProperties.size()); - assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); } @Test @@ -149,7 +149,7 @@ void validation_empty_results_in_default_categorization() { Map additionalProperties = properties.getAdditionalProperties(); assertEquals(1, additionalProperties.size()); - assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertEquals(categorization.getDefaultSeverity(), additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); } @Test @@ -174,7 +174,7 @@ void validation_result_valid_results_in_severity_value_is_null() throws Malforme Map additionalProperties = properties.getAdditionalProperties(); assertEquals(1, additionalProperties.size()); - assertNull(additionalProperties.get(SarifImporterKeys.SECRETSCAN_SECHUB_SEVERITY.getKey())); + assertNull(additionalProperties.get(SarifImporterKeys.SECRETSCAN_SERECO_SEVERITY.getKey())); } } diff --git a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt index ba37047594..8dc507b517 100644 --- a/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt +++ b/sechub-wrapper-secret-validator/src/test/resources/config-test-files/valid-files/test-result.txt @@ -800,6 +800,9 @@ "endColumn" : 1, "snippet" : { "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } @@ -828,6 +831,9 @@ "endColumn" : 61, "snippet" : { "text" : "531486b2bf646636a6a1bba61e78ec4a4a54efbd" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } @@ -856,6 +862,9 @@ "endColumn" : 56, "snippet" : { "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } @@ -884,6 +893,9 @@ "endColumn" : 56, "snippet" : { "text" : "9bbc0d79e686e847bc305c9bd4cc2ea6" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } @@ -912,6 +924,9 @@ "endColumn" : 1, "snippet" : { "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } @@ -940,6 +955,9 @@ "endColumn" : 1, "snippet" : { "text" : "b3816fddcf28aa29d94b10ec305cd52be14c472b" + }, + "properties" : { + "secretscan.sereco.severity" : "high" } } } From 916ba1bad68a8da94a4df195f4ff750a47bbedd5 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Fri, 19 Jul 2024 15:03:28 +0200 Subject: [PATCH 06/10] Fix renaming #3280 --- .../pds/product-scripts/pds-solutions-gitleaks-mocked.sh | 2 +- ...-config.json => sechub-wrapper-secret-validator-config.json} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename sechub-pds-solutions/gitleaks/docker/{sechub-wrapper-secret-validation-config.json => sechub-wrapper-secret-validator-config.json} (100%) diff --git a/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh b/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh index c94aa8cf95..b02af0ed72 100755 --- a/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh +++ b/sechub-integrationtest/pds/product-scripts/pds-solutions-gitleaks-mocked.sh @@ -18,7 +18,7 @@ export TOOL_FOLDER=./../sechub-integrationtest/build/pds-tools # Export the config file necessary for the sechub wrapper secret validator application # Besides the config file the wrapper application will automatically use the PDS_JOB_RESULT_FILE, # which is already available in this context -export SECRET_VALIDATOR_CONFIGFILE="./../sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json" +export SECRET_VALIDATOR_CONFIGFILE="./../sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validator-config.json" # Uses the original gitleaks.sh script from the pds gitleaks # Since 'PDS_INTEGRATIONTEST_ENABLED=true' gitleaks will no be executed. diff --git a/sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json b/sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validator-config.json similarity index 100% rename from sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validation-config.json rename to sechub-pds-solutions/gitleaks/docker/sechub-wrapper-secret-validator-config.json From f191ce45f375c573a2122650a07cdce3844d3f66 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Tue, 23 Jul 2024 11:24:31 +0200 Subject: [PATCH 07/10] Add MIT headers #3280 --- .../validator/execution/ResponseValidationServiceTest.java | 1 + .../validator/execution/SecretValidatorExecutionServiceTest.java | 1 + .../secret/validator/support/SarifValidationSupportTest.java | 1 + 3 files changed, 3 insertions(+) diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java index 1b697102a1..010ba4c668 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/ResponseValidationServiceTest.java @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.secret.validator.execution; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java index 0172e5f199..a2112b120f 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.secret.validator.execution; import static org.mockito.ArgumentMatchers.any; diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java index 1b944bc0fd..9c2f8a3251 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/support/SarifValidationSupportTest.java @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.secret.validator.support; import static org.junit.jupiter.api.Assertions.assertFalse; From 03832d4f7e0ddd66019659f46c521ea4e5ccb56f Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 24 Jul 2024 09:22:10 +0200 Subject: [PATCH 08/10] Make configuration properties immutable #3280 --- sechub-wrapper-secret-validator/build.gradle | 6 ++ ...ntegrationTestSecretValidationService.java | 6 +- .../SecretValidatorConfiguration.java | 11 +++ .../SecretValidatorPDSJobResult.java | 22 +++-- .../properties/SecretValidatorProperties.java | 29 +++--- ...tValidatorExecutionContextFactoryTest.java | 88 ++----------------- ...tValidatorConfigurationSpringBootTest.java | 4 +- 7 files changed, 63 insertions(+), 103 deletions(-) rename sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/{ => test}/IntegrationTestSecretValidationService.java (80%) create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfiguration.java diff --git a/sechub-wrapper-secret-validator/build.gradle b/sechub-wrapper-secret-validator/build.gradle index fb4956f952..1a1deefb18 100644 --- a/sechub-wrapper-secret-validator/build.gradle +++ b/sechub-wrapper-secret-validator/build.gradle @@ -22,6 +22,12 @@ dependencies { // TODO Jan 2024-07-17: version = versionData.getSecretValidatorWrapperVersion() +compileJava { + + options.compilerArgs += ['-parameters'] + +} + bootJar { doLast { diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java similarity index 80% rename from sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java rename to sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java index d6bce5dd66..e5ff587342 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/IntegrationTestSecretValidationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java @@ -1,11 +1,15 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.secret.validator.execution; +package com.mercedesbenz.sechub.wrapper.secret.validator.execution.test; import java.util.List; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationModul; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationResult; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationStatus; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidatorSpringProfiles; import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; import de.jcup.sarif_2_1_0.model.Region; diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfiguration.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfiguration.java new file mode 100644 index 0000000000..12b793da20 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfiguration.java @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties({ SecretValidatorProperties.class, SecretValidatorPDSJobResult.class }) +public class SecretValidatorConfiguration { + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java index 7b86405978..9dc11aa451 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java @@ -4,25 +4,31 @@ import java.io.File; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; +import org.springframework.boot.context.properties.bind.ConstructorBinding; import org.springframework.validation.annotation.Validated; import jakarta.validation.constraints.NotNull; @Validated @ConfigurationProperties(prefix = "pds.job.result") -@Component public class SecretValidatorPDSJobResult { - @NotNull - private File file; + private final File file; - public File getFile() { - return file; + @ConstructorBinding + public SecretValidatorPDSJobResult(@NotNull String file) { + this.file = new File(file); + + if (!this.file.exists()) { + throw new IllegalArgumentException("The PDS result file " + file + " does not exist!"); + } + if (!this.file.canRead()) { + throw new IllegalArgumentException("The PDS result file " + file + " is not readable!"); + } } - public void setFile(File file) { - this.file = file; + public File getFile() { + return file; } } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java index 96a65fd23a..3e4c70e850 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java @@ -4,35 +4,38 @@ import java.io.File; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; +import org.springframework.boot.context.properties.bind.ConstructorBinding; import org.springframework.validation.annotation.Validated; import jakarta.validation.constraints.NotNull; @Validated @ConfigurationProperties(prefix = "secret.validator") -@Component public class SecretValidatorProperties { - @NotNull - private File configFile; + private final File configFile; + private final boolean trustAllCertificates; - private boolean trustAllCertificates; + @ConstructorBinding + public SecretValidatorProperties(@NotNull String configFile, boolean trustAllCertificates) { + this.configFile = new File(configFile); - public File getConfigFile() { - return configFile; + if (!this.configFile.exists()) { + throw new IllegalStateException("The configuration file " + configFile + " does not exist!"); + } + if (!this.configFile.canRead()) { + throw new IllegalStateException("The configuration file " + configFile + " is not readable!"); + } + + this.trustAllCertificates = trustAllCertificates; } - public void setConfigFile(File configFile) { - this.configFile = configFile; + public File getConfigFile() { + return configFile; } public boolean isTrustAllCertificates() { return trustAllCertificates; } - public void setTrustAllCertificates(boolean trustAllCertificates) { - this.trustAllCertificates = trustAllCertificates; - } - } diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java index 181a9285ab..f201239ac2 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java @@ -4,10 +4,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,57 +20,22 @@ class SecretValidatorExecutionContextFactoryTest { private SecretValidatorProperties invalidProperties; private SecretValidatorProperties validProperties; - private static final File invalidSarifFile = new File("src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"); - private static final File invalidConfigFile = new File("src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"); - private static final File validSarifFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); - private static final File validConfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); + private static final String invalidSarifFile = "src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"; + private static final String invalidConfigFile = "src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"; + private static final String validSarifFile = "src/test/resources/config-test-files/valid-files/test-result.txt"; + private static final String validConfigFile = "src/test/resources/config-test-files/valid-files/test-config.json"; @BeforeEach void beforeEach() { factoryToTest = new SecretValidatorExecutionContextFactory(); - invalidsecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - invalidsecretValidatorPDSJobResult.setFile(invalidSarifFile); - - invalidProperties = new SecretValidatorProperties(); - invalidProperties.setConfigFile(invalidConfigFile); - - validSecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - validSecretValidatorPDSJobResult.setFile(validSarifFile); - - validProperties = new SecretValidatorProperties(); - validProperties.setConfigFile(validConfigFile); - } - - @Test - void not_existing_pds_job_result_file_throws_exception() { - /* prepare */ - File notExisting = mock(File.class); - when(notExisting.exists()).thenReturn(false); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(notExisting); - - factoryToTest.pdsResult = secretValidatorPDSJobResult; + invalidsecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(invalidSarifFile); - /* execute + test */ - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("PDS job result file: " + notExisting + " does not exist!", exception.getMessage()); - } + invalidProperties = new SecretValidatorProperties(invalidConfigFile, false); - @Test - void not_readable_pds_job_result_file_throws_exception() { - /* prepare */ - File notReadable = mock(File.class); - when(notReadable.exists()).thenReturn(true); - when(notReadable.canRead()).thenReturn(false); - SecretValidatorPDSJobResult secretValidatorPDSJobResult = new SecretValidatorPDSJobResult(); - secretValidatorPDSJobResult.setFile(notReadable); + validSecretValidatorPDSJobResult = new SecretValidatorPDSJobResult(validSarifFile); - factoryToTest.pdsResult = secretValidatorPDSJobResult; - - /* execute + test */ - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("PDS job result file: " + notReadable + " is not readable!", exception.getMessage()); + validProperties = new SecretValidatorProperties(validConfigFile, false); } @Test @@ -87,39 +48,6 @@ void invalid_sarif_pds_job_result_file_throws_exception() { assertEquals("Creating SARIF report model from: " + invalidsecretValidatorPDSJobResult.getFile() + " failed!", exception.getMessage()); } - @Test - void not_existing_secret_validator_config_file_throws_exception() { - /* prepare */ - File notExisting = mock(File.class); - when(notExisting.exists()).thenReturn(false); - SecretValidatorProperties properties = new SecretValidatorProperties(); - properties.setConfigFile(notExisting); - - factoryToTest.pdsResult = validSecretValidatorPDSJobResult; - factoryToTest.properties = properties; - - /* execute + test */ - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("Secret validator configuration file: " + notExisting + " does not exist!", exception.getMessage()); - } - - @Test - void not_readable_secret_validator_config_file_throws_exception() { - /* prepare */ - File notReadable = mock(File.class); - when(notReadable.exists()).thenReturn(true); - when(notReadable.canRead()).thenReturn(false); - SecretValidatorProperties properties = new SecretValidatorProperties(); - properties.setConfigFile(notReadable); - - factoryToTest.pdsResult = validSecretValidatorPDSJobResult; - factoryToTest.properties = properties; - - /* execute + test */ - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> factoryToTest.create()); - assertEquals("Secret validator configuration file: " + notReadable + " is not readable!", exception.getMessage()); - } - @Test void invalid_secret_validator_config_file_throws_exception() { /* prepare */ diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java index 2d303778f9..08f88e2f02 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorConfigurationSpringBootTest.java @@ -8,14 +8,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; -@SpringBootTest(classes = { SecretValidatorProperties.class, SecretValidatorPDSJobResult.class }) +@SpringBootTest @ExtendWith(SpringExtension.class) @EnableConfigurationProperties @TestPropertySource(properties = { "secret.validator.config-file=src/test/resources/config-test-files/valid-files/test-config.json", "secret.validator.trust-all-certificates=false", "pds.job.result.file=src/test/resources/config-test-files/valid-files/test-result.txt" }) +@ActiveProfiles("test") class SecretValidatorConfigurationSpringBootTest { @Autowired From 342ec4155612dee7efe34de759b84c0bab9ed031 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 24 Jul 2024 10:45:34 +0200 Subject: [PATCH 09/10] Change string to file and add tests #3280 --- sechub-wrapper-secret-validator/build.gradle | 1 - .../SecretValidatorPDSJobResult.java | 12 ++--- .../properties/SecretValidatorProperties.java | 16 +++--- ...tValidatorExecutionContextFactoryTest.java | 10 ++-- .../SecretValidatorPDSJobResultTest.java | 54 +++++++++++++++++++ .../SecretValidatorPropertiesTest.java | 54 +++++++++++++++++++ 6 files changed, 128 insertions(+), 19 deletions(-) create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResultTest.java create mode 100644 sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPropertiesTest.java diff --git a/sechub-wrapper-secret-validator/build.gradle b/sechub-wrapper-secret-validator/build.gradle index 1a1deefb18..dc4bd23da1 100644 --- a/sechub-wrapper-secret-validator/build.gradle +++ b/sechub-wrapper-secret-validator/build.gradle @@ -10,7 +10,6 @@ dependencies { implementation project(':sechub-commons-pds') implementation library.sarif_210 - implementation library.springboot_starter_validation /* test */ testImplementation project(':sechub-testframework') diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java index 9dc11aa451..6bc6e8497c 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResult.java @@ -5,19 +5,19 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.ConstructorBinding; -import org.springframework.validation.annotation.Validated; -import jakarta.validation.constraints.NotNull; - -@Validated @ConfigurationProperties(prefix = "pds.job.result") public class SecretValidatorPDSJobResult { private final File file; @ConstructorBinding - public SecretValidatorPDSJobResult(@NotNull String file) { - this.file = new File(file); + public SecretValidatorPDSJobResult(File file) { + if (file == null) { + throw new IllegalArgumentException("The PDS result file is null!"); + } + + this.file = file; if (!this.file.exists()) { throw new IllegalArgumentException("The PDS result file " + file + " does not exist!"); diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java index 3e4c70e850..7e3112eb88 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorProperties.java @@ -5,11 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.bind.ConstructorBinding; -import org.springframework.validation.annotation.Validated; -import jakarta.validation.constraints.NotNull; - -@Validated @ConfigurationProperties(prefix = "secret.validator") public class SecretValidatorProperties { @@ -17,14 +13,18 @@ public class SecretValidatorProperties { private final boolean trustAllCertificates; @ConstructorBinding - public SecretValidatorProperties(@NotNull String configFile, boolean trustAllCertificates) { - this.configFile = new File(configFile); + public SecretValidatorProperties(File configFile, boolean trustAllCertificates) { + if (configFile == null) { + throw new IllegalArgumentException("The secret validator configuration file is null!"); + } + + this.configFile = configFile; if (!this.configFile.exists()) { - throw new IllegalStateException("The configuration file " + configFile + " does not exist!"); + throw new IllegalArgumentException("The secret validator configuration file " + configFile + " does not exist!"); } if (!this.configFile.canRead()) { - throw new IllegalStateException("The configuration file " + configFile + " is not readable!"); + throw new IllegalArgumentException("The secret validator configuration file " + configFile + " is not readable!"); } this.trustAllCertificates = trustAllCertificates; diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java index f201239ac2..1e2bc60bda 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionContextFactoryTest.java @@ -5,6 +5,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.io.File; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -20,10 +22,10 @@ class SecretValidatorExecutionContextFactoryTest { private SecretValidatorProperties invalidProperties; private SecretValidatorProperties validProperties; - private static final String invalidSarifFile = "src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"; - private static final String invalidConfigFile = "src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"; - private static final String validSarifFile = "src/test/resources/config-test-files/valid-files/test-result.txt"; - private static final String validConfigFile = "src/test/resources/config-test-files/valid-files/test-config.json"; + private static final File invalidSarifFile = new File("src/test/resources/config-test-files/invalid-files/invalid-sarif.txt"); + private static final File invalidConfigFile = new File("src/test/resources/config-test-files/invalid-files/invalid-validator-config.txt"); + private static final File validSarifFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + private static final File validConfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); @BeforeEach void beforeEach() { diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResultTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResultTest.java new file mode 100644 index 0000000000..3774fb5534 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPDSJobResultTest.java @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +class SecretValidatorPDSJobResultTest { + + @Test + void pds_job_result_file_is_null_throws_exception() { + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorPDSJobResult(null)); + } + + @Test + void not_existing_pds_job_result_file_throws_exception() { + /* prepare */ + File notExisting = mock(File.class); + when(notExisting.exists()).thenReturn(false); + + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorPDSJobResult(notExisting)); + } + + @Test + void not_readable_pds_job_result_file_throws_exception() { + /* prepare */ + File notReadable = mock(File.class); + when(notReadable.exists()).thenReturn(true); + when(notReadable.canRead()).thenReturn(false); + + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorPDSJobResult(notReadable)); + } + + @Test + void valid_properties_result_in_valid_configuration() { + /* prepare */ + File validConfigFile = new File("src/test/resources/config-test-files/valid-files/test-result.txt"); + + /* execute */ + SecretValidatorPDSJobResult pdsJobResult = new SecretValidatorPDSJobResult(validConfigFile); + + /* test */ + assertEquals(validConfigFile, pdsJobResult.getFile()); + } + +} diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPropertiesTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPropertiesTest.java new file mode 100644 index 0000000000..1700d787b9 --- /dev/null +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/properties/SecretValidatorPropertiesTest.java @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.properties; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; + +import org.junit.jupiter.api.Test; + +class SecretValidatorPropertiesTest { + + @Test + void validator_config_file_is_null_throws_exception() { + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorProperties(null, false)); + } + + @Test + void not_existing_validator_config_file_throws_exception() { + /* prepare */ + File notExisting = mock(File.class); + when(notExisting.exists()).thenReturn(false); + + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorProperties(notExisting, false)); + } + + @Test + void not_readable_validator_config_file_throws_exception() { + /* prepare */ + File notReadable = mock(File.class); + when(notReadable.exists()).thenReturn(true); + when(notReadable.canRead()).thenReturn(false); + + /* execute + test */ + assertThrows(IllegalArgumentException.class, () -> new SecretValidatorProperties(notReadable, false)); + } + + @Test + void valid_properties_result_in_valid_configuration() { + /* prepare */ + File validConfigFile = new File("src/test/resources/config-test-files/valid-files/test-config.json"); + + /* execute */ + SecretValidatorProperties properties = new SecretValidatorProperties(validConfigFile, true); + + /* test */ + assertEquals(validConfigFile, properties.getConfigFile()); + assertTrue(properties.isTrustAllCertificates()); + } + +} From 0b5359c59df4e8b56ffebd2fba36705de02fcef1 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Mon, 5 Aug 2024 15:02:07 +0200 Subject: [PATCH 10/10] PR review changes #3280 - rename module to better fitting name service - rename tests - minor changes and typo fixes --- .../execution/SecretValidationModul.java | 14 ------ .../execution/SecretValidationService.java | 35 +-------------- .../SecretValidationServiceImpl.java | 45 +++++++++++++++++++ .../SecretValidatorExecutionService.java | 2 +- .../SecretValidatorWebRequestService.java | 2 +- ...ationTestSecretValidationServiceImpl.java} | 4 +- .../cli/SecretValidatorSpringBootTest.java | 4 +- ...a => SecretValidationServiceImplTest.java} | 6 +-- .../SecretValidatorExecutionServiceTest.java | 4 +- 9 files changed, 58 insertions(+), 58 deletions(-) delete mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java create mode 100644 sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImpl.java rename sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/{IntegrationTestSecretValidationService.java => IntegrationTestSecretValidationServiceImpl.java} (93%) rename sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/{SecretValidationServiceTest.java => SecretValidationServiceImplTest.java} (96%) diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java deleted file mode 100644 index 57cdc4b8b2..0000000000 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationModul.java +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.secret.validator.execution; - -import java.util.List; - -import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; - -import de.jcup.sarif_2_1_0.model.Region; - -public interface SecretValidationModul { - - SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates); - -} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java index 2ebe7bfe52..81d07ed578 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationService.java @@ -3,43 +3,12 @@ import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Service; - import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; -import de.jcup.sarif_2_1_0.model.ArtifactContent; import de.jcup.sarif_2_1_0.model.Region; -@Profile("!" + SecretValidatorSpringProfiles.INTEGRATIONTEST) -@Service -public class SecretValidationService implements SecretValidationModul { - - private static final Logger LOG = LoggerFactory.getLogger(SecretValidationService.class); - - @Autowired - SecretValidatorWebRequestService webRequestService; - - @Override - public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { - ArtifactContent snippet = findingRegion.getSnippet(); - SecretValidationResult validationResult = new SecretValidationResult(); - if (snippet == null) { - LOG.warn("Cannot validate finding because the SARIF snippet is null."); - validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); - return validationResult; - } +public interface SecretValidationService { - String snippetText = snippet.getText(); - if (snippetText == null || snippetText.isBlank()) { - LOG.warn("Cannot validate finding because the SARIF snippet text is null or empty."); - validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); - return validationResult; - } - return webRequestService.validateFinding(snippetText, requests, trustAllCertificates); - } + SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates); } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImpl.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImpl.java new file mode 100644 index 0000000000..e38f6d6f7f --- /dev/null +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImpl.java @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.secret.validator.execution; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; + +import de.jcup.sarif_2_1_0.model.ArtifactContent; +import de.jcup.sarif_2_1_0.model.Region; + +@Profile("!" + SecretValidatorSpringProfiles.INTEGRATIONTEST) +@Service +public class SecretValidationServiceImpl implements SecretValidationService { + + private static final Logger LOG = LoggerFactory.getLogger(SecretValidationServiceImpl.class); + + @Autowired + SecretValidatorWebRequestService webRequestService; + + @Override + public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { + ArtifactContent snippet = findingRegion.getSnippet(); + SecretValidationResult validationResult = new SecretValidationResult(); + if (snippet == null) { + LOG.warn("Cannot validate finding because the SARIF snippet is null."); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + return validationResult; + } + + String snippetText = snippet.getText(); + if (snippetText == null || snippetText.isBlank()) { + LOG.warn("Cannot validate finding because the SARIF snippet text is null or empty."); + validationResult.setValidationStatus(SecretValidationStatus.SARIF_SNIPPET_NOT_SET); + return validationResult; + } + return webRequestService.validateFinding(snippetText, requests, trustAllCertificates); + } + +} diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java index 8d706a8fc1..6ff9d4b38b 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionService.java @@ -27,7 +27,7 @@ public class SecretValidatorExecutionService { SecretValidatorExecutionContextFactory contextFactory; @Autowired - SecretValidationModul validationService; + SecretValidationService validationService; @Autowired SerecoSeveritySarifEnhancementService sarifEnhancementService; diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java index ad529498af..4dbcf2d04a 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorWebRequestService.java @@ -92,7 +92,7 @@ private HttpResponse createAndExecuteHttpRequest(String snippetText, Htt response = directHttpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); } } catch (IOException | InterruptedException e) { - LOG.error("Performing validation request failed!"); + LOG.error("Performing validation request failed!", e); } return response; } diff --git a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationServiceImpl.java similarity index 93% rename from sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java rename to sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationServiceImpl.java index e5ff587342..2250eacfbc 100644 --- a/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationService.java +++ b/sechub-wrapper-secret-validator/src/main/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/test/IntegrationTestSecretValidationServiceImpl.java @@ -6,8 +6,8 @@ import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationModul; import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationResult; +import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationService; import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidationStatus; import com.mercedesbenz.sechub.wrapper.secret.validator.execution.SecretValidatorSpringProfiles; import com.mercedesbenz.sechub.wrapper.secret.validator.model.SecretValidatorRequest; @@ -25,7 +25,7 @@ */ @Profile(SecretValidatorSpringProfiles.INTEGRATIONTEST) @Service -public class IntegrationTestSecretValidationService implements SecretValidationModul { +public class IntegrationTestSecretValidationServiceImpl implements SecretValidationService { @Override public SecretValidationResult validateFindingByRegion(Region findingRegion, List requests, boolean trustAllCertificates) { diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java index bfede6e691..714048a605 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/cli/SecretValidatorSpringBootTest.java @@ -44,11 +44,11 @@ void execution_service_with_correct_configuration_without_validation_categorizes for (Result finding : run.getResults()) { // since all validation requests fail the default categorization of the config // file will be used which is high - assertFindHasSerecoSeverity("high", finding); + assertFindingHasSerecoSeverity("high", finding); } } - private void assertFindHasSerecoSeverity(String expectedSerecoSeverity, Result finding) { + private void assertFindingHasSerecoSeverity(String expectedSerecoSeverity, Result finding) { Location location = finding.getLocations().get(0); Region region = location.getPhysicalLocation().getRegion(); Map additionalProperties = region.getProperties().getAdditionalProperties(); diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImplTest.java similarity index 96% rename from sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java rename to sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImplTest.java index 0b0b66d82e..1a1c2fd76b 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidationServiceImplTest.java @@ -19,15 +19,15 @@ import de.jcup.sarif_2_1_0.model.ArtifactContent; import de.jcup.sarif_2_1_0.model.Region; -class SecretValidationServiceTest { +class SecretValidationServiceImplTest { - private SecretValidationService serviceToTest; + private SecretValidationServiceImpl serviceToTest; private SecretValidatorWebRequestService webRequestService; @BeforeEach void beforeEach() { - serviceToTest = new SecretValidationService(); + serviceToTest = new SecretValidationServiceImpl(); webRequestService = mock(SecretValidatorWebRequestService.class); serviceToTest.webRequestService = webRequestService; diff --git a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java index a2112b120f..b4e3efc859 100644 --- a/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java +++ b/sechub-wrapper-secret-validator/src/test/java/com/mercedesbenz/sechub/wrapper/secret/validator/execution/SecretValidatorExecutionServiceTest.java @@ -36,7 +36,7 @@ class SecretValidatorExecutionServiceTest { private SecretValidatorExecutionService serviceToTest; private SecretValidatorExecutionContextFactory contextFactory; - private SecretValidationService validationService; + private SecretValidationServiceImpl validationService; private SerecoSeveritySarifEnhancementService sarifEnhancementService; private SarifValidationSupport sarifValidationSupport; @@ -45,7 +45,7 @@ void beforeEach() { serviceToTest = new SecretValidatorExecutionService(); contextFactory = mock(SecretValidatorExecutionContextFactory.class); - validationService = mock(SecretValidationService.class); + validationService = mock(SecretValidationServiceImpl.class); sarifEnhancementService = mock(SerecoSeveritySarifEnhancementService.class); sarifValidationSupport = mock(SarifValidationSupport.class);