From b7d49a867db9a7dd9281b8be54f0873b320182aa Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Thu, 14 Nov 2024 10:57:51 +0100 Subject: [PATCH 01/13] Add encodingType to totp config #3611 - add entry to openapi.yaml - add field with default - extend unit tests - extend examples, documentation and RestDocTest --- .../TestWebLoginConfigurationBuilder.java | 4 +- .../commons/model/login/EncodingType.java | 25 +++++++++ .../login/WebLoginTOTPConfiguration.java | 12 +++++ .../login/WebLoginTOTPConfigurationTest.java | 6 ++- .../shared/configuration/sechub_config.adoc | 9 ++++ ...xample21_webscan_login_form_with_totp.json | 3 +- .../sechub/ExampleFilesValidTest.java | 1 + .../SchedulerRestControllerRestDocTest.java | 54 ++++--------------- .../src/main/resources/openapi.yaml | 12 +++++ 9 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java diff --git a/sechub-commons-model-testframework/src/main/java/com/mercedesbenz/sechub/commons/model/login/TestWebLoginConfigurationBuilder.java b/sechub-commons-model-testframework/src/main/java/com/mercedesbenz/sechub/commons/model/login/TestWebLoginConfigurationBuilder.java index d55646140f..1cabf1592c 100644 --- a/sechub-commons-model-testframework/src/main/java/com/mercedesbenz/sechub/commons/model/login/TestWebLoginConfigurationBuilder.java +++ b/sechub-commons-model-testframework/src/main/java/com/mercedesbenz/sechub/commons/model/login/TestWebLoginConfigurationBuilder.java @@ -41,12 +41,14 @@ public ScriptPageEntryBuilder formScripted(String user, String login) { return builder; } - public TestWebLoginConfigurationBuilder totp(String seed, int validityInSeconds, TOTPHashAlgorithm hashAlgorithm, int tokenLength) { + public TestWebLoginConfigurationBuilder totp(String seed, int validityInSeconds, TOTPHashAlgorithm hashAlgorithm, int tokenLength, + EncodingType encodingType) { WebLoginTOTPConfiguration totp = new WebLoginTOTPConfiguration(); totp.setSeed(seed); totp.setValidityInSeconds(validityInSeconds); totp.setHashAlgorithm(hashAlgorithm); totp.setTokenLength(tokenLength); + totp.setEncodingType(encodingType); loginConfig.setTotp(totp); return this; diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java new file mode 100644 index 0000000000..8c0f9857e8 --- /dev/null +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.commons.model.login; + +import com.fasterxml.jackson.annotation.JsonFormat; + +public enum EncodingType { + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + AUTODETECT, + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + HEX, + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + BASE32, + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + BASE64, + + @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + PLAIN, + + ; + +} diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfiguration.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfiguration.java index 9435499eee..9ddd3a5533 100644 --- a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfiguration.java +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfiguration.java @@ -13,20 +13,24 @@ public class WebLoginTOTPConfiguration { public static final String PROPERTY_VALIDITY_IN_SECONDS = "validityInSeconds"; public static final String PROPERTY_TOKEN_LENGTH = "tokenLength"; public static final String PROPERTY_HASH_ALGORITHM = "hashAlgorithm"; + public static final String PROPERTY_ENCODING_TYPE = "encodingType"; public static final int DEFAULT_VALIDITY_IN_SECONDS = 30; public static final int DEFAULT_TOKEN_LENGTH = 6; public static final TOTPHashAlgorithm DEFAULT_HASH_ALGORITHM = TOTPHashAlgorithm.HMAC_SHA1; + public static final EncodingType DEFAULT_ENCODING_TYPE = EncodingType.AUTODETECT; private SealedObject seed; private int validityInSeconds; private int tokenLength; private TOTPHashAlgorithm hashAlgorithm; + private EncodingType encodingType; public WebLoginTOTPConfiguration() { this.validityInSeconds = DEFAULT_VALIDITY_IN_SECONDS; this.tokenLength = DEFAULT_TOKEN_LENGTH; this.hashAlgorithm = DEFAULT_HASH_ALGORITHM; + this.encodingType = DEFAULT_ENCODING_TYPE; } public String getSeed() { @@ -61,4 +65,12 @@ public void setHashAlgorithm(TOTPHashAlgorithm hashAlgorithm) { this.hashAlgorithm = hashAlgorithm; } + public EncodingType getEncodingType() { + return encodingType; + } + + public void setEncodingType(EncodingType encodingType) { + this.encodingType = encodingType; + } + } diff --git a/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfigurationTest.java b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfigurationTest.java index 877b334bae..8f6b8df019 100644 --- a/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfigurationTest.java +++ b/sechub-commons-model/src/test/java/com/mercedesbenz/sechub/commons/model/login/WebLoginTOTPConfigurationTest.java @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.commons.model.login; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; @@ -19,6 +19,7 @@ void default_values_are_as_expected() { assertEquals(WebLoginTOTPConfiguration.DEFAULT_VALIDITY_IN_SECONDS, defaultConfig.getValidityInSeconds()); assertEquals(WebLoginTOTPConfiguration.DEFAULT_TOKEN_LENGTH, defaultConfig.getTokenLength()); assertEquals(WebLoginTOTPConfiguration.DEFAULT_HASH_ALGORITHM, defaultConfig.getHashAlgorithm()); + assertEquals(WebLoginTOTPConfiguration.DEFAULT_ENCODING_TYPE, defaultConfig.getEncodingType()); } @Test @@ -35,6 +36,7 @@ void default_values_are_used_correctly_during_json_serialization_and_deserializa assertEquals(config.getValidityInSeconds(), expectedConfig.getValidityInSeconds()); assertEquals(config.getTokenLength(), expectedConfig.getTokenLength()); assertEquals(config.getHashAlgorithm(), expectedConfig.getHashAlgorithm()); + assertEquals(config.getEncodingType(), expectedConfig.getEncodingType()); } @Test @@ -45,6 +47,7 @@ void custom_values_are_used_correctly_during_json_serialization_and_deserializat expectedConfig.setValidityInSeconds(45); expectedConfig.setTokenLength(9); expectedConfig.setHashAlgorithm(TOTPHashAlgorithm.HMAC_SHA512); + expectedConfig.setEncodingType(EncodingType.BASE64); /* execute */ String json = JSONConverter.get().toJSON(expectedConfig); @@ -55,6 +58,7 @@ void custom_values_are_used_correctly_during_json_serialization_and_deserializat assertEquals(config.getValidityInSeconds(), expectedConfig.getValidityInSeconds()); assertEquals(config.getTokenLength(), expectedConfig.getTokenLength()); assertEquals(config.getHashAlgorithm(), expectedConfig.getHashAlgorithm()); + assertEquals(config.getEncodingType(), expectedConfig.getEncodingType()); } } diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc index 39c0d463a6..83f1644c72 100644 --- a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc +++ b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc @@ -328,6 +328,15 @@ The currently available hash algorithms are: - `HMAC_SHA1` - `HMAC_SHA256` - `HMAC_SHA512` +<6> The `encodingType` is an __optional__ field, representing the encoding of the __mandatory__ field `seed`. +Sechub has a default configured if nothing is specified or the encoding type is not known. +The default value is `AUTODETECT` where SecHub tries to detect the encoding of one of the four other available types. + The currently available encoding types for `seed` are, which are treated case-insensitive: +- `BASE64` +- `BASE32` +- `HEX` +- `PLAIN` +- `AUTODETECT` [[sechub-config-example-webscan-openapi]] ====== Example OpenAPI scan diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config_example21_webscan_login_form_with_totp.json b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config_example21_webscan_login_form_with_totp.json index 989a54b318..110468808a 100644 --- a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config_example21_webscan_login_form_with_totp.json +++ b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config_example21_webscan_login_form_with_totp.json @@ -27,7 +27,8 @@ "seed" : "example-seed", //<2> "validityInSeconds" : 60, //<3> "tokenLength" : 8, //<4> - "hashAlgorithm" : "HMAC_SHA256" //<5> + "hashAlgorithm" : "HMAC_SHA256", //<5> + "encodingType" : "base64" //<6> } } } diff --git a/sechub-doc/src/test/java/com/mercedesbenz/sechub/ExampleFilesValidTest.java b/sechub-doc/src/test/java/com/mercedesbenz/sechub/ExampleFilesValidTest.java index d7c8500f5c..786c247b73 100644 --- a/sechub-doc/src/test/java/com/mercedesbenz/sechub/ExampleFilesValidTest.java +++ b/sechub-doc/src/test/java/com/mercedesbenz/sechub/ExampleFilesValidTest.java @@ -307,6 +307,7 @@ void webscan_form_based_script_auth_with_totp_can_be_read_and_contains_expected_ assertEquals(60, totp.getValidityInSeconds()); assertEquals(8, totp.getTokenLength()); assertEquals(TOTPHashAlgorithm.HMAC_SHA256, totp.getHashAlgorithm()); + assertEquals(EncodingType.BASE64, totp.getEncodingType()); } private void assertDefaultValue(PDSProductSetup setup, boolean isMandatory, String parameterKey, String expectedDefault) { diff --git a/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/SchedulerRestControllerRestDocTest.java b/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/SchedulerRestControllerRestDocTest.java index 82aa3f5248..f68687e0e9 100644 --- a/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/SchedulerRestControllerRestDocTest.java +++ b/sechub-doc/src/test/java/com/mercedesbenz/sechub/restdoc/SchedulerRestControllerRestDocTest.java @@ -3,17 +3,17 @@ import static com.mercedesbenz.sechub.commons.core.CommonConstants.*; import static com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel.*; -import static com.mercedesbenz.sechub.commons.model.TestSecHubConfigurationBuilder.*; -import static com.mercedesbenz.sechub.restdoc.RestDocumentation.*; +import static com.mercedesbenz.sechub.commons.model.TestSecHubConfigurationBuilder.configureSecHub; +import static com.mercedesbenz.sechub.restdoc.RestDocumentation.defineRestService; import static com.mercedesbenz.sechub.test.RestDocPathParameter.*; -import static com.mercedesbenz.sechub.test.SecHubTestURLBuilder.*; +import static com.mercedesbenz.sechub.test.SecHubTestURLBuilder.https; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.restdocs.headers.HeaderDocumentation.*; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.io.InputStream; @@ -42,57 +42,24 @@ import org.springframework.util.StringUtils; import com.mercedesbenz.sechub.commons.core.CommonConstants; -import com.mercedesbenz.sechub.commons.model.ClientCertificateConfiguration; -import com.mercedesbenz.sechub.commons.model.HTTPHeaderConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubCodeScanConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubConfigurationMetaData; -import com.mercedesbenz.sechub.commons.model.SecHubDataConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubDataConfigurationUsageByName; -import com.mercedesbenz.sechub.commons.model.SecHubFileSystemConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubInfrastructureScanConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubSourceDataConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubTimeUnit; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanApiConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanApiType; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; -import com.mercedesbenz.sechub.commons.model.TrafficLight; -import com.mercedesbenz.sechub.commons.model.WebScanDurationConfiguration; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.commons.model.job.ExecutionResult; import com.mercedesbenz.sechub.commons.model.job.ExecutionState; -import com.mercedesbenz.sechub.commons.model.login.ActionType; -import com.mercedesbenz.sechub.commons.model.login.FormLoginConfiguration; -import com.mercedesbenz.sechub.commons.model.login.TOTPHashAlgorithm; -import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; -import com.mercedesbenz.sechub.commons.model.login.WebLoginTOTPConfiguration; +import com.mercedesbenz.sechub.commons.model.login.*; import com.mercedesbenz.sechub.docgen.util.RestDocFactory; import com.mercedesbenz.sechub.docgen.util.RestDocTestFileSupport; -import com.mercedesbenz.sechub.domain.schedule.ScheduleJobStatus; -import com.mercedesbenz.sechub.domain.schedule.SchedulerApproveJobService; -import com.mercedesbenz.sechub.domain.schedule.SchedulerBinariesUploadService; -import com.mercedesbenz.sechub.domain.schedule.SchedulerCreateJobService; -import com.mercedesbenz.sechub.domain.schedule.SchedulerGetJobStatusService; -import com.mercedesbenz.sechub.domain.schedule.SchedulerRestController; -import com.mercedesbenz.sechub.domain.schedule.SchedulerResult; -import com.mercedesbenz.sechub.domain.schedule.SchedulerSourcecodeUploadService; +import com.mercedesbenz.sechub.domain.schedule.*; import com.mercedesbenz.sechub.domain.schedule.access.ScheduleAccess; import com.mercedesbenz.sechub.domain.schedule.access.ScheduleAccess.ProjectAccessCompositeKey; import com.mercedesbenz.sechub.domain.schedule.access.ScheduleAccessRepository; -import com.mercedesbenz.sechub.domain.schedule.job.ScheduleSecHubJob; -import com.mercedesbenz.sechub.domain.schedule.job.SecHubJobInfoForUser; -import com.mercedesbenz.sechub.domain.schedule.job.SecHubJobInfoForUserListPage; -import com.mercedesbenz.sechub.domain.schedule.job.SecHubJobInfoForUserService; -import com.mercedesbenz.sechub.domain.schedule.job.SecHubJobRepository; +import com.mercedesbenz.sechub.domain.schedule.job.*; import com.mercedesbenz.sechub.sharedkernel.Profiles; import com.mercedesbenz.sechub.sharedkernel.configuration.AbstractSecHubAPISecurityConfiguration; import com.mercedesbenz.sechub.sharedkernel.configuration.SecHubConfiguration; import com.mercedesbenz.sechub.sharedkernel.configuration.SecHubConfigurationValidator; import com.mercedesbenz.sechub.sharedkernel.usecases.UseCaseRestDoc; import com.mercedesbenz.sechub.sharedkernel.usecases.job.UseCaseUserListsJobsForProject; -import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.UseCaseUserApprovesJob; -import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.UseCaseUserChecksJobStatus; -import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.UseCaseUserCreatesNewJob; -import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.UseCaseUserUploadsBinaries; -import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.UseCaseUserUploadsSourceCode; +import com.mercedesbenz.sechub.sharedkernel.usecases.user.execute.*; import com.mercedesbenz.sechub.test.ExampleConstants; import com.mercedesbenz.sechub.test.TestIsNecessaryForDocumentation; import com.mercedesbenz.sechub.test.TestPortProvider; @@ -755,7 +722,7 @@ public void restDoc_userCreatesNewJob_webScan_login_form_script_and_totp_as_seco webConfig(). addURI("https://localhost/mywebapp"). login("https://localhost/mywebapp/login"). - totp("example-seed", 30, TOTPHashAlgorithm.HMAC_SHA1, 6). + totp("example-seed", 30, TOTPHashAlgorithm.HMAC_SHA1, 6, EncodingType.BASE32). formScripted("username1","password1"). createPage(). createAction(). @@ -817,6 +784,7 @@ public void restDoc_userCreatesNewJob_webScan_login_form_script_and_totp_as_seco fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+WebLoginConfiguration.PROPERTY_TOTP+"."+WebLoginTOTPConfiguration.PROPERTY_VALIDITY_IN_SECONDS).description("The time in seconds the generated TOTP is valid. In most cases nothing is specified and the default of '"+WebLoginTOTPConfiguration.DEFAULT_VALIDITY_IN_SECONDS+"' seconds is used.").optional(), fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+WebLoginConfiguration.PROPERTY_TOTP+"."+WebLoginTOTPConfiguration.PROPERTY_TOKEN_LENGTH).description("The length of the generated TOTP. In most cases nothing is specified and the default length '"+WebLoginTOTPConfiguration.DEFAULT_TOKEN_LENGTH+"' is used.").optional(), fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+WebLoginConfiguration.PROPERTY_TOTP+"."+WebLoginTOTPConfiguration.PROPERTY_HASH_ALGORITHM).description("The hash algorithm to generate the TOTP. In most cases nothing is specified and the default hash algorithm '"+WebLoginTOTPConfiguration.DEFAULT_HASH_ALGORITHM+"' is used. Currently available values are: 'HMAC_SHA1', 'HMAC_SHA256', 'HMAC_SHA512'").optional(), + fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+WebLoginConfiguration.PROPERTY_TOTP+"."+WebLoginTOTPConfiguration.PROPERTY_ENCODING_TYPE).description("The encoding type of the 'seed'. The default value is '"+WebLoginTOTPConfiguration.DEFAULT_ENCODING_TYPE+"'. Currently available values are: 'BASE64', 'BASE32', 'HEX', 'PLAIN', 'AUTODETECT'").optional(), fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+".url").description("Login URL").optional(), fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+FORM).description("form login definition").optional(), fieldWithPath(PROPERTY_WEB_SCAN+"."+SecHubWebScanConfiguration.PROPERTY_LOGIN+"."+FORM+"."+SCRIPT).description("script").optional(), diff --git a/sechub-openapi-java/src/main/resources/openapi.yaml b/sechub-openapi-java/src/main/resources/openapi.yaml index 316395f78f..cb55881156 100644 --- a/sechub-openapi-java/src/main/resources/openapi.yaml +++ b/sechub-openapi-java/src/main/resources/openapi.yaml @@ -650,6 +650,8 @@ components: format: int32 hashAlgorithm: $ref: '#/components/schemas/TOTPHashAlgorithm' + encodingType: + $ref: '#/components/schemas/EncodingType' required: - seed @@ -661,6 +663,16 @@ components: - HmacSHA512 description: Representing the TOTP hash algorithms. default: HmacSHA1 + + EncodingType: + enum: + - AUTODETECT + - HEX + - BASE32 + - BASE64 + - PLAIN + description: Representing the encoding of the TOTP seed. + default: AUTODETECT WebLoginConfiguration: title: WebLoginConfiguration From 7d600081fe5234743b614c3dc4a753fff734f745 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Thu, 14 Nov 2024 11:38:09 +0100 Subject: [PATCH 02/13] Update totp generator and add seed decoding #3611 - add decoder with autodetect method and unit testcases - add seed to totp generator and change signature - update unit testcases --- .../sechub/zapwrapper/util/StringDecoder.java | 84 +++++++++++++++++++ .../sechub/zapwrapper/util/TOTPGenerator.java | 26 +++--- .../zapwrapper/util/StringDecoderTest.java | 58 +++++++++++++ .../zapwrapper/util/TOTPGeneratorTest.java | 16 ++-- 4 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java create mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java new file mode 100644 index 0000000000..73168048f0 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.util; + +import java.util.regex.Pattern; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Base32; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.binary.Hex; + +import com.mercedesbenz.sechub.commons.model.login.EncodingType; + +public class StringDecoder { + + private static final String HEX_REGEX = "^(0x|#)?[\\p{XDigit}]+$"; + private static final Pattern HEX_PATTERN = Pattern.compile(HEX_REGEX); + + private static final String BASE32_REGEX = "^[A-Z2-7]+=*$"; + private static final Pattern BASE32_PATTERN = Pattern.compile(BASE32_REGEX); + + private static final String BASE64_REGEX = "^[-A-Za-z0-9+/]+=*$"; + private static final Pattern BASE64_PATTERN = Pattern.compile(BASE64_REGEX); + + public byte[] decodeIfNecessary(String seed, EncodingType encodingType) { + if (seed == null) { + throw new IllegalArgumentException("The secret key must not be null!"); + } + // some services generate keys with spaces + seed = seed.replaceAll("\\s", ""); + + EncodingType realEncodingType = encodingType; + if (encodingType == EncodingType.AUTODETECT) { + realEncodingType = detectEncoding(seed); + } + + try { + switch (realEncodingType) { + case HEX: + return Hex.decodeHex(seed); + case BASE32: + Base32 base32 = new Base32(); + return base32.decode(seed); + case BASE64: + return Base64.decodeBase64(seed); + case PLAIN: + default: + return seed.getBytes(); + } + } catch (DecoderException e) { + throw new IllegalArgumentException("The secret key could not be decoded!", e); + } + } + + /** + * This detection can produce errors of the regex and the length matches with a + * human readable string as input. In the context of secret keys which are + * usually random it should be enough to handle the encodings correctly. + * + * Normally a service generates a random secret key for TOTP and nothing like + * 'example1', which technically would match the condition for BASE64 below. + * + * @param string + * @return + */ + private EncodingType detectEncoding(String string) { + if (HEX_PATTERN.matcher(string).matches()) { + return EncodingType.HEX; + } + if (BASE32_PATTERN.matcher(string).matches()) { + // base32 string length is always a multiple of 8 + if (string.length() % 8 == 0) { + return EncodingType.BASE32; + } + } + if (BASE64_PATTERN.matcher(string).matches()) { + // base64 string length is always a multiple of 4 + if (string.length() % 4 == 0) { + return EncodingType.BASE64; + } + } + return EncodingType.PLAIN; + } + +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java index 13c6126aff..8f8b98f391 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java @@ -6,8 +6,10 @@ import java.security.NoSuchAlgorithmException; import javax.crypto.Mac; +import javax.crypto.SealedObject; import javax.crypto.spec.SecretKeySpec; +import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; import com.mercedesbenz.sechub.commons.model.login.TOTPHashAlgorithm; /** @@ -22,16 +24,22 @@ public class TOTPGenerator { private static final int DEFAULT_TOTP_LENGTH = 6; private static final int DEFAULT_TOKEN_VALIDITY_TIME_IN_SECONDS = 30; + private SealedObject seed; private String hashAlgorithmName; private int totpLength; private int tokenValidityTimeInSeconds; private long digitsTruncate; - public TOTPGenerator() { - this(DEFAULT_TOTP_LENGTH, TOTPHashAlgorithm.HMAC_SHA1, DEFAULT_TOKEN_VALIDITY_TIME_IN_SECONDS); + public TOTPGenerator(String seed) { + this(seed, DEFAULT_TOTP_LENGTH, TOTPHashAlgorithm.HMAC_SHA1, DEFAULT_TOKEN_VALIDITY_TIME_IN_SECONDS); } - public TOTPGenerator(int totpLength, TOTPHashAlgorithm hashAlgorithm, int tokenValidityTimeInSeconds) { + public TOTPGenerator(String seed, int totpLength, TOTPHashAlgorithm hashAlgorithm, int tokenValidityTimeInSeconds) { + if (seed == null) { + throw new IllegalArgumentException("The specified seed must not be null!"); + } + + this.seed = CryptoAccess.CRYPTO_STRING.seal(seed); this.totpLength = totpLength; this.hashAlgorithmName = hashAlgorithm.getName(); this.tokenValidityTimeInSeconds = tokenValidityTimeInSeconds; @@ -48,12 +56,8 @@ public TOTPGenerator(int totpLength, TOTPHashAlgorithm hashAlgorithm, int tokenV * @param currentTimeMillis * @return */ - public String generateTOTP(byte[] seed, long currentTimeMillis) { - if (seed == null) { - throw new IllegalArgumentException("The specified seed must not be null!"); - } - - byte[] hash = computeHash(seed, currentTimeMillis); + public String generateTOTP(long currentTimeMillis) { + byte[] hash = computeHash(currentTimeMillis); int offset = hash[hash.length - 1] & 0xf; /* @formatter:off */ @@ -68,10 +72,10 @@ public String generateTOTP(byte[] seed, long currentTimeMillis) { return String.format("%0" + totpLength + "d", otp); } - private byte[] computeHash(byte[] seed, long currentTimeMillis) { + private byte[] computeHash(long currentTimeMillis) { try { Mac mac = Mac.getInstance(hashAlgorithmName); - mac.init(new SecretKeySpec(seed, hashAlgorithmName)); + mac.init(new SecretKeySpec(CryptoAccess.CRYPTO_STRING.unseal(seed).getBytes(), hashAlgorithmName)); byte[] timeBytes = computeTimeBytes(currentTimeMillis, tokenValidityTimeInSeconds); byte[] hash = mac.doFinal(timeBytes); return hash; diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java new file mode 100644 index 0000000000..77aee2a729 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.apache.commons.codec.DecoderException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import com.mercedesbenz.sechub.commons.model.login.EncodingType; + +class StringDecoderTest { + + private StringDecoder supportToTest = new StringDecoder(); + + @Test + void when_secret_key_is_null_an_exception_is_thrown() { + /* execute + test */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> supportToTest.decodeIfNecessary(null, EncodingType.AUTODETECT)); + + assertEquals("The secret key must not be null!", exception.getMessage()); + } + + /* @formatter:off */ + @ParameterizedTest + @ValueSource(strings = { "746573742d737472696e67", + " 7465 7374 2d 73 7472 696e 67 ", + "7465 7374 2D73 7472 696E 67", + "746573742D737472696E67", + "ORSXG5BNON2HE2LOM4======", + " ORSXG5 BNON2HE2L OM4===== = ", + "dGVzdC1zdHJpbmc=", " dG VzdC 1zdHJp bmc =" + }) + /* @formatter:on */ + void encoded_values_are_decoded_correctly_ignoring_spaces_or_tabs(String value) throws DecoderException { + /* prepare */ + String expected = "test-string"; + + /* execute */ + byte[] decoded = supportToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); + + /* test */ + assertEquals(expected, new String(decoded)); + } + + @ParameterizedTest + @ValueSource(strings = { "���", "NotEncoded!", "@:_DASF2daagjtz", "HelloWorld" }) + void not_encoded_values_are_correctly_treated_ignoring_spaces_or_tabs(String value) throws DecoderException { + /* execute */ + byte[] decoded = supportToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); + + /* test */ + assertEquals(value, new String(decoded)); + } + +} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java index 77c07b31f4..1d0a0c1fc4 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.nio.charset.StandardCharsets; import java.util.stream.Stream; import org.apache.commons.codec.DecoderException; @@ -22,11 +23,8 @@ class TOTPGeneratorTest { @Test void secret_key_being_null_throws_exception() { - /* prepare */ - TOTPGenerator totpGenerator = new TOTPGenerator(); - /* execute + test */ - assertThrows(IllegalArgumentException.class, () -> totpGenerator.generateTOTP(null, 1000L)); + assertThrows(IllegalArgumentException.class, () -> new TOTPGenerator(null)); } @Test @@ -36,11 +34,12 @@ void generate_the_excpected_otp_with_default_config() throws DecoderException { byte[] seedBytes = new Base32().decode(seed); long timeMillis = 1724650799055L; String expectedToken = "950308"; + String seedDecoded = new String(seedBytes, StandardCharsets.UTF_8); - TOTPGenerator totpGenerator = new TOTPGenerator(); + TOTPGenerator totpGenerator = new TOTPGenerator(seedDecoded); /* execute */ - String generatedToken = totpGenerator.generateTOTP(seedBytes, timeMillis); + String generatedToken = totpGenerator.generateTOTP(timeMillis); /* test */ assertEquals(expectedToken, generatedToken); @@ -52,11 +51,12 @@ void rfc_6238_test_data_generate_the_excpected_otp(String seed, long timeInMilli int totpValidityTimeInSeconds, String expectedToken) throws DecoderException { /* prepare */ byte[] seedBytes = Hex.decodeHex(seed); + String seedDecoded = new String(seedBytes, StandardCharsets.UTF_8); - TOTPGenerator totpGenerator = new TOTPGenerator(totpLength, algorithm, totpValidityTimeInSeconds); + TOTPGenerator totpGenerator = new TOTPGenerator(seedDecoded, totpLength, algorithm, totpValidityTimeInSeconds); /* execute */ - String generatedToken = totpGenerator.generateTOTP(seedBytes, timeInMillis); + String generatedToken = totpGenerator.generateTOTP(timeInMillis); /* test */ assertEquals(expectedToken, generatedToken); From 6d990f9c09a4f43b1e2576d1afc38eb2593c83c6 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Fri, 15 Nov 2024 07:43:04 +0100 Subject: [PATCH 03/13] Refactoring of usage --- .../zapwrapper/cli/ZapScanExecutor.java | 11 +- .../sechub/zapwrapper/cli/ZapWrapperCLI.java | 4 +- .../zapwrapper/config/ZapScanContext.java | 29 ++- .../config/ZapScanContextFactory.java | 137 +++++++---- .../zapwrapper/config/ZapScannerFactory.java | 6 +- .../SecHubWebScanConfigurationHelper.java | 56 ----- .../zapwrapper/helper/ZapPDSEventHandler.java | 4 +- .../helper/ZapProductMessageHelper.java | 2 +- .../ZapWrapperDataSectionFileSupport.java | 2 +- ...ntApiFacade.java => ClientApiSupport.java} | 118 ++++++++- .../config/ZapScanContextFactoryTest.java | 225 +++++++----------- .../SecHubWebScanConfigurationHelperTest.java | 51 ---- .../helper/ZapPDSEventHandlerTest.java | 22 +- .../ZapWrapperDataSectionFileSupportTest.java | 2 +- 14 files changed, 339 insertions(+), 330 deletions(-) delete mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelper.java rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/{config => helper}/ZapWrapperDataSectionFileSupport.java (99%) rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/{ClientApiFacade.java => ClientApiSupport.java} (88%) delete mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelperTest.java rename sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/{config => helper}/ZapWrapperDataSectionFileSupportTest.java (99%) diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapScanExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapScanExecutor.java index 076eac6fe0..c1e7b31a62 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapScanExecutor.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapScanExecutor.java @@ -12,13 +12,12 @@ public class ZapScanExecutor { private static final Logger LOG = LoggerFactory.getLogger(ZapScanExecutor.class); - ZapScannerFactory zapScannerFactory; + private final ZapScannerFactory zapScannerFactory; + private final TargetConnectionChecker connectionChecker; - TargetConnectionChecker connectionChecker; - - public ZapScanExecutor() { - zapScannerFactory = new ZapScannerFactory(); - connectionChecker = new TargetConnectionChecker(); + public ZapScanExecutor(ZapScannerFactory zapScannerFactory, TargetConnectionChecker connectionChecker) { + this.zapScannerFactory = zapScannerFactory; + this.connectionChecker = connectionChecker; } public void execute(ZapScanContext scanContext) throws ZapWrapperRuntimeException { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapWrapperCLI.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapWrapperCLI.java index 40cdd9804c..15190882b4 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapWrapperCLI.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/ZapWrapperCLI.java @@ -8,6 +8,8 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperCommandLineParser.ZapWrapperCommandLineParserException; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; +import com.mercedesbenz.sechub.zapwrapper.config.ZapScannerFactory; +import com.mercedesbenz.sechub.zapwrapper.util.TargetConnectionChecker; public class ZapWrapperCLI { private static final Logger LOG = LoggerFactory.getLogger(ZapWrapperCLI.class); @@ -45,7 +47,7 @@ private ZapScanContext resolveScanContext(String[] args) throws ZapWrapperComman } private void startExecution(ZapScanContext scanContext) { - ZapScanExecutor scanExecutor = new ZapScanExecutor(); + ZapScanExecutor scanExecutor = new ZapScanExecutor(new ZapScannerFactory(), new TargetConnectionChecker()); scanExecutor.execute(scanContext); } } \ No newline at end of file diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java index acb96759ea..4fed08ed68 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java @@ -14,7 +14,6 @@ import java.util.Set; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; @@ -33,8 +32,6 @@ public class ZapScanContext { private URL targetUrl; - private AuthenticationType authenticationType; - private long maxScanDurationInMilliSeconds; private SecHubWebScanConfiguration secHubWebScanConfiguration; @@ -62,6 +59,7 @@ public class ZapScanContext { private File clientCertificateFile; private Map headerValueFiles; private String ajaxSpiderBrowserId; + private File groovyScriptLoginFile; private ZapScanContext() { } @@ -98,10 +96,6 @@ public URL getTargetUrl() { return targetUrl; } - public AuthenticationType getAuthenticationType() { - return authenticationType; - } - public long getMaxScanDurationInMilliSeconds() { return maxScanDurationInMilliSeconds; } @@ -181,6 +175,10 @@ public String getAjaxSpiderBrowserId() { return ajaxSpiderBrowserId; } + public File getGroovyScriptLoginFile() { + return groovyScriptLoginFile; + } + public static ZapScanContextBuilder builder() { return new ZapScanContextBuilder(); } @@ -199,8 +197,6 @@ public static class ZapScanContextBuilder { private URL targetUrl; - private AuthenticationType authenticationType; - private long maxScanDurationInMilliSeconds; private SecHubWebScanConfiguration secHubWebScanConfiguration; @@ -232,6 +228,8 @@ public static class ZapScanContextBuilder { private String ajaxSpiderBrowserId; + private File groovyScriptLoginFile; + public ZapScanContextBuilder setServerConfig(ZapServerConfiguration serverConfig) { this.serverConfig = serverConfig; return this; @@ -267,11 +265,6 @@ public ZapScanContextBuilder setTargetUrl(URL targetUrl) { return this; } - public ZapScanContextBuilder setAuthenticationType(AuthenticationType authenticationType) { - this.authenticationType = authenticationType; - return this; - } - public ZapScanContextBuilder setMaxScanDurationInMilliSeconds(long maxScanDurationInMilliSeconds) { this.maxScanDurationInMilliSeconds = maxScanDurationInMilliSeconds; return this; @@ -352,6 +345,11 @@ public ZapScanContextBuilder setAjaxSpiderBrowserId(String ajaxSpiderBrowserId) return this; } + public ZapScanContextBuilder setGroovyScriptLoginFile(File groovyScriptLoginFile) { + this.groovyScriptLoginFile = groovyScriptLoginFile; + return this; + } + public ZapScanContext build() { ZapScanContext zapScanConfiguration = new ZapScanContext(); zapScanConfiguration.serverConfig = this.serverConfig; @@ -361,7 +359,6 @@ public ZapScanContext build() { zapScanConfiguration.reportFile = this.reportFile; zapScanConfiguration.contextName = this.contextName; zapScanConfiguration.targetUrl = this.targetUrl; - zapScanConfiguration.authenticationType = this.authenticationType; zapScanConfiguration.maxScanDurationInMilliSeconds = this.maxScanDurationInMilliSeconds; @@ -392,6 +389,8 @@ public ZapScanContext build() { zapScanConfiguration.ajaxSpiderBrowserId = this.ajaxSpiderBrowserId; + zapScanConfiguration.groovyScriptLoginFile = this.groovyScriptLoginFile; + return zapScanConfiguration; } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java index 467cc9141e..ca7e34d885 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java @@ -13,19 +13,15 @@ import org.slf4j.LoggerFactory; import com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubTimeUnit; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; import com.mercedesbenz.sechub.zapwrapper.cli.CommandLineSettings; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; -import com.mercedesbenz.sechub.zapwrapper.helper.BaseTargetUriFactory; -import com.mercedesbenz.sechub.zapwrapper.helper.IncludeExcludeToZapURLHelper; -import com.mercedesbenz.sechub.zapwrapper.helper.SecHubWebScanConfigurationHelper; -import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; -import com.mercedesbenz.sechub.zapwrapper.helper.ZapProductMessageHelper; +import com.mercedesbenz.sechub.zapwrapper.helper.*; import com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants; import com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableReader; import com.mercedesbenz.sechub.zapwrapper.util.UrlUtil; @@ -33,16 +29,21 @@ public class ZapScanContextFactory { private static final Logger LOG = LoggerFactory.getLogger(ZapScanContextFactory.class); - SecHubWebScanConfigurationHelper sechubWebConfigHelper; - EnvironmentVariableReader environmentVariableReader; - BaseTargetUriFactory targetUriFactory; - RuleProvider ruleProvider; - ZapWrapperDataSectionFileSupport dataSectionFileSupport; - SecHubScanConfigProvider secHubScanConfigProvider; - IncludeExcludeToZapURLHelper includeExcludeToZapURLHelper; + private static final int SECONDS_IN_MS = 1000; + private static final int MINUTES_IN_MS = 60 * SECONDS_IN_MS; + private static final int HOURS_IN_MS = 60 * MINUTES_IN_MS; + private static final int DAYS_IN_MS = 24 * HOURS_IN_MS; + + private static final int DEFAULT_MAX_SCAN_DURATION = 8 * HOURS_IN_MS; + + private final EnvironmentVariableReader environmentVariableReader; + private final BaseTargetUriFactory targetUriFactory; + private final RuleProvider ruleProvider; + private final ZapWrapperDataSectionFileSupport dataSectionFileSupport; + private final SecHubScanConfigProvider secHubScanConfigProvider; + private final IncludeExcludeToZapURLHelper includeExcludeToZapURLHelper; public ZapScanContextFactory() { - sechubWebConfigHelper = new SecHubWebScanConfigurationHelper(); environmentVariableReader = new EnvironmentVariableReader(); targetUriFactory = new BaseTargetUriFactory(); ruleProvider = new RuleProvider(); @@ -51,15 +52,30 @@ public ZapScanContextFactory() { includeExcludeToZapURLHelper = new IncludeExcludeToZapURLHelper(); } + ZapScanContextFactory(EnvironmentVariableReader environmentVariableReader, BaseTargetUriFactory targetUriFactory, + RuleProvider ruleProvider, ZapWrapperDataSectionFileSupport dataSectionFileSupport, + SecHubScanConfigProvider secHubScanConfigProvider, + IncludeExcludeToZapURLHelper includeExcludeToZapURLHelper) { + this.environmentVariableReader = environmentVariableReader; + this.targetUriFactory = targetUriFactory; + this.ruleProvider = ruleProvider; + this.dataSectionFileSupport = dataSectionFileSupport; + this.secHubScanConfigProvider = secHubScanConfigProvider; + this.includeExcludeToZapURLHelper = includeExcludeToZapURLHelper; + } + public ZapScanContext create(CommandLineSettings settings) { if (settings == null) { - throw new ZapWrapperRuntimeException("Command line settings must not be null!", ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); + throw new ZapWrapperRuntimeException("Command line settings must not be null!", + ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); } /* Zap rule setup */ ZapFullRuleset fullRuleset = ruleProvider.fetchFullRuleset(settings.getFullRulesetFile()); - DeactivatedRuleReferences deactivatedRuleReferences = createDeactivatedRuleReferencesFromSettingsOrEnv(settings); + DeactivatedRuleReferences deactivatedRuleReferences = createDeactivatedRuleReferencesFromSettingsOrEnv( + settings); - DeactivatedRuleReferences ruleReferencesFromFile = ruleProvider.fetchDeactivatedRuleReferences(settings.getRulesDeactvationFile()); + DeactivatedRuleReferences ruleReferencesFromFile = ruleProvider + .fetchDeactivatedRuleReferences(settings.getRulesDeactvationFile()); for (RuleReference reference : ruleReferencesFromFile.getDeactivatedRuleReferences()) { deactivatedRuleReferences.addRuleReference(reference); } @@ -71,11 +87,10 @@ public ZapScanContext create(CommandLineSettings settings) { /* SecHub settings */ URL targetUrl = targetUriFactory.create(settings.getTargetURL()); - SecHubScanConfiguration sechubScanConfig = secHubScanConfigProvider.getSecHubWebConfiguration(settings.getSecHubConfigFile()); + SecHubScanConfiguration sechubScanConfig = secHubScanConfigProvider + .getSecHubWebConfiguration(settings.getSecHubConfigFile()); SecHubWebScanConfiguration sechubWebConfig = getSecHubWebConfiguration(sechubScanConfig); - long maxScanDurationInMillis = sechubWebConfigHelper.fetchMaxScanDurationInMillis(sechubWebConfig); - - AuthenticationType authType = sechubWebConfigHelper.determineAuthenticationType(sechubWebConfig); + long maxScanDurationInMillis = fetchMaxScanDurationInMillis(sechubWebConfig); List apiDefinitionFiles = fetchApiDefinitionFiles(sechubScanConfig); @@ -106,7 +121,6 @@ public ZapScanContext create(CommandLineSettings settings) { .setAjaxSpiderBrowserId(settings.getAjaxSpiderBrowserId()) .setActiveScanEnabled(settings.isActiveScanEnabled()) .setServerConfig(serverConfig) - .setAuthenticationType(authType) .setMaxScanDurationInMilliSeconds(maxScanDurationInMillis) .setSecHubWebScanConfiguration(sechubWebConfig) .setProxyInformation(proxyInformation) @@ -122,6 +136,7 @@ public ZapScanContext create(CommandLineSettings settings) { .setRetryWaittimeInMilliseconds(settings.getRetryWaittimeInMilliseconds()) .setZapProductMessageHelper(productMessagehelper) .setZapPDSEventHandler(zapEventHandler) + .setGroovyScriptLoginFile(null) // TODO implement .build(); /* @formatter:on */ return scanContext; @@ -134,8 +149,10 @@ private DeactivatedRuleReferences createDeactivatedRuleReferencesFromSettingsOrE // if no rules to deactivate were specified via the command line, // look for rules specified via the corresponding env variable if (deactivatedRuleRefsAsString == null) { - LOG.info("Reading rules to deactivate from env variable {} if set.", EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); - deactivatedRuleRefsAsString = environmentVariableReader.readAsString(EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); + LOG.info("Reading rules to deactivate from env variable {} if set.", + EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); + deactivatedRuleRefsAsString = environmentVariableReader + .readAsString(EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); } // if no rules to deactivate were set at all, continue without @@ -169,20 +186,24 @@ private ZapServerConfiguration createZapServerConfig(CommandLineSettings setting zapPort = environmentVariableReader.readAsInt(EnvironmentVariableConstants.ZAP_PORT_ENV_VARIABLE_NAME); } if (zapApiKey == null) { - zapApiKey = environmentVariableReader.readAsString(EnvironmentVariableConstants.ZAP_API_KEY_ENV_VARIABLE_NAME); + zapApiKey = environmentVariableReader + .readAsString(EnvironmentVariableConstants.ZAP_API_KEY_ENV_VARIABLE_NAME); } if (zapHost == null) { - throw new ZapWrapperRuntimeException("Zap host is null. Please set the Zap host to the host use by the Zap.", + throw new ZapWrapperRuntimeException( + "Zap host is null. Please set the Zap host to the host use by the Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } if (zapPort <= 0) { - throw new ZapWrapperRuntimeException("Zap Port was set to " + zapPort + ". Please set the Zap port to the port used by the Zap.", + throw new ZapWrapperRuntimeException( + "Zap Port was set to " + zapPort + ". Please set the Zap port to the port used by the Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } if (zapApiKey == null) { - throw new ZapWrapperRuntimeException("Zap API-Key is null. Please set the Zap API-key to the same value set inside your Zap.", + throw new ZapWrapperRuntimeException( + "Zap API-Key is null. Please set the Zap API-key to the same value set inside your Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapServerConfiguration(zapHost, zapPort, zapApiKey); @@ -193,7 +214,8 @@ private ProxyInformation createProxyInformation(CommandLineSettings settings) { int proxyPort = settings.getProxyPort(); if (proxyHost == null) { - proxyHost = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME); + proxyHost = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME); } if (proxyPort <= 0) { proxyPort = environmentVariableReader.readAsInt(EnvironmentVariableConstants.PROXY_PORT_ENV_VARIABLE_NAME); @@ -216,28 +238,32 @@ private SecHubWebScanConfiguration getSecHubWebConfiguration(SecHubScanConfigura private List fetchApiDefinitionFiles(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchApiDefinitionFiles(extractedSourcesFolderPath, sechubScanConfig); } private File fetchClientCertificateFile(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchClientCertificateFile(extractedSourcesFolderPath, sechubScanConfig); } private Map fetchHeaderValueFiles(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchHeaderValueFiles(extractedSourcesFolderPath, sechubScanConfig); } private Set createUrlsIncludedInContext(URL targetUrl, SecHubWebScanConfiguration sechubWebConfig) { Set includeSet = new HashSet<>(); if (sechubWebConfig.getIncludes().isPresent()) { - includeSet.addAll(includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getIncludes().get())); + includeSet.addAll( + includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getIncludes().get())); } // if no includes are specified everything is included if (includeSet.isEmpty()) { @@ -251,7 +277,8 @@ private Set createUrlsIncludedInContext(URL targetUrl, SecHubWebScanConf private Set createUrlsExcludedFromContext(URL targetUrl, SecHubWebScanConfiguration sechubWebConfig) { Set excludeSet = new HashSet<>(); if (sechubWebConfig.getExcludes().isPresent()) { - excludeSet.addAll(includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getExcludes().get())); + excludeSet.addAll( + includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getExcludes().get())); } return excludeSet; } @@ -259,11 +286,14 @@ private Set createUrlsExcludedFromContext(URL targetUrl, SecHubWebScanCo private ZapProductMessageHelper createZapProductMessageHelper(CommandLineSettings settings) { String userMessagesFolder = settings.getPDSUserMessageFolder(); if (userMessagesFolder == null) { - userMessagesFolder = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER); + userMessagesFolder = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER); } if (userMessagesFolder == null) { - throw new ZapWrapperRuntimeException("PDS configuration invalid. Cannot send user messages, because environment variable " - + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER + " is not set.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); + throw new ZapWrapperRuntimeException( + "PDS configuration invalid. Cannot send user messages, because environment variable " + + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER + " is not set.", + ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapProductMessageHelper(userMessagesFolder); } @@ -271,13 +301,40 @@ private ZapProductMessageHelper createZapProductMessageHelper(CommandLineSetting private ZapPDSEventHandler createZapEventhandler(CommandLineSettings settings) { String pdsJobEventsFolder = settings.getPDSEventFolder(); if (pdsJobEventsFolder == null) { - pdsJobEventsFolder = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER); + pdsJobEventsFolder = environmentVariableReader + .readAsString(EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER); } if (pdsJobEventsFolder == null) { - throw new ZapWrapperRuntimeException("PDS configuration invalid. Cannot send check for job events, because environment variable " - + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER + " is not set.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); + throw new ZapWrapperRuntimeException( + "PDS configuration invalid. Cannot send check for job events, because environment variable " + + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER + " is not set.", + ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapPDSEventHandler(pdsJobEventsFolder); } + + private long fetchMaxScanDurationInMillis(SecHubWebScanConfiguration sechubWebConfig) { + if (sechubWebConfig.getMaxScanDuration().isEmpty()) { + return DEFAULT_MAX_SCAN_DURATION; + } + + SecHubTimeUnit sechubTimeUnit = sechubWebConfig.getMaxScanDuration().get().getUnit(); + int maxScanDuration = sechubWebConfig.getMaxScanDuration().get().getDuration(); + + switch (sechubTimeUnit) { + case DAY: + return maxScanDuration * DAYS_IN_MS; + case HOUR: + return maxScanDuration * HOURS_IN_MS; + case MINUTE: + return maxScanDuration * MINUTES_IN_MS; + case SECOND: + return maxScanDuration * SECONDS_IN_MS; + case MILLISECOND: + return maxScanDuration; + default: + return DEFAULT_MAX_SCAN_DURATION; + } + } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java index 568f0ac176..89fec8d613 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java @@ -7,7 +7,7 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiFacade; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; import com.mercedesbenz.sechub.zapwrapper.scan.ZapScanner; public class ZapScannerFactory { @@ -26,9 +26,9 @@ public ZapScanner create(ZapScanContext scanContext) { String zaproxyApiKey = serverConfig.getZaproxyApiKey(); ClientApi clientApi = new ClientApi(zaproxyHost, zaproxyPort, zaproxyApiKey); - ClientApiFacade clientApiFacade = new ClientApiFacade(clientApi); + ClientApiSupport clientApiSupport = new ClientApiSupport(clientApi); - return ZapScanner.from(clientApiFacade, scanContext); + return new ZapScanner(clientApiSupport, scanContext); } private void assertValidServerConfig(ZapServerConfiguration serverConfig) { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelper.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelper.java deleted file mode 100644 index b976c6d4ec..0000000000 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelper.java +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.helper; - -import com.mercedesbenz.sechub.commons.model.SecHubTimeUnit; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; -import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; - -public class SecHubWebScanConfigurationHelper { - private static final int SECONDS_IN_MS = 1000; - private static final int MINUTES_IN_MS = 60 * SECONDS_IN_MS; - private static final int HOURS_IN_MS = 60 * MINUTES_IN_MS; - private static final int DAYS_IN_MS = 24 * HOURS_IN_MS; - - private static final int DEFAULT_MAX_SCAN_DURATION = 8 * HOURS_IN_MS; - - public AuthenticationType determineAuthenticationType(SecHubWebScanConfiguration secHubWebScanConfiguration) { - if (secHubWebScanConfiguration == null) { - return AuthenticationType.UNAUTHENTICATED; - } - if (!secHubWebScanConfiguration.getLogin().isPresent()) { - return AuthenticationType.UNAUTHENTICATED; - } - - WebLoginConfiguration webLoginConfiguration = secHubWebScanConfiguration.getLogin().get(); - if (webLoginConfiguration.getBasic().isPresent()) { - return AuthenticationType.HTTP_BASIC_AUTHENTICATION; - } - return AuthenticationType.UNAUTHENTICATED; - } - - public long fetchMaxScanDurationInMillis(SecHubWebScanConfiguration sechubWebConfig) { - if (!sechubWebConfig.getMaxScanDuration().isPresent()) { - return DEFAULT_MAX_SCAN_DURATION; - } - - SecHubTimeUnit sechubTimeUnit = sechubWebConfig.getMaxScanDuration().get().getUnit(); - int maxScanDuration = sechubWebConfig.getMaxScanDuration().get().getDuration(); - - switch (sechubTimeUnit) { - case DAY: - return maxScanDuration * DAYS_IN_MS; - case HOUR: - return maxScanDuration * HOURS_IN_MS; - case MINUTE: - return maxScanDuration * MINUTES_IN_MS; - case SECOND: - return maxScanDuration * SECONDS_IN_MS; - case MILLISECOND: - return maxScanDuration; - default: - return DEFAULT_MAX_SCAN_DURATION; - } - } - -} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandler.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandler.java index f772ffebe5..dd0ba86a7e 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandler.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandler.java @@ -7,14 +7,14 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; public class ZapPDSEventHandler { - File cancelEventFile; + private final File cancelEventFile; public ZapPDSEventHandler(String pdsJobEventsFolder) { this.cancelEventFile = new File(pdsJobEventsFolder, "cancel_requested.json"); } public boolean isScanCancelled() { - return cancelEventFile.exists(); + return cancelEventFile.isFile(); } public void cancelScan(String scanContextName) { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapProductMessageHelper.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapProductMessageHelper.java index 93141c11b9..33407729dc 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapProductMessageHelper.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapProductMessageHelper.java @@ -17,7 +17,7 @@ public class ZapProductMessageHelper { private static final Logger LOG = LoggerFactory.getLogger(ZapProductMessageHelper.class); - private PDSUserMessageSupport productMessageSupport; + private final PDSUserMessageSupport productMessageSupport; public ZapProductMessageHelper(String userMessagesFolder) { productMessageSupport = new PDSUserMessageSupport(userMessagesFolder, new TextFileWriter()); diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupport.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupport.java similarity index 99% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupport.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupport.java index d701ed19e7..e295729e08 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupport.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupport.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.config; +package com.mercedesbenz.sechub.zapwrapper.helper; import java.io.File; import java.util.Collections; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiFacade.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java similarity index 88% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiFacade.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java index 161faa9766..75f3ad4487 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiFacade.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java @@ -14,18 +14,18 @@ import org.zaproxy.clientapi.core.ClientApi; import org.zaproxy.clientapi.core.ClientApiException; -public class ClientApiFacade { +public class ClientApiSupport { private static final String URL_KEY = "url"; private static final String STATUS_CODE_KEY = "statusCode"; private static final String STATUS_REASON_KEY = "statusReason"; private static final String METHOD_KEY = "method"; - private static final Logger LOG = LoggerFactory.getLogger(ClientApiFacade.class); + private static final Logger LOG = LoggerFactory.getLogger(ClientApiSupport.class); private ClientApi clientApi; - public ClientApiFacade(ClientApi clientApi) { + public ClientApiSupport(ClientApi clientApi) { this.clientApi = clientApi; } @@ -88,7 +88,8 @@ public ApiResponse enableAllPassiveScannerRules() throws ClientApiException { * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse enableAllActiveScannerRulesForPolicy(String policy) throws ClientApiException { - return clientApi.ascan.enableAllScanners(null); + return clientApi.ascan.enableAllScanners(policy); + } /** @@ -98,10 +99,33 @@ public ApiResponse enableAllActiveScannerRulesForPolicy(String policy) throws Cl * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse configureAjaxSpiderBrowserId(String browserId) throws ClientApiException { + public ApiResponse setAjaxSpiderBrowserId(String browserId) throws ClientApiException { return clientApi.ajaxSpider.setOptionBrowserId(browserId); } + /** + * Define the max depth of directories after the ajax spider will stop the + * recursion. + * + * @param maxDepth + * @return + * @throws ClientApiException + */ + public ApiResponse setAjaxSpiderMaxDepth(int maxDepth) throws ClientApiException { + return clientApi.spider.setOptionMaxDepth(maxDepth); + } + + /** + * Define the max depth of directories after the spider will stop the recursion. + * + * @param maxDepth + * @return + * @throws ClientApiException + */ + public ApiResponse setSpiderMaxDepth(int maxDepth) throws ClientApiException { + return clientApi.spider.setOptionMaxDepth(maxDepth); + } + /** * Disable passive rule by given ruleId. * @@ -664,6 +688,89 @@ public ApiResponse setForcedUserModeEnabled(boolean enabled) throws ClientApiExc return clientApi.forcedUser.setForcedUserModeEnabled(enabled); } + /** + * Add a new HTTP session token to ZAP with the given token identifier for the + * specified URL. The token identifier can be used to access the session later + * on. + * + * @param targetUrl + * @param sessionTokenIdentifier + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse addHTTPSessionToken(String targetUrl, String sessionTokenIdentifier) throws ClientApiException { + return clientApi.httpSessions.addSessionToken(targetUrl, sessionTokenIdentifier); + } + + /** + * Add a new HTTP session to ZAP with the given identifier for the specified + * URL. The identifier can be used to access the session later on. + * + * @param targetUrl + * @param sessionIdentifier + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse createEmptyHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + return clientApi.httpSessions.createEmptySession(targetUrl, sessionIdentifier); + + } + + /** + * Add a new HTTP session token value to ZAP with the given session identifier + * using the given name and value for the specified URL. + * + * @param targetUrl + * @param sessionIdentifier + * @param name + * @param value + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse setHTTPSessionTokenValue(String targetUrl, String sessionIdentifier, String name, String value) throws ClientApiException { + return clientApi.httpSessions.setSessionTokenValue(targetUrl, sessionIdentifier, name, value); + + } + + /** + * Set the session with the given identifier and the given URL as the active + * session the ZAP shall use. + * + * @param targetUrl + * @param sessionIdentifier + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse setActiveHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + return clientApi.httpSessions.setActiveSession(targetUrl, sessionIdentifier); + } + + /** + * Remove the session with the given identifier and the given URL from ZAP. + * + * @param targetUrl + * @param sessionIdentifier + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse removeHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + return clientApi.httpSessions.removeSession(targetUrl, sessionIdentifier); + } + + /** + * Remove the session token with the given identifier and the given URL from + * ZAP. + * + * @param targetUrl + * @param sessionIdentifier + * @return + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse removeHTTPSessionToken(String targetUrl, String sessionTokenIdentifier) throws ClientApiException { + return clientApi.httpSessions.removeSessionToken(targetUrl, sessionTokenIdentifier); + } + private String getIdOfApiResponseElement(ApiResponseElement apiResponseElement) { return apiResponseElement.getValue(); } @@ -689,4 +796,5 @@ private Map createSafeMap(Map valuesMap) { return safeMap; } + } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index f8ec409b20..1a366c9e12 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -1,27 +1,10 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.config; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.PROXY_PORT_ENV_VARIABLE_NAME; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.ZAP_API_KEY_ENV_VARIABLE_NAME; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.ZAP_HOST_ENV_VARIABLE_NAME; -import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.ZAP_PORT_ENV_VARIABLE_NAME; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableConstants.*; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.atLeast; -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 static org.mockito.Mockito.*; import java.io.File; import java.net.URI; @@ -35,23 +18,24 @@ import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mockito; import com.mercedesbenz.sechub.zapwrapper.cli.CommandLineSettings; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; -import com.mercedesbenz.sechub.zapwrapper.helper.SecHubWebScanConfigurationHelper; +import com.mercedesbenz.sechub.zapwrapper.helper.BaseTargetUriFactory; +import com.mercedesbenz.sechub.zapwrapper.helper.IncludeExcludeToZapURLHelper; +import com.mercedesbenz.sechub.zapwrapper.helper.ZapWrapperDataSectionFileSupport; import com.mercedesbenz.sechub.zapwrapper.util.EnvironmentVariableReader; class ZapScanContextFactoryTest { private ZapScanContextFactory factoryToTest; - private SecHubWebScanConfigurationHelper sechubWebConfigHelper; - private EnvironmentVariableReader environmentVariableReader; + private static final EnvironmentVariableReader ENVIRONMENT_VAIRABLE_READER = mock(); - private RuleProvider ruleProvider; + private static final RuleProvider RULE_PROVIDER = mock(); private File fullRulesetFile; private File deactivationFile; @@ -61,26 +45,21 @@ class ZapScanContextFactoryTest { @BeforeEach void beforeEach() { + Mockito.reset(ENVIRONMENT_VAIRABLE_READER, RULE_PROVIDER); // create object to test - factoryToTest = new ZapScanContextFactory(); - - // create mocks - sechubWebConfigHelper = mock(SecHubWebScanConfigurationHelper.class); - environmentVariableReader = mock(EnvironmentVariableReader.class); - ruleProvider = mock(RuleProvider.class); - - // connect mocks with test object - factoryToTest.sechubWebConfigHelper = sechubWebConfigHelper; - factoryToTest.environmentVariableReader = environmentVariableReader; - factoryToTest.ruleProvider = ruleProvider; + factoryToTest = new ZapScanContextFactory(ENVIRONMENT_VAIRABLE_READER, new BaseTargetUriFactory(), + RULE_PROVIDER, new ZapWrapperDataSectionFileSupport(), new SecHubScanConfigProvider(), + new IncludeExcludeToZapURLHelper()); // create test data fullRulesetFile = new File("src/test/resources/zap-available-rules/zap-full-ruleset.json"); - deactivationFile = new File("src/test/resources/wrapper-deactivated-rule-examples/zap-rules-to-deactivate.json"); + deactivationFile = new File( + "src/test/resources/wrapper-deactivated-rule-examples/zap-rules-to-deactivate.json"); - when(environmentVariableReader.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)).thenReturn(tempDir.getAbsolutePath()); - when(environmentVariableReader.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)) + .thenReturn(tempDir.getAbsolutePath()); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); } @Test @@ -89,22 +68,6 @@ void commandLineSettings_object_is_null_results_in_mustexitruntimeexception() { assertThrows(ZapWrapperRuntimeException.class, () -> factoryToTest.create(null)); } - @Test - void created_configuration_has_max_scan_duration_from_sechub_webconfig() { - /* prepare */ - CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - long maxScanDuration = 4711L; - when(sechubWebConfigHelper.fetchMaxScanDurationInMillis(any())).thenReturn(maxScanDuration); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - - /* execute */ - ZapScanContext result = factoryToTest.create(settings); - - /* test */ - assertEquals(result.getMaxScanDurationInMilliSeconds(), maxScanDuration); - - } - @Test void context_name_is_used_from_settings_when_defined() { /* prepare */ @@ -112,7 +75,7 @@ void context_name_is_used_from_settings_when_defined() { String jobUUID = "12345"; when(settings.getJobUUID()).thenReturn(jobUUID); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -127,7 +90,7 @@ void context_name_is_created_as_UUID_when_not_defined() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getJobUUID()).thenReturn(null); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -139,9 +102,10 @@ void context_name_is_created_as_UUID_when_not_defined() { } @ParameterizedTest - @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", "host,4711,secret,proxy,5312" }) - void result_contains_server_config_with_arguments_from_command_line_settings_no_env_variables(String host, int port, String apiKey, String proxy, - int proxyPort) { + @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", + "host,4711,secret,proxy,5312" }) + void result_contains_server_config_with_arguments_from_command_line_settings_no_env_variables(String host, int port, + String apiKey, String proxy, int proxyPort) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getZapHost()).thenReturn(host); @@ -149,7 +113,7 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ when(settings.getZapApiKey()).thenReturn(apiKey); when(settings.getProxyHost()).thenReturn(proxy); when(settings.getProxyPort()).thenReturn(proxyPort); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -164,28 +128,29 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ assertEquals(proxy, result.getProxyInformation().getHost()); assertEquals(proxyPort, result.getProxyInformation().getPort()); - verify(environmentVariableReader, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); - verify(environmentVariableReader, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); - verify(environmentVariableReader, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); - verify(environmentVariableReader, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); - verify(environmentVariableReader, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); } @ParameterizedTest - @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", "host,4711,secret,proxy,5312" }) - void result_contains_server_config_with_arguments_from_environment_when_command_line_settings_not_set(String host, int port, String apiKey, String proxy, - int proxyPort) { + @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", + "host,4711,secret,proxy,5312" }) + void result_contains_server_config_with_arguments_from_environment_when_command_line_settings_not_set(String host, + int port, String apiKey, String proxy, int proxyPort) { /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getTargetURL()).thenReturn("https://www.targeturl.com"); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(environmentVariableReader.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); - when(environmentVariableReader.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); - when(environmentVariableReader.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); + when(ENVIRONMENT_VAIRABLE_READER.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); - when(environmentVariableReader.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); - when(environmentVariableReader.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); + when(ENVIRONMENT_VAIRABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -206,10 +171,10 @@ void proxy_set_or_not_is_valid_result_returned_contains_null_as_proxyinformation CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getProxyHost()).thenReturn(null); when(settings.getProxyPort()).thenReturn(0); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(environmentVariableReader.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); - when(environmentVariableReader.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); + when(ENVIRONMENT_VAIRABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -227,11 +192,12 @@ void proxy_set_or_not_is_valid_result_returned_contains_null_as_proxyinformation ",4711,secret", }) /* @formatter:on*/ - void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(String host, Integer port, String apiKey) { + void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(String host, Integer port, + String apiKey) { /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getZapHost()).thenReturn(host); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); if (port != null) { // when not defined in CSV, null is used. The mock does use int primitive, // so we just do not set it. @@ -244,22 +210,6 @@ void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(Strin } - @Test - void authentication_type_from_config_is_in_result() { - /* prepare */ - CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - AuthenticationType type = AuthenticationType.FORM_BASED_AUTHENTICATION; - when(sechubWebConfigHelper.determineAuthenticationType(any())).thenReturn(type); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - - /* execute */ - ZapScanContext result = factoryToTest.create(settings); - - /* test */ - assertEquals(result.getAuthenticationType(), type); - - } - @Test void targetURI_calculated_by_factory_is_in_result() { /* prepare */ @@ -272,7 +222,7 @@ void targetURI_calculated_by_factory_is_in_result() { when(settings.getTargetURL()).thenReturn(targetUri); URI createdUri = URI.create("https://fromfactory.example.com"); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -288,7 +238,7 @@ void verbose_from_settings_is_in_result(boolean verboseEnabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isVerboseEnabled()).thenReturn(verboseEnabled); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -304,7 +254,7 @@ void ajaxspider_enabled_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isAjaxSpiderEnabled()).thenReturn(enabled); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -320,7 +270,7 @@ void active_scan_enabled_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isActiveScanEnabled()).thenReturn(enabled); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -336,7 +286,7 @@ void report_file_from_setting_is_used_in_result() { CommandLineSettings settings = createSettingsMockWithNecessaryParts(); Path path = new File("not-existing").toPath(); when(settings.getReportFile()).thenReturn(path); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -356,8 +306,8 @@ void commandline_settings_null_throws_zap_wrapper_runtime_exception() { void fullruleset_returned_by_provider_is_in_result() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - when(ruleProvider.fetchFullRuleset(fullRulesetFile)).thenReturn(createZapFullRuleset()); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchFullRuleset(fullRulesetFile)).thenReturn(createZapFullRuleset()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -365,7 +315,7 @@ void fullruleset_returned_by_provider_is_in_result() { ZapFullRuleset fullRuleset = result.getFullRuleset(); /* test */ - verify(ruleProvider, times(1)).fetchFullRuleset(any()); + verify(RULE_PROVIDER, times(1)).fetchFullRuleset(any()); assertNotNull(fullRuleset); assertNotNull(fullRuleset.getRules()); assertEquals("https://www.zaproxy.org/docs/alerts/", fullRuleset.getOrigin()); @@ -377,14 +327,15 @@ void fullruleset_returned_by_provider_is_in_result() { void rules_to_deactivate_returned_by_provider_is_inside_result() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - when(ruleProvider.fetchDeactivatedRuleReferences(deactivationFile)).thenReturn(createDeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(deactivationFile)) + .thenReturn(createDeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); DeactivatedRuleReferences deactivatedRuleReferences = result.getDeactivatedRuleReferences(); /* test */ - verify(ruleProvider, times(1)).fetchDeactivatedRuleReferences(any()); + verify(RULE_PROVIDER, times(1)).fetchDeactivatedRuleReferences(any()); assertNotNull(deactivatedRuleReferences); assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(2, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); @@ -398,8 +349,8 @@ void rules_to_deactivate_returned_by_provider_is_inside_result() { void rules_to_deactivate_returned_by_env_variable_is_inside_result(String value) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - when(environmentVariableReader.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); String[] arrayToTestExpectedLength = {}; if (value != null) { @@ -423,7 +374,7 @@ void rules_to_deactivate_returned_by_command_line_parameter_is_inside_result(Str /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getDeactivatedRuleReferences()).thenReturn(value); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); String[] arrayToTestExpectedLength = {}; if (value != null) { @@ -439,66 +390,70 @@ void rules_to_deactivate_returned_by_command_line_parameter_is_inside_result(Str assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(arrayToTestExpectedLength.length, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); - verify(environmentVariableReader, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @ParameterizedTest @NullSource - void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_reader_is_called_as_fallback(String value) { + void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_reader_is_called_as_fallback( + String value) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getDeactivatedRuleReferences()).thenReturn(value); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ factoryToTest.create(settings); /* test */ - verify(environmentVariableReader, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(ENVIRONMENT_VAIRABLE_READER, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @Test void api_definition_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json"); + File sechubScanConfigFile = new File( + "src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(environmentVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)).thenReturn(extractedSourcesPath); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(environmentVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(1, result.getApiDefinitionFiles().size()); } @Test void client_certificate_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/client-certificate-auth.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(environmentVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)).thenReturn(extractedSourcesPath); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(environmentVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertNotNull(result.getClientCertificateFile()); } @Test void includes_and_excludes_from_sechub_json_are_inside_result() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/no-auth-include-exclude.json"); @@ -516,10 +471,11 @@ void includes_and_excludes_from_sechub_json_are_inside_result() { @Test void includes_and_excludes_empty_from_sechub_json_result_in_empty_exclude_and_target_url_as_single_include() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/no-auth-without-includes-or-excludes.json"); + File sechubScanConfigFile = new File( + "src/test/resources/sechub-config-examples/no-auth-without-includes-or-excludes.json"); when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); /* execute */ @@ -538,7 +494,7 @@ void connection_check_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isConnectionCheckEnabled()).thenReturn(enabled); - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -551,40 +507,43 @@ void connection_check_from_settings_is_in_result(boolean enabled) { @Test void header_config_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/header-config.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(environmentVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)).thenReturn(extractedSourcesPath); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(environmentVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(2, result.getHeaderValueFiles().size()); - assertEquals(extractedSourcesPath+"/header-token.txt", result.getHeaderValueFiles().get("Key").toString()); - assertEquals(extractedSourcesPath+"/token.txt", result.getHeaderValueFiles().get("Other").toString()); + assertEquals(extractedSourcesPath + "/header-token.txt", result.getHeaderValueFiles().get("Key").toString()); + assertEquals(extractedSourcesPath + "/token.txt", result.getHeaderValueFiles().get("Other").toString()); } @Test void header_config_without_data_section_no_file_is_inside_result() { /* prepare */ - when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/header-config-without-data-section.json"); + File sechubScanConfigFile = new File( + "src/test/resources/sechub-config-examples/header-config-without-data-section.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(environmentVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)).thenReturn(extractedSourcesPath); + when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(environmentVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(0, result.getHeaderValueFiles().size()); } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelperTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelperTest.java deleted file mode 100644 index e2d45ba707..0000000000 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/SecHubWebScanConfigurationHelperTest.java +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.helper; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.File; - -import org.junit.jupiter.api.Test; - -import com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; -import com.mercedesbenz.sechub.test.TestFileReader; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; - -class SecHubWebScanConfigurationHelperTest { - - private SecHubWebScanConfigurationHelper helperToTest = new SecHubWebScanConfigurationHelper(); - - @Test - void determines_AuthenticationType_from_empty_sechub_config_correctly() { - /* execute */ - AuthenticationType authTypeNewConfig = helperToTest.determineAuthenticationType(new SecHubWebScanConfiguration()); - - /* test */ - assertEquals(authTypeNewConfig, AuthenticationType.UNAUTHENTICATED); - } - - @Test - void determines_AuthenticationType_sechub_config_is_null() { - /* execute */ - AuthenticationType authTypeFromNull = helperToTest.determineAuthenticationType(null); - - /* test */ - assertEquals(authTypeFromNull, AuthenticationType.UNAUTHENTICATED); - } - - @Test - void determines_AuthenticationType_sechub_config_has_basic_auth() { - /* prepare */ - File file = new File("src/test/resources/sechub-config-examples/basic-auth.json"); - String sechubConfigJSON = TestFileReader.readTextFromFile(file); - SecHubScanConfiguration sechubConfig = SecHubScanConfiguration.createFromJSON(sechubConfigJSON); - SecHubWebScanConfiguration secHubWebScanConfiguration = sechubConfig.getWebScan().get(); - - /* execute */ - AuthenticationType authenticationType = helperToTest.determineAuthenticationType(secHubWebScanConfiguration); - - /* test */ - assertEquals(authenticationType, AuthenticationType.HTTP_BASIC_AUTHENTICATION); - } -} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java index 0002a37e9d..1b358e1212 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.helper; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.UUID; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -18,17 +15,11 @@ class ZapPDSEventHandlerTest { - private ZapPDSEventHandler zapPDSEventHandler; - - @BeforeEach - void beforeEach() { - zapPDSEventHandler = new ZapPDSEventHandler(""); - } - @Test void file_does_not_exist_and_so_no_scan_is_cancelled() throws IOException { /* prepare */ String scanContextName = UUID.randomUUID().toString(); + ZapPDSEventHandler zapPDSEventHandler = new ZapPDSEventHandler(""); /* execute + test */ assertFalse(zapPDSEventHandler.isScanCancelled()); @@ -36,9 +27,10 @@ void file_does_not_exist_and_so_no_scan_is_cancelled() throws IOException { } @Test - void file_does_exist_and_so_scan_is_cancelled(@TempDir File tempDir) throws IOException { + void file_does_exist_and_so_scan_is_cancelled(@TempDir Path tempDir) throws IOException { /* prepare */ - zapPDSEventHandler.cancelEventFile = tempDir; + Path tempFile = Files.createFile(tempDir.resolve("cancel_requested.json")); + ZapPDSEventHandler zapPDSEventHandler = new ZapPDSEventHandler(tempFile.getParent().toString()); String scanContextName = UUID.randomUUID().toString(); /* execute + test */ diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupportTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupportTest.java similarity index 99% rename from sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupportTest.java rename to sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupportTest.java index 1932852e73..78727a7751 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapWrapperDataSectionFileSupportTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapWrapperDataSectionFileSupportTest.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.config; +package com.mercedesbenz.sechub.zapwrapper.helper; import static org.junit.Assert.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; From f19d26b2204ae0122ee885ab6923ddd27d9bd6b7 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Fri, 15 Nov 2024 14:11:19 +0100 Subject: [PATCH 04/13] Implement script login via template handling with some dummy data #3611 - add parts for script execution with session management - add script authentication to ZapScanner - add necessary dependencies to gradle files - add configuration option via commandline parameter and ENV variable --- gradle/libraries.gradle | 8 + sechub-doc/build.gradle | 1 + sechub-wrapper-owasp-zap/build.gradle | 3 + .../zapwrapper/cli/CommandLineSettings.java | 10 + .../config/ZapScanContextFactory.java | 87 +-- .../config/auth/AuthenticationType.java | 2 + .../sechub/zapwrapper/scan/ZapScanner.java | 322 +++++---- .../scan/login/ZapScriptBindingKeys.java | 16 + .../zapwrapper/scan/login/ZapScriptLogin.java | 73 ++ .../login/ZapScriptLoginSessionGrabber.java | 154 ++++ .../login/ZapScriptLoginWebDriverFactory.java | 40 + .../login/ZapWrapperGroovyScriptExecutor.java | 84 +++ .../util/EnvironmentVariableConstants.java | 2 + .../config/ZapScanContextFactoryTest.java | 139 ++-- .../zapwrapper/scan/ZapScannerTest.java | 683 ++++++++++-------- .../ZapScriptLoginSessionGrabberTest.java | 119 +++ .../scan/login/ZapScriptLoginTest.java | 143 ++++ .../ZapWrapperGroovyScriptExecutorTest.java | 77 ++ .../invalid-script.groovy | 27 + .../login-script-examples/test-script.groovy | 27 + .../zap-ruleset-helper/requirements.txt | 0 .../zap-ruleset-helper/zap_ruleset_helper.py | 0 22 files changed, 1482 insertions(+), 535 deletions(-) create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptBindingKeys.java create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java create mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java create mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java create mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java create mode 100644 sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy create mode 100644 sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy rename sechub-wrapper-owasp-zap/{src/main/resources => }/zap-ruleset-helper/requirements.txt (100%) rename sechub-wrapper-owasp-zap/{src/main/resources => }/zap-ruleset-helper/zap_ruleset_helper.py (100%) diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index 9094378c20..fd82d78b5f 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -87,6 +87,9 @@ ext { /* Owasp Zap wrapper */ owaspzap_client_api: "1.14.0", jcommander: "1.82", + selenium_firefox_driver: "4.26.0", + selenium_support: "4.26.0", + groovy_jsr223: "4.0.24", thymeleaf_extras_springsecurity5: "3.1.2.RELEASE", @@ -195,6 +198,11 @@ ext { jcommander: "com.beust:jcommander:${libraryVersion.jcommander}", + selenium_firefox_driver: "org.seleniumhq.selenium:selenium-firefox-driver:${libraryVersion.selenium_firefox_driver}", + selenium_support: "org.seleniumhq.selenium:selenium-support:${libraryVersion.selenium_support}", + + groovy_jsr223: "org.apache.groovy:groovy-jsr223:${libraryVersion.groovy_jsr223}", + /* * Needed for Spring Boot WebFlux CSRF protection - see: https://stackoverflow.com/a/53305169 */ diff --git a/sechub-doc/build.gradle b/sechub-doc/build.gradle index b72cb03032..b75a3f3692 100644 --- a/sechub-doc/build.gradle +++ b/sechub-doc/build.gradle @@ -17,6 +17,7 @@ dependencies { 'sechub-pds-tools', /* only pds tooling + avoid cycles */ 'sechub-api-java', /* the api project needs sechub-doc tests (and compile) for open api json files. So we may not have this as relation! */ 'sechub-systemtest', /* avoid cyclic dependency, see AdoptedSystemTestDefaultFallbacks javadoc for more information */ + 'sechub-wrapper-owasp-zap', ] /* fetch all sub projects, except unwanted and all only used for testing */ diff --git a/sechub-wrapper-owasp-zap/build.gradle b/sechub-wrapper-owasp-zap/build.gradle index c3f6a80f6f..e7ae258f83 100644 --- a/sechub-wrapper-owasp-zap/build.gradle +++ b/sechub-wrapper-owasp-zap/build.gradle @@ -14,6 +14,9 @@ dependencies { implementation library.owaspzap_client_api implementation library.jcommander implementation library.commons_codec + implementation library.selenium_firefox_driver + implementation library.selenium_support + implementation library.groovy_jsr223 implementation spring_boot_dependency.slf4j_api implementation spring_boot_dependency.logback_classic diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java index 575fb7ff7b..6f387f4ad7 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java @@ -185,4 +185,14 @@ public String getPDSUserMessageFolder() { public String getPDSEventFolder() { return pdsEventFolder; } + + @Parameter(names = { + "--templateFolder" }, description = "Folder where the ZAP wrapper fetches the logins script from. This is not needed since the PDS provides the env variable: " + + EnvironmentVariableConstants.PDS_TEMPLATE_FOLDER + + ". This env variable is automatically used if this command line parameter is not set.", required = false) + private String templateFolder; + + public String getTemplateFolder() { + return templateFolder; + } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java index ca7e34d885..9a3932bf1e 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java @@ -33,9 +33,10 @@ public class ZapScanContextFactory { private static final int MINUTES_IN_MS = 60 * SECONDS_IN_MS; private static final int HOURS_IN_MS = 60 * MINUTES_IN_MS; private static final int DAYS_IN_MS = 24 * HOURS_IN_MS; - private static final int DEFAULT_MAX_SCAN_DURATION = 8 * HOURS_IN_MS; + private static final String GROOVY_LOGIN_SCRIPTFILE_NAME = "script.groovy"; + private final EnvironmentVariableReader environmentVariableReader; private final BaseTargetUriFactory targetUriFactory; private final RuleProvider ruleProvider; @@ -52,9 +53,8 @@ public ZapScanContextFactory() { includeExcludeToZapURLHelper = new IncludeExcludeToZapURLHelper(); } - ZapScanContextFactory(EnvironmentVariableReader environmentVariableReader, BaseTargetUriFactory targetUriFactory, - RuleProvider ruleProvider, ZapWrapperDataSectionFileSupport dataSectionFileSupport, - SecHubScanConfigProvider secHubScanConfigProvider, + ZapScanContextFactory(EnvironmentVariableReader environmentVariableReader, BaseTargetUriFactory targetUriFactory, RuleProvider ruleProvider, + ZapWrapperDataSectionFileSupport dataSectionFileSupport, SecHubScanConfigProvider secHubScanConfigProvider, IncludeExcludeToZapURLHelper includeExcludeToZapURLHelper) { this.environmentVariableReader = environmentVariableReader; this.targetUriFactory = targetUriFactory; @@ -66,16 +66,13 @@ public ZapScanContextFactory() { public ZapScanContext create(CommandLineSettings settings) { if (settings == null) { - throw new ZapWrapperRuntimeException("Command line settings must not be null!", - ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); + throw new ZapWrapperRuntimeException("Command line settings must not be null!", ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); } /* Zap rule setup */ ZapFullRuleset fullRuleset = ruleProvider.fetchFullRuleset(settings.getFullRulesetFile()); - DeactivatedRuleReferences deactivatedRuleReferences = createDeactivatedRuleReferencesFromSettingsOrEnv( - settings); + DeactivatedRuleReferences deactivatedRuleReferences = createDeactivatedRuleReferencesFromSettingsOrEnv(settings); - DeactivatedRuleReferences ruleReferencesFromFile = ruleProvider - .fetchDeactivatedRuleReferences(settings.getRulesDeactvationFile()); + DeactivatedRuleReferences ruleReferencesFromFile = ruleProvider.fetchDeactivatedRuleReferences(settings.getRulesDeactvationFile()); for (RuleReference reference : ruleReferencesFromFile.getDeactivatedRuleReferences()) { deactivatedRuleReferences.addRuleReference(reference); } @@ -87,8 +84,7 @@ public ZapScanContext create(CommandLineSettings settings) { /* SecHub settings */ URL targetUrl = targetUriFactory.create(settings.getTargetURL()); - SecHubScanConfiguration sechubScanConfig = secHubScanConfigProvider - .getSecHubWebConfiguration(settings.getSecHubConfigFile()); + SecHubScanConfiguration sechubScanConfig = secHubScanConfigProvider.getSecHubWebConfiguration(settings.getSecHubConfigFile()); SecHubWebScanConfiguration sechubWebConfig = getSecHubWebConfiguration(sechubScanConfig); long maxScanDurationInMillis = fetchMaxScanDurationInMillis(sechubWebConfig); @@ -136,7 +132,7 @@ public ZapScanContext create(CommandLineSettings settings) { .setRetryWaittimeInMilliseconds(settings.getRetryWaittimeInMilliseconds()) .setZapProductMessageHelper(productMessagehelper) .setZapPDSEventHandler(zapEventHandler) - .setGroovyScriptLoginFile(null) // TODO implement + .setGroovyScriptLoginFile(fetchGroovyScriptFile(settings)) .build(); /* @formatter:on */ return scanContext; @@ -149,10 +145,8 @@ private DeactivatedRuleReferences createDeactivatedRuleReferencesFromSettingsOrE // if no rules to deactivate were specified via the command line, // look for rules specified via the corresponding env variable if (deactivatedRuleRefsAsString == null) { - LOG.info("Reading rules to deactivate from env variable {} if set.", - EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); - deactivatedRuleRefsAsString = environmentVariableReader - .readAsString(EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); + LOG.info("Reading rules to deactivate from env variable {} if set.", EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); + deactivatedRuleRefsAsString = environmentVariableReader.readAsString(EnvironmentVariableConstants.ZAP_DEACTIVATED_RULE_REFERENCES); } // if no rules to deactivate were set at all, continue without @@ -186,24 +180,20 @@ private ZapServerConfiguration createZapServerConfig(CommandLineSettings setting zapPort = environmentVariableReader.readAsInt(EnvironmentVariableConstants.ZAP_PORT_ENV_VARIABLE_NAME); } if (zapApiKey == null) { - zapApiKey = environmentVariableReader - .readAsString(EnvironmentVariableConstants.ZAP_API_KEY_ENV_VARIABLE_NAME); + zapApiKey = environmentVariableReader.readAsString(EnvironmentVariableConstants.ZAP_API_KEY_ENV_VARIABLE_NAME); } if (zapHost == null) { - throw new ZapWrapperRuntimeException( - "Zap host is null. Please set the Zap host to the host use by the Zap.", + throw new ZapWrapperRuntimeException("Zap host is null. Please set the Zap host to the host use by the Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } if (zapPort <= 0) { - throw new ZapWrapperRuntimeException( - "Zap Port was set to " + zapPort + ". Please set the Zap port to the port used by the Zap.", + throw new ZapWrapperRuntimeException("Zap Port was set to " + zapPort + ". Please set the Zap port to the port used by the Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } if (zapApiKey == null) { - throw new ZapWrapperRuntimeException( - "Zap API-Key is null. Please set the Zap API-key to the same value set inside your Zap.", + throw new ZapWrapperRuntimeException("Zap API-Key is null. Please set the Zap API-key to the same value set inside your Zap.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapServerConfiguration(zapHost, zapPort, zapApiKey); @@ -214,8 +204,7 @@ private ProxyInformation createProxyInformation(CommandLineSettings settings) { int proxyPort = settings.getProxyPort(); if (proxyHost == null) { - proxyHost = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME); + proxyHost = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME); } if (proxyPort <= 0) { proxyPort = environmentVariableReader.readAsInt(EnvironmentVariableConstants.PROXY_PORT_ENV_VARIABLE_NAME); @@ -238,32 +227,28 @@ private SecHubWebScanConfiguration getSecHubWebConfiguration(SecHubScanConfigura private List fetchApiDefinitionFiles(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchApiDefinitionFiles(extractedSourcesFolderPath, sechubScanConfig); } private File fetchClientCertificateFile(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchClientCertificateFile(extractedSourcesFolderPath, sechubScanConfig); } private Map fetchHeaderValueFiles(SecHubScanConfiguration sechubScanConfig) { // use the extracted sources folder path, where all text files are uploaded and // extracted - String extractedSourcesFolderPath = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); + String extractedSourcesFolderPath = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EXTRACTED_SOURCES_FOLDER); return dataSectionFileSupport.fetchHeaderValueFiles(extractedSourcesFolderPath, sechubScanConfig); } private Set createUrlsIncludedInContext(URL targetUrl, SecHubWebScanConfiguration sechubWebConfig) { Set includeSet = new HashSet<>(); if (sechubWebConfig.getIncludes().isPresent()) { - includeSet.addAll( - includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getIncludes().get())); + includeSet.addAll(includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getIncludes().get())); } // if no includes are specified everything is included if (includeSet.isEmpty()) { @@ -277,8 +262,7 @@ private Set createUrlsIncludedInContext(URL targetUrl, SecHubWebScanConf private Set createUrlsExcludedFromContext(URL targetUrl, SecHubWebScanConfiguration sechubWebConfig) { Set excludeSet = new HashSet<>(); if (sechubWebConfig.getExcludes().isPresent()) { - excludeSet.addAll( - includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getExcludes().get())); + excludeSet.addAll(includeExcludeToZapURLHelper.createListOfUrls(targetUrl, sechubWebConfig.getExcludes().get())); } return excludeSet; } @@ -286,14 +270,11 @@ private Set createUrlsExcludedFromContext(URL targetUrl, SecHubWebScanCo private ZapProductMessageHelper createZapProductMessageHelper(CommandLineSettings settings) { String userMessagesFolder = settings.getPDSUserMessageFolder(); if (userMessagesFolder == null) { - userMessagesFolder = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER); + userMessagesFolder = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER); } if (userMessagesFolder == null) { - throw new ZapWrapperRuntimeException( - "PDS configuration invalid. Cannot send user messages, because environment variable " - + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER + " is not set.", - ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); + throw new ZapWrapperRuntimeException("PDS configuration invalid. Cannot send user messages, because environment variable " + + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER + " is not set.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapProductMessageHelper(userMessagesFolder); } @@ -301,15 +282,12 @@ private ZapProductMessageHelper createZapProductMessageHelper(CommandLineSetting private ZapPDSEventHandler createZapEventhandler(CommandLineSettings settings) { String pdsJobEventsFolder = settings.getPDSEventFolder(); if (pdsJobEventsFolder == null) { - pdsJobEventsFolder = environmentVariableReader - .readAsString(EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER); + pdsJobEventsFolder = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER); } if (pdsJobEventsFolder == null) { - throw new ZapWrapperRuntimeException( - "PDS configuration invalid. Cannot send check for job events, because environment variable " - + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER + " is not set.", - ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); + throw new ZapWrapperRuntimeException("PDS configuration invalid. Cannot send check for job events, because environment variable " + + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER + " is not set.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } return new ZapPDSEventHandler(pdsJobEventsFolder); } @@ -337,4 +315,15 @@ private long fetchMaxScanDurationInMillis(SecHubWebScanConfiguration sechubWebCo return DEFAULT_MAX_SCAN_DURATION; } } + + private File fetchGroovyScriptFile(CommandLineSettings settings) { + String templateDir = settings.getTemplateFolder(); + if (templateDir == null) { + templateDir = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_TEMPLATE_FOLDER); + } + if (templateDir == null) { + return null; + } + return new File(templateDir, GROOVY_LOGIN_SCRIPTFILE_NAME); + } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java index 1cede08ea5..2253dd6e23 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java @@ -18,6 +18,8 @@ public enum AuthenticationType { JSON_BASED_AUTHENTICATION("jsonBasedAuthentication"), + MANUAL_AUTHENTICATION("manualAuthentication"), + ; private String zapAuthenticationMethod; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java index 237a6a31d7..9f9515b8a2 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java @@ -18,18 +18,14 @@ import org.slf4j.LoggerFactory; import org.zaproxy.clientapi.core.ClientApiException; -import com.mercedesbenz.sechub.commons.TextFileReader; -import com.mercedesbenz.sechub.commons.model.ClientCertificateConfiguration; -import com.mercedesbenz.sechub.commons.model.HTTPHeaderConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubMessage; -import com.mercedesbenz.sechub.commons.model.SecHubMessageType; -import com.mercedesbenz.sechub.commons.model.SecHubWebScanApiConfiguration; +import com.mercedesbenz.sechub.commons.model.*; import com.mercedesbenz.sechub.commons.model.login.BasicLoginConfiguration; import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; import com.mercedesbenz.sechub.zapwrapper.config.ProxyInformation; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; +import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; import com.mercedesbenz.sechub.zapwrapper.config.auth.SessionManagementType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.Rule; @@ -37,55 +33,51 @@ import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiFacade; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLogin; +import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginSessionGrabber; +import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginWebDriverFactory; +import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapWrapperGroovyScriptExecutor; import com.mercedesbenz.sechub.zapwrapper.util.SystemUtil; import com.mercedesbenz.sechub.zapwrapper.util.UrlUtil; public class ZapScanner implements ZapScan { private static final Logger LOG = LoggerFactory.getLogger(ZapScanner.class); - static final int CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS = 5000; public static final String X_SECHUB_DAST_HEADER_NAME = "x-sechub-dast"; - ClientApiFacade clientApiFacade; - ZapScanContext scanContext; + private static final int CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS = 5000; + private static final int DEFAULT_MAX_DEPTH = 10; - ScanDurationHelper scanDurationHelper; - UrlUtil urlUtil; - SystemUtil systemUtil; + private final ClientApiSupport clientApiSupport; + private final ZapScanContext scanContext; - long remainingScanTime; + private final ZapScriptLogin scriptLogin; + private final ScanDurationHelper scanDurationHelper; + private final UrlUtil urlUtil; + private final SystemUtil systemUtil; - TextFileReader fileReader; - - public static ZapScanner from(ClientApiFacade clientApiFacade, ZapScanContext scanContext) { - if (clientApiFacade == null) { - throw new ZapWrapperRuntimeException("Cannot create Zap Scanner because ClientApiFacade is null!", ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); - } - - if (scanContext == null) { - throw new ZapWrapperRuntimeException("Cannot create Zap Scanner because ZapScanContext is null!", ZapWrapperExitCode.UNSUPPORTED_CONFIGURATION); - } + public ZapScanner(ClientApiSupport clientApiSupport, ZapScanContext scanContext) { + this.clientApiSupport = clientApiSupport; + this.scanContext = scanContext; - ScanDurationHelper scanDurationHelper = new ScanDurationHelper(); - UrlUtil urlUtil = new UrlUtil(); - SystemUtil systemUtil = new SystemUtil(); + this.scanDurationHelper = new ScanDurationHelper(); + this.urlUtil = new UrlUtil(); + this.systemUtil = new SystemUtil(); - return new ZapScanner(clientApiFacade, scanContext, scanDurationHelper, urlUtil, systemUtil); + this.scriptLogin = new ZapScriptLogin(new ZapScriptLoginWebDriverFactory(), new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionGrabber()); } - private ZapScanner(ClientApiFacade clientApiFacade, ZapScanContext scanContext, ScanDurationHelper scanDurationHelper, UrlUtil urlUtil, - SystemUtil systemUtil) { - this.clientApiFacade = clientApiFacade; + ZapScanner(ClientApiSupport clientApiSupport, ZapScanContext scanContext, ScanDurationHelper scanDurationHelper, UrlUtil urlUtil, SystemUtil systemUtil, + ZapScriptLogin scriptLogin) { + this.clientApiSupport = clientApiSupport; this.scanContext = scanContext; this.scanDurationHelper = scanDurationHelper; this.urlUtil = urlUtil; this.systemUtil = systemUtil; - this.remainingScanTime = scanContext.getMaxScanDurationInMilliSeconds(); - - this.fileReader = new TextFileReader(); + this.scriptLogin = scriptLogin; } @Override @@ -123,24 +115,28 @@ public void scan() throws ZapWrapperRuntimeException { void setupStandardConfiguration() throws ClientApiException { LOG.info("Creating new session inside the Zap"); // to ensure parts from previous scan are deleted - clientApiFacade.createNewSession(scanContext.getContextName(), "true"); + clientApiSupport.createNewSession(scanContext.getContextName(), "true"); LOG.info("Setting default maximum number of alerts for each rule."); // setting this value to zero means unlimited - clientApiFacade.configureMaximumAlertsForEachRule("0"); + clientApiSupport.configureMaximumAlertsForEachRule("0"); LOG.info("Enable all passive scan rules before configuration begins."); // enable all passive scanner rules by default - clientApiFacade.enableAllPassiveScannerRules(); + clientApiSupport.enableAllPassiveScannerRules(); LOG.info("Enable all active scan rules before configuration begins."); // enable all passive scanner rules by default // null specifies the default scan policy - clientApiFacade.enableAllActiveScannerRulesForPolicy(null); + clientApiSupport.enableAllActiveScannerRulesForPolicy(null); LOG.info("Set browser for ajaxSpider."); // use firefox in headless mode by default - clientApiFacade.configureAjaxSpiderBrowserId(scanContext.getAjaxSpiderBrowserId()); + clientApiSupport.setAjaxSpiderBrowserId(scanContext.getAjaxSpiderBrowserId()); + + LOG.info("Set max directory depth of spider and ajaxSpider to: {}", DEFAULT_MAX_DEPTH); + clientApiSupport.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); + clientApiSupport.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); } void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deactivatedRuleReferences) throws ClientApiException { @@ -156,11 +152,11 @@ void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deact Rule ruleToDeactivate = fullRuleset.findRuleByReference(ruleRef.getReference()); if (isPassiveRule(ruleToDeactivate.getType())) { LOG.info("Deactivate passive scanner rule: {} ", ruleRef.getReference()); - clientApiFacade.disablePassiveScannerRule(ruleToDeactivate.getId()); + clientApiSupport.disablePassiveScannerRule(ruleToDeactivate.getId()); } else if (isActiveRule(ruleToDeactivate.getType())) { LOG.info("Deactivate active scanner rule: {} ", ruleRef.getReference()); // null specifies the default scan policy - clientApiFacade.disableActiveScannerRuleForPolicy(ruleToDeactivate.getId(), null); + clientApiSupport.disableActiveScannerRuleForPolicy(ruleToDeactivate.getId(), null); } } } @@ -170,12 +166,12 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws String proxyHost = proxyInformation.getHost(); int proxyPort = proxyInformation.getPort(); LOG.info("Using proxy {}:{} to reach target.", proxyHost, proxyPort); - clientApiFacade.configureHttpProxy(proxyHost, "" + proxyPort, null, null, null); - clientApiFacade.setHttpProxyEnabled("true"); - clientApiFacade.setHttpProxyAuthEnabled("false"); + clientApiSupport.configureHttpProxy(proxyHost, "" + proxyPort, null, null, null); + clientApiSupport.setHttpProxyEnabled("true"); + clientApiSupport.setHttpProxyAuthEnabled("false"); } else { LOG.info("No proxy was set, continuing without proxy."); - clientApiFacade.setHttpProxyEnabled("false"); + clientApiSupport.setHttpProxyEnabled("false"); } } @@ -187,7 +183,7 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws */ String createContext() throws ClientApiException { LOG.info("Creating context: {}", scanContext.getContextName()); - return clientApiFacade.createNewContext(scanContext.getContextName()); + return clientApiSupport.createNewContext(scanContext.getContextName()); } void addReplacerRulesForHeaders() throws ClientApiException { @@ -228,13 +224,13 @@ void addReplacerRulesForHeaders() throws ClientApiException { if (httpHeader.getOnlyForUrls().isEmpty()) { // if there are no onlyForUrl patterns, there is only one rule for each header description = httpHeader.getName(); - clientApiFacade.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } else { for (String onlyForUrl : httpHeader.getOnlyForUrls().get()) { // we need to create a rule for each onlyForUrl pattern on each header description = onlyForUrl; url = urlUtil.replaceWebScanWildCardsWithRegexInString(onlyForUrl); - clientApiFacade.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } } } @@ -249,19 +245,19 @@ void addIncludedAndExcludedUrlsToContext() throws ClientApiException { LOG.info("For scan {}: Adding include parts.", scanContext.getContextName()); String followRedirects = "false"; for (String url : scanContext.getZapURLsIncludeSet()) { - clientApiFacade.addIncludeUrlPatternToContext(scanContext.getContextName(), url); + clientApiSupport.addIncludeUrlPatternToContext(scanContext.getContextName(), url); // Cannot not perform initial connection check to included URL with wildcards if (url.contains(".*")) { LOG.info("For scan {}: Cannot not perform initial connection check to included URL: {} because it contains wildcards.", scanContext.getContextName(), url); } else { - clientApiFacade.accessUrlViaZap(url, followRedirects); + clientApiSupport.accessUrlViaZap(url, followRedirects); } } LOG.info("For scan {}: Adding exclude parts.", scanContext.getContextName()); for (String url : scanContext.getZapURLsExcludeSet()) { - clientApiFacade.addExcludeUrlPatternToContext(scanContext.getContextName(), url); + clientApiSupport.addExcludeUrlPatternToContext(scanContext.getContextName(), url); } } @@ -279,11 +275,11 @@ void loadApiDefinitions(String zapContextId) throws ClientApiException { URL apiDefinitionUrl = secHubWebScanApiConfiguration.getApiDefinitionUrl(); if (apiDefinitionUrl != null) { LOG.info("For scan {}: Loading openAPI definition from : {}", scanContext.getContextName(), apiDefinitionUrl.toString()); - clientApiFacade.importOpenApiDefintionFromUrl(apiDefinitionUrl, scanContext.getTargetUrlAsString(), zapContextId); + clientApiSupport.importOpenApiDefintionFromUrl(apiDefinitionUrl, scanContext.getTargetUrlAsString(), zapContextId); } for (File apiFile : scanContext.getApiDefinitionFiles()) { LOG.info("For scan {}: Loading openAPI file: {}", scanContext.getContextName(), apiFile.toString()); - clientApiFacade.importOpenApiFile(apiFile.toString(), scanContext.getTargetUrlAsString(), zapContextId); + clientApiSupport.importOpenApiFile(apiFile.toString(), scanContext.getTargetUrlAsString(), zapContextId); } break; default: @@ -320,29 +316,30 @@ void importClientCertificate() throws ClientApiException { password = new String(clientCertificateConfig.getPassword()); } LOG.info("For scan {}: Loading client certificate file: {}", scanContext.getContextName(), clientCertificateFile.getAbsolutePath()); - clientApiFacade.importPkcs12ClientCertificate(clientCertificateFile.getAbsolutePath(), password); - clientApiFacade.enableClientCertificate(); + clientApiSupport.importPkcs12ClientCertificate(clientCertificateFile.getAbsolutePath(), password); + clientApiSupport.enableClientCertificate(); } void executeScan(String zapContextId) throws ClientApiException { - UserInformation userInfo = configureLoginInsideZapContext(zapContextId); + UserInformation userInfo = setupLoginInsideZapContext(zapContextId); + long remainingScanDurationInMillis = scanContext.getMaxScanDurationInMilliSeconds(); if (userInfo != null) { - runSpiderAsUser(zapContextId, userInfo.zapuserId); - passiveScan(); + remainingScanDurationInMillis = runSpiderAsUser(zapContextId, userInfo.zapuserId, remainingScanDurationInMillis); + remainingScanDurationInMillis = passiveScan(remainingScanDurationInMillis); if (scanContext.isAjaxSpiderEnabled()) { - runAjaxSpiderAsUser(userInfo.userName); + remainingScanDurationInMillis = runAjaxSpiderAsUser(userInfo.userName, remainingScanDurationInMillis); } if (scanContext.isActiveScanEnabled()) { - runActiveScanAsUser(zapContextId, userInfo.zapuserId); + runActiveScanAsUser(zapContextId, userInfo.zapuserId, remainingScanDurationInMillis); } } else { - runSpider(); - passiveScan(); + remainingScanDurationInMillis = runSpider(remainingScanDurationInMillis); + remainingScanDurationInMillis = passiveScan(remainingScanDurationInMillis); if (scanContext.isAjaxSpiderEnabled()) { - runAjaxSpider(); + remainingScanDurationInMillis = runAjaxSpider(remainingScanDurationInMillis); } if (scanContext.isActiveScanEnabled()) { - runActiveScan(); + runActiveScan(remainingScanDurationInMillis); } } } @@ -355,7 +352,7 @@ void executeScan(String zapContextId) throws ClientApiException { * null if nothing could be configured. * @throws ClientApiException */ - UserInformation configureLoginInsideZapContext(String zapContextId) throws ClientApiException { + UserInformation setupLoginInsideZapContext(String zapContextId) throws ClientApiException { if (scanContext.getSecHubWebScanConfiguration().getLogin().isEmpty()) { LOG.info("For scan {}: No login section detected.", scanContext.getContextName()); return null; @@ -367,6 +364,24 @@ UserInformation configureLoginInsideZapContext(String zapContextId) throws Clien return initBasicAuthentication(zapContextId, webLoginConfiguration.getBasic().get()); } + if (isScriptLoginWanted()) { + LOG.info("For scan {}: Setting up authentcation and session management method for script authentication.", scanContext.getContextName()); + setupAuthenticationAndSessionManagementMethodForScriptLogin(zapContextId); + + LOG.info("For scan {}: Performing script authentication.", scanContext.getContextName()); + String zapAuthSessionName = scriptLogin.login(scanContext, clientApiSupport); + + // TODO read the username from templateData as soon as it is implemented + String username = "DUMMY"; + /* @formatter:off */ + LOG.info("For scan {}: Setup scan user in ZAP to use authenticated session.", scanContext.getContextName()); + StringBuilder authCredentialsConfigParams = new StringBuilder(); + authCredentialsConfigParams.append("username=").append(urlEncodeUTF8(username)) + .append("&sessionName=").append(urlEncodeUTF8(zapAuthSessionName)); + /* @formatter:on */ + UserInformation userInfo = setupScanUserForZapContext(zapContextId, username, authCredentialsConfigParams.toString()); + return userInfo; + } return null; } @@ -395,7 +410,7 @@ void generateZapReport() throws ClientApiException { String display = null; /* @formatter:off */ // we use the context name as report title - clientApiFacade.generateReport( + clientApiSupport.generateReport( title, template, theme, @@ -423,7 +438,7 @@ void cleanUp() { // to ensure parts from previous scan are deleted try { LOG.info("Cleaning up by starting new and empty session...", scanContext.getContextName()); - clientApiFacade.createNewSession("Cleaned after scan", "true"); + clientApiSupport.createNewSession("Cleaned after scan", "true"); LOG.info("New and empty session inside Zap created."); // Replacer rules are persistent even after restarting ZAP @@ -433,12 +448,15 @@ void cleanUp() { // Remove x-sechub-dast header replacer rule LOG.info("Remove '{}' replacer rule.", X_SECHUB_DAST_HEADER_NAME); - clientApiFacade.removeReplacerRule(X_SECHUB_DAST_HEADER_NAME); + clientApiSupport.removeReplacerRule(X_SECHUB_DAST_HEADER_NAME); // disable client certificate here, the imported client certificate will be // removed on ZAP shutdown automatically anyway LOG.info("Disable client certificate if one was used for the scan."); - clientApiFacade.disableClientCertificate(); + clientApiSupport.disableClientCertificate(); + + LOG.info("Cleaning up script login data."); + scriptLogin.cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); LOG.info("Cleanup successful."); } catch (ClientApiException e) { @@ -446,7 +464,7 @@ void cleanUp() { } } - void runSpider() throws ClientApiException { + long runSpider(long remainingScanDurationInMillis) throws ClientApiException { String contextName = scanContext.getContextName(); String subTreeOnly = "true"; String recurse = "true"; @@ -455,36 +473,36 @@ void runSpider() throws ClientApiException { LOG.info("For scan {}: Starting Spider.", contextName); /* @formatter:off */ String scanId = - clientApiFacade.startSpiderScan( + clientApiSupport.startSpiderScan( targetUrlAsString, maxChildren, recurse, contextName, subTreeOnly); /* @formatter:on */ - waitForSpiderResults(scanId); + return waitForSpiderResults(scanId, remainingScanDurationInMillis); } - void runAjaxSpider() throws ClientApiException { + long runAjaxSpider(long remainingScanDurationInMillis) throws ClientApiException { String inScope = "true"; String subTreeOnly = "true"; String contextName = scanContext.getContextName(); String targetUrlAsString = scanContext.getTargetUrlAsString(); LOG.info("For scan {}: Starting AjaxSpider.", scanContext.getContextName()); /* @formatter:off */ - clientApiFacade.startAjaxSpiderScan( + clientApiSupport.startAjaxSpiderScan( targetUrlAsString, inScope, contextName, subTreeOnly); /* @formatter:on */ - waitForAjaxSpiderResults(); + return waitForAjaxSpiderResults(remainingScanDurationInMillis); } - void runActiveScan() throws ClientApiException { + void runActiveScan(long remainingScanDurationInMillis) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before - if (!clientApiFacade.atLeastOneURLDetected()) { + if (!clientApiSupport.atLeastOneURLDetected()) { LOG.warn("For {} skipping active scan, since no URLs where detected by spider or ajaxSpider!", scanContext.getContextName()); scanContext.getZapProductMessageHelper().writeSingleProductMessage( new SecHubMessage(SecHubMessageType.WARNING, "Skipped the active scan, because no URLs were detected by the crawler! " @@ -500,7 +518,7 @@ void runActiveScan() throws ClientApiException { LOG.info("For scan {}: Starting ActiveScan.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiFacade.startActiveScan( + clientApiSupport.startActiveScan( targetUrlAsString, recurse, inScopeOnly, @@ -508,10 +526,10 @@ void runActiveScan() throws ClientApiException { method, postData); /* @formatter:on */ - waitForActiveScanResults(scanId); + waitForActiveScanResults(scanId, remainingScanDurationInMillis); } - void runSpiderAsUser(String contextId, String userId) throws ClientApiException { + long runSpiderAsUser(String contextId, String userId, long remainingScanDurationInMillis) throws ClientApiException { String url = scanContext.getTargetUrlAsString(); String maxchildren = null; String recurse = "true"; @@ -519,7 +537,7 @@ void runSpiderAsUser(String contextId, String userId) throws ClientApiException LOG.info("For scan {}: Starting authenticated Spider.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiFacade.startSpiderScanAsUser( + clientApiSupport.startSpiderScanAsUser( contextId, userId, url, @@ -527,28 +545,28 @@ void runSpiderAsUser(String contextId, String userId) throws ClientApiException recurse, subtreeonly); /* @formatter:on */ - waitForSpiderResults(scanId); + return waitForSpiderResults(scanId, remainingScanDurationInMillis); } - void runAjaxSpiderAsUser(String username) throws ClientApiException { + long runAjaxSpiderAsUser(String username, long remainingScanDurationInMillis) throws ClientApiException { String contextname = scanContext.getContextName(); String url = scanContext.getTargetUrlAsString(); String subtreeonly = "true"; LOG.info("For scan {}: Starting authenticated Ajax Spider.", scanContext.getContextName()); /* @formatter:off */ - clientApiFacade.startAjaxSpiderScanAsUser( + clientApiSupport.startAjaxSpiderScanAsUser( contextname, username, url, subtreeonly); /* @formatter:on */ - waitForAjaxSpiderResults(); + return waitForAjaxSpiderResults(remainingScanDurationInMillis); } - void runActiveScanAsUser(String contextId, String userId) throws ClientApiException { + void runActiveScanAsUser(String contextId, String userId, long remainingScanDurationInMillis) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before - if (!clientApiFacade.atLeastOneURLDetected()) { + if (!clientApiSupport.atLeastOneURLDetected()) { LOG.warn("For {} skipping active scan, since no URLs where detected by spider or ajaxSpider!", scanContext.getContextName()); scanContext.getZapProductMessageHelper().writeSingleProductMessage( new SecHubMessage(SecHubMessageType.WARNING, "Skipped the active scan, because no URLs were detected by the crawler! " @@ -563,7 +581,7 @@ void runActiveScanAsUser(String contextId, String userId) throws ClientApiExcept LOG.info("For scan {}: Starting authenticated ActiveScan.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiFacade.startActiveScanAsUser( + clientApiSupport.startActiveScanAsUser( url, contextId, userId, @@ -572,20 +590,22 @@ void runActiveScanAsUser(String contextId, String userId) throws ClientApiExcept method, postdata); /* @formatter:on */ - waitForActiveScanResults(scanId); + waitForActiveScanResults(scanId, remainingScanDurationInMillis); } /** * Wait for the results of the ajax spider. Periodically checks the progress of * the ajax spider. * + * @param remainingScanDurationInMillis + * @return * @throws ClientApiException */ - void waitForAjaxSpiderResults() throws ClientApiException { + long waitForAjaxSpiderResults(long remainingScanDurationInMillis) throws ClientApiException { String ajaxSpiderStatus = null; long startTime = systemUtil.getCurrentTimeInMilliseconds(); - long maxDuration = scanDurationHelper.computeAjaxSpiderMaxScanDuration(scanContext.isActiveScanEnabled(), remainingScanTime); + long maxDuration = scanDurationHelper.computeAjaxSpiderMaxScanDuration(scanContext.isActiveScanEnabled(), remainingScanDurationInMillis); boolean timeOut = false; @@ -593,70 +613,74 @@ void waitForAjaxSpiderResults() throws ClientApiException { while (!isAjaxSpiderStopped(ajaxSpiderStatus) && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiFacade.stopAjaxSpider(); + clientApiSupport.stopAjaxSpider(); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - ajaxSpiderStatus = clientApiFacade.getAjaxSpiderStatus(); + ajaxSpiderStatus = clientApiSupport.getAjaxSpiderStatus(); LOG.info("For scan {}: AjaxSpider status {}", scanContext.getContextName(), ajaxSpiderStatus); timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > maxDuration; } /* stop spider - otherwise running in background */ - clientApiFacade.stopAjaxSpider(); + clientApiSupport.stopAjaxSpider(); LOG.info("For scan {}: AjaxSpider completed.", scanContext.getContextName()); - remainingScanTime = remainingScanTime - (systemUtil.getCurrentTimeInMilliseconds() - startTime); + return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** * Wait for the results of the spider. Periodically checks the progress of the * spider. * - * @param response + * @param scanId + * @param remainingScanDurationInMillis + * @return * @throws ClientApiException */ - void waitForSpiderResults(String scanId) throws ClientApiException { + long waitForSpiderResults(String scanId, long remainingScanDurationInMillis) throws ClientApiException { int progressSpider = 0; long startTime = systemUtil.getCurrentTimeInMilliseconds(); long maxDuration = scanDurationHelper.computeSpiderMaxScanDuration(scanContext.isActiveScanEnabled(), scanContext.isAjaxSpiderEnabled(), - remainingScanTime); + remainingScanDurationInMillis); boolean timeOut = false; ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); while (progressSpider < 100 && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiFacade.stopSpiderScan(scanId); + clientApiSupport.stopSpiderScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - progressSpider = clientApiFacade.getSpiderStatusForScan(scanId); + progressSpider = clientApiSupport.getSpiderStatusForScan(scanId); LOG.info("For scan {}: Spider progress {}%", scanContext.getContextName(), progressSpider); timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } /* stop spider - otherwise running in background */ - clientApiFacade.stopSpiderScan(scanId); + clientApiSupport.stopSpiderScan(scanId); - long numberOfSpiderResults = clientApiFacade.logFullSpiderResults(scanId); + long numberOfSpiderResults = clientApiSupport.logFullSpiderResults(scanId); scanContext.getZapProductMessageHelper() .writeSingleProductMessage(new SecHubMessage(SecHubMessageType.INFO, "Scanned %s URLs during the scan.".formatted(numberOfSpiderResults))); LOG.info("For scan {}: Spider completed.", scanContext.getContextName()); - remainingScanTime = remainingScanTime - (systemUtil.getCurrentTimeInMilliseconds() - startTime); + return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** * Wait for the results of the passive scan. Periodically checks the progress of * the passive scan. * + * @param remainingScanDurationInMillis + * @return * @throws ClientApiException */ - void passiveScan() throws ClientApiException { + long passiveScan(long remainingScanDurationInMillis) throws ClientApiException { LOG.info("For scan {}: Starting passive scan.", scanContext.getContextName()); long startTime = systemUtil.getCurrentTimeInMilliseconds(); long maxDuration = scanDurationHelper.computePassiveScanMaxScanDuration(scanContext.isActiveScanEnabled(), scanContext.isAjaxSpiderEnabled(), - remainingScanTime); + remainingScanDurationInMillis); - int numberOfRecords = clientApiFacade.getNumberOfPassiveScannerRecordsToScan(); + int numberOfRecords = clientApiSupport.getNumberOfPassiveScannerRecordsToScan(); boolean timeOut = false; ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); @@ -665,42 +689,42 @@ void passiveScan() throws ClientApiException { zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - numberOfRecords = clientApiFacade.getNumberOfPassiveScannerRecordsToScan(); + numberOfRecords = clientApiSupport.getNumberOfPassiveScannerRecordsToScan(); LOG.info("For scan {}: Passive scan number of records left for scanning: {}", scanContext.getContextName(), numberOfRecords); timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } LOG.info("For scan {}: Passive scan completed.", scanContext.getContextName()); - remainingScanTime = remainingScanTime - (systemUtil.getCurrentTimeInMilliseconds() - startTime); + return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** * Wait for the results of the active scan. Periodically checks the progress of * the active scan. * - * @param response + * @param scanId + * @param remainingScanDurationInMillis * @throws ClientApiException */ - void waitForActiveScanResults(String scanId) throws ClientApiException { + void waitForActiveScanResults(String scanId, long remainingScanDurationInMillis) throws ClientApiException { int progressActive = 0; long startTime = systemUtil.getCurrentTimeInMilliseconds(); - long maxDuration = remainingScanTime; boolean timeOut = false; ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); while (progressActive < 100 && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiFacade.stopActiveScan(scanId); + clientApiSupport.stopActiveScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - progressActive = clientApiFacade.getActiveScannerStatusForScan(scanId); + progressActive = clientApiSupport.getActiveScannerStatusForScan(scanId); LOG.info("For scan {}: Active scan progress {}%", scanContext.getContextName(), progressActive); - timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > maxDuration; + timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > remainingScanDurationInMillis; } - clientApiFacade.stopActiveScan(scanId); + clientApiSupport.stopActiveScan(scanId); LOG.info("For scan {}: Active scan completed.", scanContext.getContextName()); } @@ -725,43 +749,58 @@ private UserInformation initBasicAuthentication(String zapContextId, BasicLoginC .append("&port=").append(urlEncodeUTF8(port)); /* @formatter:on */ LOG.info("For scan {}: Setting basic authentication.", scanContext.getContextName()); - String authMethodName = scanContext.getAuthenticationType().getZapAuthenticationMethod(); - clientApiFacade.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); + String authMethodName = AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); + clientApiSupport.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); String methodName = SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); // methodconfigparams in case of http basic auth is null, because it is // configured automatically String methodconfigparams = null; - clientApiFacade.setSessionManagementMethod(zapContextId, methodName, methodconfigparams); - - return initBasicAuthScanUser(zapContextId, basicLoginConfiguration); - } + clientApiSupport.setSessionManagementMethod(zapContextId, methodName, methodconfigparams); - private UserInformation initBasicAuthScanUser(String zapContextId, BasicLoginConfiguration basicLoginConfiguration) throws ClientApiException { + /* @formatter:off */ String username = new String(basicLoginConfiguration.getUser()); String password = new String(basicLoginConfiguration.getPassword()); + StringBuilder authCredentialsConfigParams = new StringBuilder(); + authCredentialsConfigParams.append("username=").append(urlEncodeUTF8(username)) + .append("&password=").append(urlEncodeUTF8(password)); + /* @formatter:on */ - String userId = clientApiFacade.createNewUser(zapContextId, username); + return setupScanUserForZapContext(zapContextId, username, authCredentialsConfigParams.toString()); + } - /* @formatter:off */ - StringBuilder authCredentialsConfigParams = new StringBuilder(); - authCredentialsConfigParams.append("username=").append(urlEncodeUTF8(username)) - .append("&password=").append(urlEncodeUTF8(password)); - /* @formatter:on */ + private UserInformation setupScanUserForZapContext(String zapContextId, String username, String authCredentialsConfigParams) throws ClientApiException { + String userId = clientApiSupport.createNewUser(zapContextId, username); LOG.info("For scan {}: Setting up user.", scanContext.getContextName()); - clientApiFacade.configureAuthenticationCredentials(zapContextId, userId, authCredentialsConfigParams.toString()); + clientApiSupport.configureAuthenticationCredentials(zapContextId, userId, authCredentialsConfigParams.toString()); String enabled = "true"; - clientApiFacade.setUserEnabled(zapContextId, userId, enabled); + clientApiSupport.setUserEnabled(zapContextId, userId, enabled); - clientApiFacade.setForcedUser(zapContextId, userId); - clientApiFacade.setForcedUserModeEnabled(true); + clientApiSupport.setForcedUser(zapContextId, userId); + clientApiSupport.setForcedUserModeEnabled(true); UserInformation userInfo = new UserInformation(username, userId); return userInfo; } + private void setupAuthenticationAndSessionManagementMethodForScriptLogin(String zapContextId) throws ClientApiException { + // authenticationMethodConfigparams in case of manual authentication is null, + // because it is + // configured automatically + String authMethodConfigParams = null; + String authMethodName = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + clientApiSupport.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams); + + // sessionMethodConfigparams in case of cookie based session management is null, + // because it is + // configured automatically + String sessionMethodconfigparams = null; + String sessionMethodName = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + clientApiSupport.setSessionManagementMethod(zapContextId, sessionMethodName, sessionMethodconfigparams); + } + private boolean isAjaxSpiderStopped(String status) { return "stopped".equals(status); } @@ -815,11 +854,11 @@ private void cleanUpReplacerRules() throws ClientApiException { for (HTTPHeaderConfiguration httpHeader : httpHeaders) { if (httpHeader.getOnlyForUrls().isEmpty()) { String description = httpHeader.getName(); - clientApiFacade.removeReplacerRule(description); + clientApiSupport.removeReplacerRule(description); } else { for (String onlyForUrl : httpHeader.getOnlyForUrls().get()) { String description = onlyForUrl; - clientApiFacade.removeReplacerRule(description); + clientApiSupport.removeReplacerRule(description); } } } @@ -830,7 +869,7 @@ private String readHeaderValueFromFile(HTTPHeaderConfiguration httpHeader) { headerFile = scanContext.getHeaderValueFiles().getOrDefault(httpHeader.getName(), null); try { if (headerFile != null) { - return fileReader.readTextFromFile(headerFile.getAbsoluteFile()); + return Files.readString(headerFile.getAbsoluteFile().toPath()); } } catch (IOException e) { SecHubMessage message = new SecHubMessage(SecHubMessageType.ERROR, "Could not read header value from file: " + headerFile); @@ -870,7 +909,18 @@ private void addXSecHubDASTHeader() throws ClientApiException { String url = null; LOG.info("Add '{}' replacer rule.", X_SECHUB_DAST_HEADER_NAME); - clientApiFacade.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + } + + private boolean isScriptLoginWanted() { + if (scanContext.getGroovyScriptLoginFile() == null) { + return false; + } + if (!scanContext.getGroovyScriptLoginFile().isFile()) { + return false; + } + // TODO check if templateData are configured inside SecHub config + return true; } record UserInformation(String userName, String zapuserId) { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptBindingKeys.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptBindingKeys.java new file mode 100644 index 0000000000..2459107d56 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptBindingKeys.java @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +public class ZapScriptBindingKeys { + public static final String FIREFOX_WEBDRIVER_KEY = "WEBDRIVER"; + public static final String FIREFOX_WEBDRIVER_WAIT_KEY = "WEBDRIVER_WAIT_KEY"; + public static final String JAVASCRIPTEXECUTOR_KEY = "JAVASCRIPTEXECUTOR"; + public static final String SECHUB_WEBSCAN_CONFIG_KEY = "SECHUB_WEBSCAN_CONFIG"; + public static final String TOTP_GENERATOR_KEY = "TOTP_GENERATOR"; + + public static final String USER_KEY = "USER"; + public static final String PASSWORD_KEY = "PASSWORD"; + public static final String LOGIN_URL_KEY = "LOGIN_URL"; + public static final String TARGET_URL_KEY = "TARGET_URL"; + +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java new file mode 100644 index 0000000000..06dee0f040 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import java.io.File; +import java.io.IOException; + +import javax.script.ScriptException; + +import org.openqa.selenium.firefox.FirefoxDriver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zaproxy.clientapi.core.ClientApiException; + +import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; +import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; +import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; + +public class ZapScriptLogin { + private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLogin.class); + + private ZapScriptLoginWebDriverFactory webDriverFactory; + private ZapWrapperGroovyScriptExecutor groovyScriptExecutor; + private ZapScriptLoginSessionGrabber sessionGrabber; + + public ZapScriptLogin(ZapScriptLoginWebDriverFactory webDriverFactory, ZapWrapperGroovyScriptExecutor groovyScriptExecutor, + ZapScriptLoginSessionGrabber sessionGrabber) { + this.webDriverFactory = webDriverFactory; + this.groovyScriptExecutor = groovyScriptExecutor; + this.sessionGrabber = sessionGrabber; + } + + /** + * Performs the login by calling the script execution. Afterwards the + * sessionGrabber will add all necessary session data to ZAP. + * + * @param scanContext + * @param clientApiSupport + * @return the name/identifier of the authenticated session inside ZAP + */ + public String login(ZapScanContext scanContext, ClientApiSupport clientApiSupport) { + File groovyScriptLoginFile = scanContext.getGroovyScriptLoginFile(); + if (groovyScriptLoginFile == null || !groovyScriptLoginFile.isFile()) { + throw new ZapWrapperRuntimeException( + "Expected a groovy script file to perform login, but no script was found. Cannot perform script login without the script file.", + ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); + } + LOG.info("Creating selenium web driver."); + FirefoxDriver firefox = webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true); + + try { + LOG.info("Calling groovy script executor to execute login script."); + groovyScriptExecutor.executeScript(groovyScriptLoginFile, firefox, scanContext); + + LOG.info("Calling session grabber to read the HTTP session data and pass them to ZAP."); + return sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + } catch (IOException e) { + throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.IO_ERROR); + } catch (ScriptException e) { + throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); + } catch (ClientApiException e) { + throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); + } finally { + firefox.quit(); + } + } + + public void cleanUpScriptLoginData(String targetUrl, ClientApiSupport clientApiSupport) { + sessionGrabber.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiSupport); + + } + +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java new file mode 100644 index 0000000000..70414fd669 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import java.util.Map; +import java.util.regex.Pattern; + +import org.openqa.selenium.Cookie; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.zaproxy.clientapi.core.ClientApiException; + +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; + +public class ZapScriptLoginSessionGrabber { + private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLoginSessionGrabber.class); + + private static final String JWT_REPLACER_DESCRIPTION = "JWT"; + private static final String SESSION_TOKEN_IDENTIFIER = "session-token"; + private static final String SESSION_IDENTIFIER = "authenticated-session"; + + private static final String LOCAL_STORAGE = "localStorage"; + private static final String SESSION_STORAGE = "sessionStorage"; + + private static final Pattern JWT_PATTERN = Pattern.compile("^[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_.+/=]*$"); + + /** + * The sessionGrabber will add all necessary session data to ZAP. + * + * @param firefox + * @param targetUrl + * @param clientApiSupport + * @return the name/identifier of the authenticated session inside ZAP + * @throws ClientApiException + */ + public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl, ClientApiSupport clientApiSupport) throws ClientApiException { + LOG.info("Removing old session data inside ZAP if necessary."); + cleanUpOldSessionDataIfNecessary(targetUrl, clientApiSupport); + + LOG.info("Add new HTTP session token: {} to ZAP.", SESSION_TOKEN_IDENTIFIER); + clientApiSupport.addHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); + LOG.info("Create new empty HTTP session: {} in ZAP.", SESSION_IDENTIFIER); + clientApiSupport.createEmptyHTTPSession(targetUrl, SESSION_IDENTIFIER); + + LOG.info("Adding all cookies to ZAP HTTP session: {}", SESSION_IDENTIFIER); + for (Cookie cookie : firefox.manage().getCookies()) { + clientApiSupport.setHTTPSessionTokenValue(targetUrl, SESSION_IDENTIFIER, cookie.getName(), cookie.getValue()); + } + LOG.info("Set ZAP HTTP session: {} as active session to use.", SESSION_IDENTIFIER); + clientApiSupport.setActiveHTTPSession(targetUrl, SESSION_IDENTIFIER); + + addJwtAsReplacerRuleToZap(firefox, clientApiSupport); + + String followRedirects = "true"; + LOG.info("Accessing target URL: {} via ZAP to make sure it is added to the sites tree.", targetUrl); + clientApiSupport.accessUrlViaZap(targetUrl, followRedirects); + + return SESSION_IDENTIFIER; + } + + /** + * Looks for old session data and cleans them up, in case anything was left from + * a previous run. + * + * @param targetUrl + * @param clientApiSupport + */ + public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiSupport clientApiSupport) { + try { + clientApiSupport.removeHTTPSession(targetUrl, SESSION_IDENTIFIER); + } catch (ClientApiException e) { + LOG.info("Could not find old HTTP session, nothing needs to be removed."); + } + try { + clientApiSupport.removeHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); + } catch (ClientApiException e) { + LOG.info("Could not find old HTTP session token, nothing needs to be removed."); + } + try { + clientApiSupport.removeReplacerRule(JWT_REPLACER_DESCRIPTION); + } catch (ClientApiException e) { + LOG.info("Could not find old JWT repalcer rule, nothing needs to be removed."); + } + } + + private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiSupport clientApiSupport) throws ClientApiException { + String enabled = "true"; + // "REQ_HEADER" means the header entry will be added to the requests if not + // existing or replaced if already existing + String matchtype = "REQ_HEADER"; + String matchregex = "false"; + + // matchstring and replacement will be set to the header name and header value + String matchstring = "Authorization"; + String replacement = null; + + // setting initiators to null means all initiators (ZAP components), + // this means spider, active scan, etc will send this rule for their requests. + String initiators = null; + // default URL is null which means the header would be send on any request to + // any URL + String url = null; + + LOG.info("Searching: {} for JWT and add JWT as replacer rule.", LOCAL_STORAGE); + Map localStorage = retrieveStorage(firefox, LOCAL_STORAGE); + + for (String key : localStorage.keySet()) { + String value = localStorage.get(key); + if (isJWT(value)) { + replacement = "Bearer %s".formatted(value); + clientApiSupport.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + return; + } + } + LOG.info("Searching: {} for JWT and add JWT as replacer rule.", SESSION_STORAGE); + Map sessionStorage = retrieveStorage(firefox, SESSION_STORAGE); + for (String key : sessionStorage.keySet()) { + String value = sessionStorage.get(key); + if (isJWT(value)) { + replacement = "Bearer %s".formatted(value); + clientApiSupport.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + return; + } + } + } + + private Map retrieveStorage(JavascriptExecutor jsExecutor, String storageType) { + String script = """ + let items = {}; + for (let i = 0; i < %s.length; i++) { + let key = %s.key(i); + items[key] = %s.getItem(key); + } + return items; + """.formatted(storageType, storageType, storageType); + + @SuppressWarnings("unchecked") + Map storage = (Map) jsExecutor.executeScript(script); + return storage; + } + + private boolean isJWT(String value) { + if (value == null) { + return false; + } + if (!JWT_PATTERN.matcher(value).matches()) { + return false; + } + String[] split = value.split("\\."); + return split[0].startsWith("eyJ") && split[1].startsWith("eyJ"); + } + +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java new file mode 100644 index 0000000000..e57fcd1728 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import org.openqa.selenium.Dimension; +import org.openqa.selenium.Proxy; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mercedesbenz.sechub.zapwrapper.config.ProxyInformation; + +public class ZapScriptLoginWebDriverFactory { + private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLoginWebDriverFactory.class); + + private static final Dimension DEFAULT_WEBDRIVER_RESOLUTION = new Dimension(1920, 1080); + + public FirefoxDriver createFirefoxWebdriver(ProxyInformation proxyInformation, boolean headless) { + FirefoxOptions options = new FirefoxOptions(); + if (headless) { + LOG.info("Using firefox in headless mode."); + options.addArguments("-headless"); + } + options.addArguments("-private"); + + if (proxyInformation != null) { + LOG.info("Adding proxy to firefox browser options."); + String proxyString = "%s:%s".formatted(proxyInformation.getHost(), proxyInformation.getPort()); + Proxy proxy = new Proxy(); + proxy.setHttpProxy(proxyString); + proxy.setSslProxy(proxyString); + options.setProxy(proxy); + } + FirefoxDriver firefox = new FirefoxDriver(options); + // Set the window size, some application need a windows size to render correctly + // even in headless mode + firefox.manage().window().setSize(DEFAULT_WEBDRIVER_RESOLUTION); + return firefox; + } +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java new file mode 100644 index 0000000000..c2d8bd7ab9 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.*; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.time.Duration; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptException; + +import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.support.ui.WebDriverWait; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; +import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; +import com.mercedesbenz.sechub.commons.model.login.WebLoginTOTPConfiguration; +import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; +import com.mercedesbenz.sechub.zapwrapper.util.StringDecoder; +import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator; + +public class ZapWrapperGroovyScriptExecutor { + private static final Logger LOG = LoggerFactory.getLogger(ZapWrapperGroovyScriptExecutor.class); + + private static final long WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS = 30; + + public void executeScript(File scriptFile, FirefoxDriver firefox, ZapScanContext scanContext) throws IOException, ScriptException { + + String script = Files.readString(scriptFile.toPath()); + ScriptEngine scriptEngine = new GroovyScriptEngineFactory().getScriptEngine(); + + LOG.info("Create bindings for groovy script."); + Bindings bindings = createBindings(scanContext, scriptEngine, firefox); + + LOG.info("Execute groovy login script."); + scriptEngine.eval(script, bindings); + } + + private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptEngine, FirefoxDriver firefox) { + // TODO use templates structure from sechub webscan config + SecHubWebScanConfiguration secHubWebScanConfiguration = scanContext.getSecHubWebScanConfiguration(); + WebLoginConfiguration webLoginConfiguration = secHubWebScanConfiguration.getLogin().get(); + + WebLoginTOTPConfiguration totp = webLoginConfiguration.getTotp(); + TOTPGenerator totpGenerator = null; + if (totp != null) { + LOG.info("Trying to decode TOTP seed if necessary."); + StringDecoder stringDecoder = new StringDecoder(); + byte[] decodedSeedBytes = stringDecoder.decodeIfNecessary(totp.getSeed(), totp.getEncodingType()); + String decodedSeed = new String(decodedSeedBytes, StandardCharsets.UTF_8); + + LOG.info("Setting up TOTP generator for login."); + totpGenerator = new TOTPGenerator(decodedSeed, totp.getTokenLength(), totp.getHashAlgorithm(), totp.getValidityInSeconds()); + } + + // TODO read the username and password from templateData as soon as it is + // implemented + String user = "DUMMY"; + String password = "DUMMY"; + + WebDriverWait wait = new WebDriverWait(firefox, Duration.ofSeconds(WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS)); + + Bindings bindings = scriptEngine.createBindings(); + bindings.put(FIREFOX_WEBDRIVER_KEY, firefox); + bindings.put(FIREFOX_WEBDRIVER_WAIT_KEY, wait); + bindings.put(JAVASCRIPTEXECUTOR_KEY, firefox); + bindings.put(SECHUB_WEBSCAN_CONFIG_KEY, secHubWebScanConfiguration); + bindings.put(TOTP_GENERATOR_KEY, totpGenerator); + + bindings.put(USER_KEY, user); + bindings.put(PASSWORD_KEY, password); + bindings.put(LOGIN_URL_KEY, webLoginConfiguration.getUrl().toString()); + bindings.put(TARGET_URL_KEY, scanContext.getTargetUrlAsString()); + + return bindings; + } +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java index 3db406a115..b7dd70be73 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java @@ -21,4 +21,6 @@ public class EnvironmentVariableConstants { public static final String PDS_JOB_EVENTS_FOLDER = "PDS_JOB_EVENTS_FOLDER"; + public static final String PDS_TEMPLATE_FOLDER = "PDS_TEMPLATE_FOLDER"; + } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index 1a366c9e12..dc33ce4cf8 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -33,7 +33,7 @@ class ZapScanContextFactoryTest { private ZapScanContextFactory factoryToTest; - private static final EnvironmentVariableReader ENVIRONMENT_VAIRABLE_READER = mock(); + private static final EnvironmentVariableReader ENVIRONMENT_VARIABLE_READER = mock(); private static final RuleProvider RULE_PROVIDER = mock(); @@ -45,21 +45,18 @@ class ZapScanContextFactoryTest { @BeforeEach void beforeEach() { - Mockito.reset(ENVIRONMENT_VAIRABLE_READER, RULE_PROVIDER); + Mockito.reset(ENVIRONMENT_VARIABLE_READER, RULE_PROVIDER); // create object to test - factoryToTest = new ZapScanContextFactory(ENVIRONMENT_VAIRABLE_READER, new BaseTargetUriFactory(), - RULE_PROVIDER, new ZapWrapperDataSectionFileSupport(), new SecHubScanConfigProvider(), - new IncludeExcludeToZapURLHelper()); + factoryToTest = new ZapScanContextFactory(ENVIRONMENT_VARIABLE_READER, new BaseTargetUriFactory(), RULE_PROVIDER, + new ZapWrapperDataSectionFileSupport(), new SecHubScanConfigProvider(), new IncludeExcludeToZapURLHelper()); // create test data fullRulesetFile = new File("src/test/resources/zap-available-rules/zap-full-ruleset.json"); - deactivationFile = new File( - "src/test/resources/wrapper-deactivated-rule-examples/zap-rules-to-deactivate.json"); + deactivationFile = new File("src/test/resources/wrapper-deactivated-rule-examples/zap-rules-to-deactivate.json"); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)) - .thenReturn(tempDir.getAbsolutePath()); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)).thenReturn(tempDir.getAbsolutePath()); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); } @Test @@ -102,10 +99,9 @@ void context_name_is_created_as_UUID_when_not_defined() { } @ParameterizedTest - @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", - "host,4711,secret,proxy,5312" }) - void result_contains_server_config_with_arguments_from_command_line_settings_no_env_variables(String host, int port, - String apiKey, String proxy, int proxyPort) { + @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", "host,4711,secret,proxy,5312" }) + void result_contains_server_config_with_arguments_from_command_line_settings_no_env_variables(String host, int port, String apiKey, String proxy, + int proxyPort) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getZapHost()).thenReturn(host); @@ -128,29 +124,28 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ assertEquals(proxy, result.getProxyInformation().getHost()); assertEquals(proxyPort, result.getProxyInformation().getPort()); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); } @ParameterizedTest - @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", - "host,4711,secret,proxy,5312" }) - void result_contains_server_config_with_arguments_from_environment_when_command_line_settings_not_set(String host, - int port, String apiKey, String proxy, int proxyPort) { + @CsvSource({ "https://zaproxy.example.com,8080,api-key,https://proxy.example.com,3333", "host,4711,secret,proxy,5312" }) + void result_contains_server_config_with_arguments_from_environment_when_command_line_settings_not_set(String host, int port, String apiKey, String proxy, + int proxyPort) { /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getTargetURL()).thenReturn("https://www.targeturl.com"); when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); - when(ENVIRONMENT_VAIRABLE_READER.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); + when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); + when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); + when(ENVIRONMENT_VARIABLE_READER.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); - when(ENVIRONMENT_VAIRABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); + when(ENVIRONMENT_VARIABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -173,8 +168,8 @@ void proxy_set_or_not_is_valid_result_returned_contains_null_as_proxyinformation when(settings.getProxyPort()).thenReturn(0); when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); - when(ENVIRONMENT_VAIRABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); + when(ENVIRONMENT_VARIABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -192,8 +187,7 @@ void proxy_set_or_not_is_valid_result_returned_contains_null_as_proxyinformation ",4711,secret", }) /* @formatter:on*/ - void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(String host, Integer port, - String apiKey) { + void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(String host, Integer port, String apiKey) { /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getZapHost()).thenReturn(host); @@ -327,8 +321,7 @@ void fullruleset_returned_by_provider_is_in_result() { void rules_to_deactivate_returned_by_provider_is_inside_result() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(deactivationFile)) - .thenReturn(createDeactivatedRuleReferences()); + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(deactivationFile)).thenReturn(createDeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -349,7 +342,7 @@ void rules_to_deactivate_returned_by_provider_is_inside_result() { void rules_to_deactivate_returned_by_env_variable_is_inside_result(String value) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); + when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); String[] arrayToTestExpectedLength = {}; @@ -390,13 +383,12 @@ void rules_to_deactivate_returned_by_command_line_parameter_is_inside_result(Str assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(arrayToTestExpectedLength.length, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); - verify(ENVIRONMENT_VAIRABLE_READER, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @ParameterizedTest @NullSource - void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_reader_is_called_as_fallback( - String value) { + void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_reader_is_called_as_fallback(String value) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getDeactivatedRuleReferences()).thenReturn(value); @@ -406,7 +398,7 @@ void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_r factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VAIRABLE_READER, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @Test @@ -419,14 +411,14 @@ void api_definition_file_from_sechub_scan_config_is_inside_result() { "src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(1, result.getApiDefinitionFiles().size()); } @@ -439,14 +431,14 @@ void client_certificate_file_from_sechub_scan_config_is_inside_result() { File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/client-certificate-auth.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertNotNull(result.getClientCertificateFile()); } @@ -513,14 +505,14 @@ void header_config_file_from_sechub_scan_config_is_inside_result() { File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/header-config.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(2, result.getHeaderValueFiles().size()); assertEquals(extractedSourcesPath + "/header-token.txt", result.getHeaderValueFiles().get("Key").toString()); assertEquals(extractedSourcesPath + "/token.txt", result.getHeaderValueFiles().get("Other").toString()); @@ -536,17 +528,70 @@ void header_config_without_data_section_no_file_is_inside_result() { "src/test/resources/sechub-config-examples/header-config-without-data-section.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VAIRABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VAIRABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(0, result.getHeaderValueFiles().size()); } + @Test + void no_template_data_results_in_no_template_data_set() { + /* prepare */ + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + + CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); + when(settings.getTemplateFolder()).thenReturn(null); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + + /* execute */ + ZapScanContext result = factoryToTest.create(settings); + + /* test */ + verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(PDS_TEMPLATE_FOLDER); + assertNull(result.getGroovyScriptLoginFile()); + } + + @Test + void cmd_param_set_results_in_environment_variable_reader_not_being_called() { + /* prepare */ + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + + CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); + String templateDir = "templateDir"; + when(settings.getTemplateFolder()).thenReturn(templateDir); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + + /* execute */ + ZapScanContext result = factoryToTest.create(settings); + + /* test */ + verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(PDS_TEMPLATE_FOLDER); + assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); + } + + @Test + void cmd_param_not_set_results_in_environment_variable_reader_being_called_as_fallback() { + /* prepare */ + when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + + CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); + String templateDir = "templateDir"; + when(settings.getTemplateFolder()).thenReturn(null); + when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(templateDir); + + /* execute */ + ZapScanContext result = factoryToTest.create(settings); + + /* test */ + verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(PDS_TEMPLATE_FOLDER); + assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); + } + private CommandLineSettings createSettingsMockWithNecessaryParts() { CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getTargetURL()).thenReturn("https://www.targeturl.com"); diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java index 4463161471..a2855d7b04 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java @@ -10,12 +10,7 @@ import java.net.URI; import java.net.URL; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; @@ -25,6 +20,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mockito; import org.zaproxy.clientapi.core.ApiResponse; import org.zaproxy.clientapi.core.ClientApiException; @@ -32,6 +28,7 @@ import com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; import com.mercedesbenz.sechub.commons.model.login.BasicLoginConfiguration; +import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; import com.mercedesbenz.sechub.test.TestFileReader; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; @@ -44,70 +41,90 @@ import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; import com.mercedesbenz.sechub.zapwrapper.helper.IncludeExcludeToZapURLHelper; +import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; import com.mercedesbenz.sechub.zapwrapper.helper.ZapProductMessageHelper; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiFacade; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; import com.mercedesbenz.sechub.zapwrapper.scan.ZapScanner.UserInformation; +import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLogin; import com.mercedesbenz.sechub.zapwrapper.util.SystemUtil; +import com.mercedesbenz.sechub.zapwrapper.util.UrlUtil; class ZapScannerTest { private ZapScanner scannerToTest; - private ClientApiFacade clientApiFacade; - private ZapScanContext scanContext; - private ZapPDSEventHandler zapPDSEventHandler; - private SystemUtil systemUtil; + private static final ClientApiSupport CLIENT_API_SUPPORT = mock(); + private static final ZapScanContext SCAN_CONTEXT = mock(); + private static final ZapPDSEventHandler ZAP_PDS_EVENT_HANDLER = mock(); + private static final SystemUtil SYSTEM_UTIL = mock(); + private static final ZapScriptLogin SCRIPT_LOGIN = mock(); + private static final ZapProductMessageHelper MESSAGE_HELPER = mock(); - private ZapProductMessageHelper helper; - private String contextName = "context-name"; + private static final ApiResponse RESPONSE = mock(); + + private static final String BROWSER_ID = ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId(); + private static final String CONTEXT_NAME = "context-name"; @BeforeEach void beforeEach() { - // create mocks - clientApiFacade = mock(ClientApiFacade.class); - scanContext = mock(ZapScanContext.class); - systemUtil = mock(SystemUtil.class); - helper = mock(ZapProductMessageHelper.class); - - zapPDSEventHandler = mock(ZapPDSEventHandler.class); + // Reset mocks + /* @formatter:off */ + Mockito.reset(CLIENT_API_SUPPORT, + SCAN_CONTEXT, + ZAP_PDS_EVENT_HANDLER, + SYSTEM_UTIL, + SCRIPT_LOGIN, + MESSAGE_HELPER); + /* @formatter:on */ - // assign mocks - scannerToTest = ZapScanner.from(clientApiFacade, scanContext); - scannerToTest.systemUtil = systemUtil; + // create scanner to test + /* @formatter:off */ + scannerToTest = new ZapScanner(CLIENT_API_SUPPORT, + SCAN_CONTEXT, + new ScanDurationHelper(), + new UrlUtil(), + SYSTEM_UTIL, SCRIPT_LOGIN); + /* @formatter:on */ // set global behavior - when(scanContext.getContextName()).thenReturn(contextName); - when(scanContext.getZapProductMessageHelper()).thenReturn(helper); - when(scanContext.getZapPDSEventHandler()).thenReturn(zapPDSEventHandler); - when(scanContext.getAjaxSpiderBrowserId()).thenReturn(ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId()); + when(SCAN_CONTEXT.getContextName()).thenReturn(CONTEXT_NAME); + when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(MESSAGE_HELPER); + when(SCAN_CONTEXT.getZapPDSEventHandler()).thenReturn(ZAP_PDS_EVENT_HANDLER); + when(SCAN_CONTEXT.getAjaxSpiderBrowserId()).thenReturn(BROWSER_ID); - doNothing().when(helper).writeProductError(any()); - doNothing().when(helper).writeProductMessages(any()); - doNothing().when(helper).writeSingleProductMessage(any()); + when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("authSessionId"); + doNothing().when(SCRIPT_LOGIN).cleanUpScriptLoginData(anyString(), eq(CLIENT_API_SUPPORT)); - doNothing().when(systemUtil).waitForMilliseconds(ZapScanner.CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - when(systemUtil.getCurrentTimeInMilliseconds()).thenCallRealMethod(); + doNothing().when(MESSAGE_HELPER).writeProductError(any()); + doNothing().when(MESSAGE_HELPER).writeProductMessages(any()); + doNothing().when(MESSAGE_HELPER).writeSingleProductMessage(any()); + + doNothing().when(SYSTEM_UTIL).waitForMilliseconds(anyInt()); + when(SYSTEM_UTIL.getCurrentTimeInMilliseconds()).thenCallRealMethod(); + + doNothing().when(SCRIPT_LOGIN).cleanUpScriptLoginData(any(), eq(CLIENT_API_SUPPORT)); } @Test void setup_standard_configuration_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(clientApiFacade.createNewSession(scanContext.getContextName(), "true")).thenReturn(null); - when(clientApiFacade.configureMaximumAlertsForEachRule("0")).thenReturn(null); - when(clientApiFacade.enableAllPassiveScannerRules()).thenReturn(null); - when(clientApiFacade.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); - when(clientApiFacade.configureAjaxSpiderBrowserId(ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId())).thenReturn(null); + when(CLIENT_API_SUPPORT.createNewSession(SCAN_CONTEXT.getContextName(), "true")).thenReturn(null); + when(CLIENT_API_SUPPORT.configureMaximumAlertsForEachRule("0")).thenReturn(null); + when(CLIENT_API_SUPPORT.enableAllPassiveScannerRules()).thenReturn(null); + when(CLIENT_API_SUPPORT.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); + when(CLIENT_API_SUPPORT.setAjaxSpiderBrowserId(BROWSER_ID)) + .thenReturn(null); /* execute */ scannerToTest.setupStandardConfiguration(); /* test */ - verify(clientApiFacade, times(1)).createNewSession(scanContext.getContextName(), "true"); - verify(clientApiFacade, times(1)).configureMaximumAlertsForEachRule("0"); - verify(clientApiFacade, times(1)).enableAllPassiveScannerRules(); - verify(clientApiFacade, times(1)).enableAllActiveScannerRulesForPolicy(null); - verify(clientApiFacade, times(1)).configureAjaxSpiderBrowserId(ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId()); + verify(CLIENT_API_SUPPORT, times(1)).createNewSession(SCAN_CONTEXT.getContextName(), "true"); + verify(CLIENT_API_SUPPORT, times(1)).configureMaximumAlertsForEachRule("0"); + verify(CLIENT_API_SUPPORT, times(1)).enableAllPassiveScannerRules(); + verify(CLIENT_API_SUPPORT, times(1)).enableAllActiveScannerRulesForPolicy(null); + verify(CLIENT_API_SUPPORT, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); } @Test @@ -123,8 +140,8 @@ void deactivate_rules_ruleset_or_rules_to_deactivate_null_results_in_nothing_is_ scannerToTest.deactivateRules(new ZapFullRuleset(), deactivatedReferences); /* test */ - verify(clientApiFacade, never()).disablePassiveScannerRule(any()); - verify(clientApiFacade, never()).disableActiveScannerRuleForPolicy(any(), any()); + verify(CLIENT_API_SUPPORT, never()).disablePassiveScannerRule(any()); + verify(CLIENT_API_SUPPORT, never()).disableActiveScannerRuleForPolicy(any(), any()); } @Test @@ -140,28 +157,28 @@ void deactivate_rules_results_in_rules_are_deactivated() throws ClientApiExcepti String json = TestFileReader.readTextFromFile("src/test/resources/zap-available-rules/zap-full-ruleset.json"); ZapFullRuleset ruleSet = new ZapFullRuleset().fromJSON(json); - when(clientApiFacade.disablePassiveScannerRule(any())).thenReturn(null); - when(clientApiFacade.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); + when(CLIENT_API_SUPPORT.disablePassiveScannerRule(any())).thenReturn(null); + when(CLIENT_API_SUPPORT.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); /* execute */ scannerToTest.deactivateRules(ruleSet, deactivatedReferences); /* test */ - verify(clientApiFacade, times(1)).disablePassiveScannerRule(any()); - verify(clientApiFacade, times(2)).disableActiveScannerRuleForPolicy(any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).disablePassiveScannerRule(any()); + verify(CLIENT_API_SUPPORT, times(2)).disableActiveScannerRuleForPolicy(any(), any()); } @Test void setup_addtional_proxy_information_with_proxy_information_null_results_in_proxy_disabled() throws ClientApiException { /* prepare */ - when(clientApiFacade.setHttpProxyEnabled("false")).thenReturn(null); + when(CLIENT_API_SUPPORT.setHttpProxyEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(null); /* test */ - verify(clientApiFacade, times(1)).setHttpProxyEnabled("false"); + verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyEnabled("false"); } @Test @@ -172,48 +189,47 @@ void setup_addtional_proxy_information_results_in_proxy_enabled() throws ClientA var portAsString = String.valueOf(port); ProxyInformation proxyInformation = new ProxyInformation(host, port); - when(clientApiFacade.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); - when(clientApiFacade.setHttpProxyEnabled("true")).thenReturn(null); - when(clientApiFacade.setHttpProxyAuthEnabled("false")).thenReturn(null); + when(CLIENT_API_SUPPORT.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); + when(CLIENT_API_SUPPORT.setHttpProxyEnabled("true")).thenReturn(null); + when(CLIENT_API_SUPPORT.setHttpProxyAuthEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(proxyInformation); /* test */ - verify(clientApiFacade, times(1)).configureHttpProxy(host, portAsString, null, null, null); - verify(clientApiFacade, times(1)).setHttpProxyEnabled("true"); - verify(clientApiFacade, times(1)).setHttpProxyAuthEnabled("false"); + verify(CLIENT_API_SUPPORT, times(1)).configureHttpProxy(host, portAsString, null, null, null); + verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyEnabled("true"); + verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyAuthEnabled("false"); } @Test void create_context_results_in_expected_calls() throws ClientApiException { /* prepare */ String expectedContextId = "random-id"; - when(clientApiFacade.createNewContext(contextName)).thenReturn(expectedContextId); + when(CLIENT_API_SUPPORT.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); /* execute */ String contextId = scannerToTest.createContext(); /* test */ assertEquals(expectedContextId, contextId); - verify(scanContext, times(2)).getContextName(); - verify(clientApiFacade, times(1)).createNewContext(contextName); + verify(SCAN_CONTEXT, times(2)).getContextName(); + verify(CLIENT_API_SUPPORT, times(1)).createNewContext(CONTEXT_NAME); } @Test void add_replacer_rules_for_headers_with_no_headers_results_add_replacer_rule_is_never_called() throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiFacade, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(CLIENT_API_SUPPORT, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -222,17 +238,16 @@ void add_replacer_rules_for_headers_with_no_onlyForUrls_results_add_replacer_rul throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiFacade, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -241,10 +256,9 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.addReplacerRulesForHeaders(); @@ -257,7 +271,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiFacade, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @Test @@ -295,27 +309,26 @@ void add_replacer_rules_for_headers_with_data_section_results_add_replacer_rule_ """; SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubConfigWithfilesystemPartHasMoreThanOneFile).getWebScan() .get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); Map headerFiles = new HashMap<>(); headerFiles.put("Key", new File("src/test/resources/header-value-files/header-token.txt")); headerFiles.put("Other", new File("src/test/resources/header-value-files/token.txt")); - when(scanContext.getHeaderValueFiles()).thenReturn(headerFiles); + when(SCAN_CONTEXT.getHeaderValueFiles()).thenReturn(headerFiles); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiFacade, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); - verify(clientApiFacade, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); + verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); + verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-include-exclude.json" }) - void set_includes_and_excludes_api_facade_is_called_once_for_each_include_and_once_for_exclude(String sechubConfigFile) + void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_once_for_exclude(String sechubConfigFile) throws ClientApiException, MalformedURLException { /* prepare */ String json = TestFileReader.readTextFromFile(sechubConfigFile); @@ -326,16 +339,15 @@ void set_includes_and_excludes_api_facade_is_called_once_for_each_include_and_on URL targetUrl = sechubWebScanConfig.getUrl().toURL(); List includesList = sechubWebScanConfig.getIncludes().get(); Set includes = new HashSet<>(helper.createListOfUrls(targetUrl, includesList)); - when(scanContext.getZapURLsIncludeSet()).thenReturn(includes); + when(SCAN_CONTEXT.getZapURLsIncludeSet()).thenReturn(includes); List excludesList = sechubWebScanConfig.getExcludes().get(); Set excludes = new HashSet<>(helper.createListOfUrls(targetUrl, excludesList)); - when(scanContext.getZapURLsExcludeSet()).thenReturn(excludes); + when(SCAN_CONTEXT.getZapURLsExcludeSet()).thenReturn(excludes); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.addIncludeUrlPatternToContext(any(), any())).thenReturn(response); - when(clientApiFacade.accessUrlViaZap(any(), any())).thenReturn(response); - when(clientApiFacade.addExcludeUrlPatternToContext(any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.addIncludeUrlPatternToContext(any(), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.accessUrlViaZap(any(), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.addExcludeUrlPatternToContext(any(), any())).thenReturn(RESPONSE); /* @formatter:off */ int includesWithoutWildcards = (int) includes.stream() @@ -347,33 +359,32 @@ void set_includes_and_excludes_api_facade_is_called_once_for_each_include_and_on scannerToTest.addIncludedAndExcludedUrlsToContext(); /* test */ - verify(clientApiFacade, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); + verify(CLIENT_API_SUPPORT, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); // make sure this method is only called for includes without wildcards - verify(clientApiFacade, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); - verify(clientApiFacade, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); + verify(CLIENT_API_SUPPORT, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); + verify(CLIENT_API_SUPPORT, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); } @Test - void import_openapi_file_but_api_file_is_null_api_facade_is_never_called() throws ClientApiException { + void import_openapi_file_but_api_file_is_null_api_support_is_never_called() throws ClientApiException { /* prepare */ String contextId = "context-id"; - ApiResponse response = mock(ApiResponse.class); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); - when(clientApiFacade.importOpenApiFile(any(), any(), any())).thenReturn(response); - when(clientApiFacade.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(response); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); + when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiFacade, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiFacade, never()).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); + verify(CLIENT_API_SUPPORT, never()).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json" }) - void import_openapi_file_api_facade_is_called_once(String sechubConfigFile) throws ClientApiException { + void import_openapi_file_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ String contextId = "context-id"; String json = TestFileReader.readTextFromFile(sechubConfigFile); @@ -382,43 +393,41 @@ void import_openapi_file_api_facade_is_called_once(String sechubConfigFile) thro List apiFiles = new ArrayList<>(); apiFiles.add(new File("openapi3.json")); - when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getApiDefinitionFiles()).thenReturn(apiFiles); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importOpenApiFile(any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiFacade, times(1)).importOpenApiFile(any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importOpenApiFile(any(), any(), any()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-from-url.json" }) - void import_openapi_defintion_from_url_api_facade_is_called_once(String sechubConfigFile) throws ClientApiException { + void import_openapi_defintion_from_url_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ String contextId = "context-id"; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importOpenApiFile(any(), any(), any())).thenReturn(response); - when(clientApiFacade.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiFacade, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiFacade, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-from-file-and-url.json" }) - void import_openapi_from_file_and_from_url_api_facade_is_called_once(String sechubConfigFile) throws ClientApiException { + void import_openapi_from_file_and_from_url_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ String contextId = "context-id"; String json = TestFileReader.readTextFromFile(sechubConfigFile); @@ -427,35 +436,33 @@ void import_openapi_from_file_and_from_url_api_facade_is_called_once(String sech List apiFiles = new ArrayList<>(); apiFiles.add(new File("openapi3.json")); - when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getApiDefinitionFiles()).thenReturn(apiFiles); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importOpenApiFile(any(), any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiFacade, times(1)).importOpenApiFile(any(), any(), any()); - verify(clientApiFacade, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importOpenApiFile(any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @Test - void import_client_certificate_file_but_client_certificate_file_is_null_api_facade_is_never_called() throws ClientApiException { + void import_client_certificate_file_but_client_certificate_file_is_null_api_support_is_never_called() throws ClientApiException { /* prepare */ - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importPkcs12ClientCertificate(any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiFacade, never()).importOpenApiFile(any(), any(), any()); + verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); } @Test - void try_import_without_client_certificate_file_api_facade_is_never_called() throws ClientApiException { + void try_import_without_client_certificate_file_api_support_is_never_called() throws ClientApiException { /* prepare */ String jsonWithClientCertConfig = """ { @@ -470,21 +477,20 @@ void try_import_without_client_certificate_file_api_facade_is_never_called() thr File clientCertificateFile = new File("backend-cert.p12"); - when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importPkcs12ClientCertificate(any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiFacade, never()).importPkcs12ClientCertificate(any(), any()); + verify(CLIENT_API_SUPPORT, never()).importPkcs12ClientCertificate(any(), any()); } @Test - void import_client_certificate_file_api_facade_is_called_once() throws ClientApiException { + void import_client_certificate_file_api_support_is_called_once() throws ClientApiException { /* prepare */ String jsonWithCertPassword = """ { @@ -504,23 +510,22 @@ void import_client_certificate_file_api_facade_is_called_once() throws ClientApi File clientCertificateFile = mock(File.class); - when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(clientCertificateFile.exists()).thenReturn(true); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importPkcs12ClientCertificate(any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiFacade, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importPkcs12ClientCertificate(any(), any()); } @Test - void import_client_certificate_file_but_without_password_api_facade_is_called_once() throws ClientApiException { + void import_client_certificate_file_but_without_password_api_support_is_called_once() throws ClientApiException { /* prepare */ String jsonWithoutCertPassword = """ { @@ -539,18 +544,17 @@ void import_client_certificate_file_but_without_password_api_facade_is_called_on File clientCertificateFile = mock(File.class); - when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(clientCertificateFile.exists()).thenReturn(true); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.importPkcs12ClientCertificate(any(), any())).thenReturn(response); + when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiFacade, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).importPkcs12ClientCertificate(any(), any()); } @ParameterizedTest @@ -562,10 +566,10 @@ void configure_login_inside_zap_using_no_auth_and_unsupported_auth_return_null(S String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); /* execute */ - UserInformation userInformation = scannerToTest.configureLoginInsideZapContext(contextId); + UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); /* test */ assertEquals(null, userInformation); @@ -576,78 +580,156 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr /* prepare */ String contextId = "context-id"; String userId = "user-id"; - URL targetUrl = URI.create("https:127.0.0.1:8000").toURL(); + URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); String json = TestFileReader.readTextFromFile("src/test/resources/sechub-config-examples/basic-auth.json"); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); BasicLoginConfiguration basicLoginConfiguration = sechubWebScanConfig.getLogin().get().getBasic().get(); String userName = new String(basicLoginConfiguration.getUser()); - ApiResponse response = mock(ApiResponse.class); + String zapAuthenticationMethod = AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - when(scanContext.getTargetUrl()).thenReturn(targetUrl); - when(scanContext.getAuthenticationType()).thenReturn(AuthenticationType.HTTP_BASIC_AUTHENTICATION); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiFacade.configureAuthenticationMethod(eq(contextId), eq(AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod()), any())) - .thenReturn(response); - when(clientApiFacade.setSessionManagementMethod(eq(contextId), eq(SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod()), - any())).thenReturn(response); - when(clientApiFacade.createNewUser(contextId, userName)).thenReturn(userId); - when(clientApiFacade.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(response); - when(clientApiFacade.setForcedUser(contextId, userId)).thenReturn(response); - when(clientApiFacade.setForcedUserModeEnabled(true)).thenReturn(response); + when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); + when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); /* execute */ - UserInformation userInformation = scannerToTest.configureLoginInsideZapContext(contextId); + UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); /* test */ assertEquals(userName, userInformation.userName()); assertEquals(userId, userInformation.zapuserId()); - verify(scanContext, times(2)).getTargetUrl(); - verify(scanContext, times(1)).getAuthenticationType(); + verify(SCAN_CONTEXT, times(2)).getTargetUrl(); - verify(clientApiFacade, times(1)).configureAuthenticationMethod(eq(contextId), - eq(AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod()), any()); - verify(clientApiFacade, times(1)).setSessionManagementMethod(eq(contextId), - eq(SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod()), any()); - verify(clientApiFacade, times(1)).createNewUser(contextId, userName); - verify(clientApiFacade, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(clientApiFacade, times(1)).setForcedUser(contextId, userId); - verify(clientApiFacade, times(1)).setForcedUserModeEnabled(true); + verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(CLIENT_API_SUPPORT, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(CLIENT_API_SUPPORT, times(1)).createNewUser(contextId, userName); + verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(CLIENT_API_SUPPORT, times(1)).setForcedUser(contextId, userId); + verify(CLIENT_API_SUPPORT, times(1)).setForcedUserModeEnabled(true); } @Test - void generate_report_calls_api_facade_once() throws ClientApiException { + void configure_login_inside_zap_using_script_auth_without_script_file_results_in_script_login_not_being_called() throws Exception { /* prepare */ - when(scanContext.getReportFile()) + String contextId = "context-id"; + String userId = "user-id"; + String userName = "user"; + URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); + SecHubWebScanConfiguration sechubWebScanConfig = new SecHubWebScanConfiguration(); + sechubWebScanConfig.setUrl(targetUrl.toURI()); + WebLoginConfiguration login = new WebLoginConfiguration(); + sechubWebScanConfig.setLogin(Optional.of(login)); + + String zapAuthenticationMethod = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + + when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("zap-auth-session"); + + when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getGroovyScriptLoginFile()).thenReturn(null); + + when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); + when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); + + /* execute */ + UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); + + /* test */ + assertNull(userInformation); + verify(SCRIPT_LOGIN, never()).login(SCAN_CONTEXT, CLIENT_API_SUPPORT); + verify(SCAN_CONTEXT, times(1)).getGroovyScriptLoginFile(); + } + + @Test + void configure_login_inside_zap_using_script_auth_with_existing_script_file_results_in_script_login_being_called() throws Exception { + /* prepare */ + String contextId = "context-id"; + String userId = "user-id"; + String userName = "DUMMY"; + URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); + SecHubWebScanConfiguration sechubWebScanConfig = new SecHubWebScanConfiguration(); + sechubWebScanConfig.setUrl(targetUrl.toURI()); + WebLoginConfiguration login = new WebLoginConfiguration(); + sechubWebScanConfig.setLogin(Optional.of(login)); + + String zapAuthenticationMethod = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); + + when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("zap-auth-session"); + + when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getGroovyScriptLoginFile()).thenReturn(scriptFile); + + when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); + when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); + when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); + + /* execute */ + UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); + + /* test */ + assertEquals(userName, userInformation.userName()); + assertEquals(userId, userInformation.zapuserId()); + + verify(SCRIPT_LOGIN, times(1)).login(SCAN_CONTEXT, CLIENT_API_SUPPORT); + verify(SCAN_CONTEXT, times(2)).getGroovyScriptLoginFile(); + + verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(CLIENT_API_SUPPORT, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(CLIENT_API_SUPPORT, times(1)).createNewUser(contextId, userName); + verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(CLIENT_API_SUPPORT, times(1)).setForcedUser(contextId, userId); + verify(CLIENT_API_SUPPORT, times(1)).setForcedUserModeEnabled(true); + } + + @Test + void generate_report_calls_api_support_once() throws ClientApiException { + /* prepare */ + when(SCAN_CONTEXT.getReportFile()) .thenReturn(Paths.get("src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json")); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), - any(), any())).thenReturn(response); + + when(CLIENT_API_SUPPORT.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), + any(), any(), any())).thenReturn(RESPONSE); /* execute */ scannerToTest.generateZapReport(); /* test */ - verify(clientApiFacade, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), - any(), any(), any(), any()); + verify(CLIENT_API_SUPPORT, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), + any(), any(), any(), any(), any()); } @Test void cleanup_after_scan() throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.removeReplacerRule(any())).thenReturn(response); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); + when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); /* execute */ scannerToTest.cleanUp(); /* test */ - verify(clientApiFacade, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); } @ParameterizedTest @@ -655,18 +737,18 @@ void cleanup_after_scan() throws ClientApiException { void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_rules(String sechubScanConfigJSON) throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.removeReplacerRule(any())).thenReturn(response); + when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); /* execute */ scannerToTest.cleanUp(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiFacade, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(clientApiFacade, times(times + 1)).removeReplacerRule(any()); + verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(CLIENT_API_SUPPORT, times(times + 1)).removeReplacerRule(any()); + verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); } @ParameterizedTest @@ -674,10 +756,9 @@ void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_r void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rules(String sechubScanConfigJSON) throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - ApiResponse response = mock(ApiResponse.class); - when(clientApiFacade.removeReplacerRule(any())).thenReturn(response); + when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); /* execute */ scannerToTest.cleanUp(); @@ -690,53 +771,53 @@ void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rule times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiFacade, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(clientApiFacade, times(times + 1)).removeReplacerRule(any()); + verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(CLIENT_API_SUPPORT, times(times + 1)).removeReplacerRule(any()); + verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); } @Test - void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { + void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() + throws ClientApiException { /* prepare */ - when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(zapPDSEventHandler).cancelScan(contextName); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(20000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + long scanDuration = 20000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); - when(clientApiFacade.stopAjaxSpider()).thenReturn(null); + when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForAjaxSpiderResults(); + scannerToTest.waitForAjaxSpiderResults(scanDuration); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiFacade, times(1)).stopAjaxSpider(); + verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); } @Test void wait_for_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(1000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + long scanDuration = 1000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); - when(clientApiFacade.stopAjaxSpider()).thenReturn(null); - when(clientApiFacade.getAjaxSpiderStatus()).thenReturn("stopped"); + when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); + when(CLIENT_API_SUPPORT.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ - scannerToTest.waitForAjaxSpiderResults(); + scannerToTest.waitForAjaxSpiderResults(scanDuration); /* test */ - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiFacade, atLeast(1)).getAjaxSpiderStatus(); - verify(clientApiFacade, times(1)).stopAjaxSpider(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(CLIENT_API_SUPPORT, atLeast(1)).getAjaxSpiderStatus(); + verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); } @Test @@ -744,25 +825,24 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ /* prepare */ String scanId = "12345"; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(zapPDSEventHandler).cancelScan(contextName); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(20000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + long scanDuration = 20000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); - when(clientApiFacade.stopSpiderScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForSpiderResults(scanId); + scannerToTest.waitForSpiderResults(scanId, scanDuration); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiFacade, times(1)).stopSpiderScan(scanId); + verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); } @Test @@ -770,166 +850,163 @@ void wait_for_spider_scan_ended_results_in_expected_calls() throws ClientApiExce /* prepare */ String scanId = "12345"; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(1000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + long scanDuration = 1000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); - when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); + when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(messageHelper); - when(clientApiFacade.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiFacade.getSpiderStatusForScan(scanId)).thenReturn(42); - when(clientApiFacade.logFullSpiderResults(scanId)).thenReturn(0L); + when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.getSpiderStatusForScan(scanId)).thenReturn(42); + when(CLIENT_API_SUPPORT.logFullSpiderResults(scanId)).thenReturn(0L); /* execute */ - scannerToTest.waitForSpiderResults(scanId); + scannerToTest.waitForSpiderResults(scanId, scanDuration); /* test */ - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiFacade, atLeast(1)).getSpiderStatusForScan(scanId); - verify(clientApiFacade, times(1)).stopSpiderScan(scanId); - verify(clientApiFacade, times(1)).logFullSpiderResults(scanId); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(SCAN_CONTEXT, times(1)).getZapProductMessageHelper(); + verify(CLIENT_API_SUPPORT, atLeast(1)).getSpiderStatusForScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).logFullSpiderResults(scanId); } @Test - void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { + void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() + throws ClientApiException { /* prepare */ - when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(zapPDSEventHandler).cancelScan(contextName); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(20000L); - when(scanContext.isActiveScanEnabled()).thenReturn(false); - when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); + long scanDuration = 20000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(false); + when(SCAN_CONTEXT.isAjaxSpiderEnabled()).thenReturn(false); - when(clientApiFacade.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); + when(CLIENT_API_SUPPORT.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.passiveScan(); + scannerToTest.passiveScan(scanDuration); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).isAjaxSpiderEnabled(); - verify(clientApiFacade, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(SCAN_CONTEXT, times(1)).isAjaxSpiderEnabled(); + verify(CLIENT_API_SUPPORT, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(20000L); - when(scanContext.isActiveScanEnabled()).thenReturn(false); - when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); + long scanDuration = 20000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(false); + when(SCAN_CONTEXT.isAjaxSpiderEnabled()).thenReturn(false); - when(clientApiFacade.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); + when(CLIENT_API_SUPPORT.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); /* execute */ - scannerToTest.passiveScan(); + scannerToTest.passiveScan(scanDuration); /* test */ - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).isAjaxSpiderEnabled(); - verify(clientApiFacade, times(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(SCAN_CONTEXT, times(1)).isAjaxSpiderEnabled(); + verify(CLIENT_API_SUPPORT, times(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { /* prepare */ String scanId = "12345"; + long scanDuration = 20000L; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(zapPDSEventHandler).cancelScan(contextName); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); - when(clientApiFacade.getActiveScannerStatusForScan(scanId)).thenReturn(42); - when(clientApiFacade.stopActiveScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(42); + when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForActiveScanResults(scanId); + scannerToTest.waitForActiveScanResults(scanId, scanDuration); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(clientApiFacade, never()).getActiveScannerStatusForScan(scanId); - verify(clientApiFacade, times(1)).stopActiveScan(scanId); + verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); + verify(CLIENT_API_SUPPORT, never()).getActiveScannerStatusForScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); } @Test void wait_for_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ String scanId = "12345"; + long scanDuration = 20000L; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(clientApiFacade.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(clientApiFacade.stopActiveScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); /* execute */ - scannerToTest.waitForActiveScanResults(scanId); + scannerToTest.waitForActiveScanResults(scanId, scanDuration); /* test */ - verify(clientApiFacade, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiFacade, times(1)).stopActiveScan(scanId); + verify(CLIENT_API_SUPPORT, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); } @Test void run_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(1000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + long scanDuration = 1000L; + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); - when(clientApiFacade.stopAjaxSpider()).thenReturn(null); - when(clientApiFacade.getAjaxSpiderStatus()).thenReturn("stopped"); + when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); + when(CLIENT_API_SUPPORT.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ - scannerToTest.runAjaxSpider(); + scannerToTest.runAjaxSpider(scanDuration); /* test */ - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiFacade, atLeast(1)).getAjaxSpiderStatus(); - verify(clientApiFacade, times(1)).stopAjaxSpider(); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(CLIENT_API_SUPPORT, atLeast(1)).getAjaxSpiderStatus(); + verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); } @Test void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ String scanId = "12345"; + long scanDuration = 1000L; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(scanContext.getMaxScanDurationInMilliSeconds()).thenReturn(1000L); - when(scanContext.isActiveScanEnabled()).thenReturn(true); + when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); - when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); + when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(messageHelper); - when(clientApiFacade.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiFacade.getSpiderStatusForScan(scanId)).thenReturn(42); - when(clientApiFacade.logFullSpiderResults(scanId)).thenReturn(0L); - when(clientApiFacade.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); + when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.getSpiderStatusForScan(scanId)).thenReturn(42); + when(CLIENT_API_SUPPORT.logFullSpiderResults(scanId)).thenReturn(0L); + when(CLIENT_API_SUPPORT.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); /* execute */ - scannerToTest.runSpider(); + scannerToTest.runSpider(scanDuration); /* test */ - verify(scanContext, times(1)).getMaxScanDurationInMilliSeconds(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiFacade, atLeast(1)).getSpiderStatusForScan(scanId); - verify(clientApiFacade, times(1)).stopSpiderScan(scanId); - verify(clientApiFacade, times(1)).logFullSpiderResults(scanId); - verify(clientApiFacade, times(1)).startSpiderScan(any(), any(), any(), any(), any()); + verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); + verify(SCAN_CONTEXT, times(1)).getZapProductMessageHelper(); + verify(CLIENT_API_SUPPORT, atLeast(1)).getSpiderStatusForScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).logFullSpiderResults(scanId); + verify(CLIENT_API_SUPPORT, times(1)).startSpiderScan(any(), any(), any(), any(), any()); } @Test @@ -937,22 +1014,22 @@ void run_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiEx /* prepare */ String scanId = "12345"; - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); + long scanDuration = 20000L; - scannerToTest.remainingScanTime = 100L; + when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); - when(clientApiFacade.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(clientApiFacade.stopActiveScan(scanId)).thenReturn(null); - when(clientApiFacade.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); - when(clientApiFacade.atLeastOneURLDetected()).thenReturn(true); + when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); + when(CLIENT_API_SUPPORT.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); + when(CLIENT_API_SUPPORT.atLeastOneURLDetected()).thenReturn(true); /* execute */ - scannerToTest.runActiveScan(); + scannerToTest.runActiveScan(scanDuration); /* test */ - verify(clientApiFacade, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiFacade, times(1)).stopActiveScan(scanId); - verify(clientApiFacade, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); + verify(CLIENT_API_SUPPORT, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); + verify(CLIENT_API_SUPPORT, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); } static Stream headerPartWithoutOnlyForUrlsTestNamedArguments() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java new file mode 100644 index 0000000000..6aef545162 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.openqa.selenium.Cookie; +import org.openqa.selenium.WebDriver.Options; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.zaproxy.clientapi.core.ApiResponse; +import org.zaproxy.clientapi.core.ClientApiException; + +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; + +class ZapScriptLoginSessionGrabberTest { + + private ZapScriptLoginSessionGrabber sessionGrabberToTest; + + private static final ClientApiSupport CLIENT_API_SUPPORT = mock(ClientApiSupport.class, new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + // Return the same response for any method call + return ZAP_API_RESPONSE; + } + }); + private static final FirefoxDriver FIREFOX = mock(); + private static final Options WEBDRIVER_OPTIONS = mock(); + + private static final ApiResponse ZAP_API_RESPONSE = mock(); + + private static final String TARGET_URL = "http://example.com"; + private static final String FOLLOW_REDIRECTS = "true"; + + @BeforeEach + void beforeEach() { + Mockito.reset(CLIENT_API_SUPPORT, FIREFOX, WEBDRIVER_OPTIONS); + sessionGrabberToTest = new ZapScriptLoginSessionGrabber(); + } + + @Test + void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiException { + /* prepare */ + Cookie cookie = new Cookie("name", "value"); + Set cookies = Set.of(cookie); + + Map storage = new HashMap<>(); + // example from https://jwt.io/ + storage.put("jwt", + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); + + when(FIREFOX.manage()).thenReturn(WEBDRIVER_OPTIONS); + + when(WEBDRIVER_OPTIONS.getCookies()).thenReturn(cookies); + when(FIREFOX.executeScript(anyString())).thenReturn(storage); + + /* execute */ + sessionGrabberToTest.extractSessionAndPassToZAP(FIREFOX, TARGET_URL, CLIENT_API_SUPPORT); + + /* test */ + verify(FIREFOX, times(1)).manage(); + verify(WEBDRIVER_OPTIONS, times(1)).getCookies(); + verify(FIREFOX, times(1)).executeScript(anyString()); + + verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(any()); + verify(CLIENT_API_SUPPORT, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); + verify(CLIENT_API_SUPPORT, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + + verify(CLIENT_API_SUPPORT, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + } + + @Test + void no_cookie_and_no_jwt_results_clienapisupport_not_adding_replacer_rule() throws ClientApiException { + /* prepare */ + when(FIREFOX.manage()).thenReturn(WEBDRIVER_OPTIONS); + + when(WEBDRIVER_OPTIONS.getCookies()).thenReturn(Collections.emptySet()); + when(FIREFOX.executeScript(anyString())).thenReturn(Collections.emptyMap()); + + /* execute */ + sessionGrabberToTest.extractSessionAndPassToZAP(FIREFOX, TARGET_URL, CLIENT_API_SUPPORT); + + /* test */ + // both browser storages are checked now without JWT + verify(FIREFOX, times(2)).executeScript(anyString()); + // no JWT can be added + verify(CLIENT_API_SUPPORT, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + // no cookie can be added + verify(CLIENT_API_SUPPORT, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); + + // the other calls must be the same as on every execution without error + verify(FIREFOX, times(1)).manage(); + verify(WEBDRIVER_OPTIONS, times(1)).getCookies(); + + verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(any()); + verify(CLIENT_API_SUPPORT, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(CLIENT_API_SUPPORT, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + + verify(CLIENT_API_SUPPORT, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + } + +} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java new file mode 100644 index 0000000000..68a1212563 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Optional; + +import javax.script.ScriptException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.zaproxy.clientapi.core.ClientApiException; + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; +import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; +import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; +import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; + +class ZapScriptLoginTest { + + private static final String AUTH_SESSION = "auth-session"; + + private ZapScriptLogin scriptLoginToTest; + + private static final ZapScriptLoginWebDriverFactory WEB_DRIVER_FACTORY = mock(); + private static final ZapWrapperGroovyScriptExecutor GROOVY_SCRIPT_EXECUTOR = mock(); + private static final ZapScriptLoginSessionGrabber SESSION_GRABBER = mock(); + + private static final ClientApiSupport CLIENT_API_SUPPORT = mock(); + private static final FirefoxDriver FIREFOX = mock(); + + @BeforeEach + void beforeEach() { + Mockito.reset(WEB_DRIVER_FACTORY, GROOVY_SCRIPT_EXECUTOR, SESSION_GRABBER, FIREFOX, CLIENT_API_SUPPORT); + scriptLoginToTest = new ZapScriptLogin(WEB_DRIVER_FACTORY, GROOVY_SCRIPT_EXECUTOR, SESSION_GRABBER); + } + + @Test + void script_login_execution_is_perfomed_as_expected() throws Exception { + /* prepare */ + + ZapScanContext scanContext = createValidZapScanContext(); + + when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); + doNothing().when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + + /* execute */ + scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT); + + /* test */ + verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + verify(SESSION_GRABBER, times(1)).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(FIREFOX, times(1)).quit(); + } + + @Test + void script_can_not_be_read_results_in_firefox_closed_and_session_grabber_never_called() throws Exception { + /* prepare */ + ZapScanContext scanContext = createValidZapScanContext(); + + when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); + doThrow(IOException.class).when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + + /* execute */ + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + + /* test */ + verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + verify(SESSION_GRABBER, never()).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(FIREFOX, times(1)).quit(); + } + + @Test + void script_login_execution_fails_results_in_firefox_closed_and_session_grabber_never_called() throws Exception { + /* prepare */ + ZapScanContext scanContext = createValidZapScanContext(); + + when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); + doThrow(ScriptException.class).when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + + /* execute */ + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + + /* test */ + verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + verify(SESSION_GRABBER, never()).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(FIREFOX, times(1)).quit(); + } + + @Test + void session_grabbing_fails_results_in_firefox_closed() throws Exception { + /* prepare */ + ZapScanContext scanContext = createValidZapScanContext(); + + when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); + doNothing().when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + doThrow(ClientApiException.class).when(SESSION_GRABBER).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + + /* execute */ + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + + /* test */ + verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); + verify(SESSION_GRABBER, times(1)).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(FIREFOX, times(1)).quit(); + } + + private ZapScanContext createValidZapScanContext() throws MalformedURLException, URISyntaxException { + URL targetUrl = new URL("http://example.com"); + + WebLoginConfiguration login = new WebLoginConfiguration(); + login.setUrl(new URL("http://example.com/login")); + + SecHubWebScanConfiguration webScanConfig = new SecHubWebScanConfiguration(); + webScanConfig.setUrl(targetUrl.toURI()); + webScanConfig.setLogin(Optional.of(login)); + File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); + /* @formatter:off */ + return ZapScanContext.builder() + .setSecHubWebScanConfiguration(webScanConfig) + .setGroovyScriptLoginFile(scriptFile) + .setTargetUrl(targetUrl) + .build(); + /* @formatter:on */ + } + +} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java new file mode 100644 index 0000000000..07f36e36a9 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.Optional; + +import javax.script.ScriptException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; +import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; +import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; + +class ZapWrapperGroovyScriptExecutorTest { + + private ZapWrapperGroovyScriptExecutor scriptExecutorToTest; + + @BeforeEach + void beforeEach() { + scriptExecutorToTest = new ZapWrapperGroovyScriptExecutor(); + } + + @Test + void throws_io_exception_when_script_cannot_be_read() { + /* prepare */ + File scriptFile = new File("not-existing.groovy"); + + /* execute + test */ + assertThrows(IOException.class, () -> scriptExecutorToTest.executeScript(scriptFile, null, null)); + } + + @Test + void throws_script_exception_when_script_contains_errors() throws Exception { + /* prepare */ + File scriptFile = new File("src/test/resources/login-script-examples/invalid-script.groovy"); + + SecHubWebScanConfiguration webScanConfig = new SecHubWebScanConfiguration(); + webScanConfig.setUrl(URI.create("http://example.com")); + + WebLoginConfiguration login = new WebLoginConfiguration(); + login.setUrl(new URL("http://example.com/login")); + webScanConfig.setLogin(Optional.of(login)); + + ZapScanContext zapScanContext = ZapScanContext.builder().setSecHubWebScanConfiguration(webScanConfig).setTargetUrl(webScanConfig.getUrl().toURL()) + .build(); + + /* execute + test */ + assertThrows(ScriptException.class, () -> scriptExecutorToTest.executeScript(scriptFile, null, zapScanContext)); + } + + @Test + void valid_script_is_executed_as_expected() throws Exception { + /* prepare */ + File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); + + SecHubWebScanConfiguration webScanConfig = new SecHubWebScanConfiguration(); + webScanConfig.setUrl(URI.create("http://example.com")); + + WebLoginConfiguration login = new WebLoginConfiguration(); + login.setUrl(new URL("http://example.com/login")); + webScanConfig.setLogin(Optional.of(login)); + + ZapScanContext zapScanContext = ZapScanContext.builder().setSecHubWebScanConfiguration(webScanConfig).setTargetUrl(webScanConfig.getUrl().toURL()) + .build(); + + /* execute + test */ + assertDoesNotThrow(() -> scriptExecutorToTest.executeScript(scriptFile, null, zapScanContext)); + } + +} diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy new file mode 100644 index 0000000000..0f8fdd132d --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy @@ -0,0 +1,27 @@ + +import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.* + +import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator + +import org.openqa.selenium.WebDriver +import org.openqa.selenium.support.ui.ExpectedConditions +import org.openqa.selenium.By +import org.openqa.selenium.support.ui.WebDriverWait +import org.openqa.selenium.JavascriptExecutor + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration + + +final WebDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) +final WebDriverWait webdriverWait = binding.getVariable(FIREFOX_WEBDRIVER_WAIT_KEY) +final JavascriptExecutor javaScriptExecutor = binding.getVariable(JAVASCRIPTEXECUTOR_KEY) +final SecHubWebScanConfiguration sechubWebScanConfig = binding.getVariable(SECHUB_WEBSCAN_CONFIG_KEY) +final TOTPGenerator totpGenerator = binding.getVariable(TOTP_GENERATOR_KEY) + +final String user = binding.getVariable(USER_KEY) +final String password = binding.getVariable(PASSWORD_KEY) +final String loginUrl = binding.getVariable(LOGIN_URL_KEY) +final String targetUrl = binding.getVariable(TARGET_URL_KEY) + + +invalid-code diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy new file mode 100644 index 0000000000..182de33c7e --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy @@ -0,0 +1,27 @@ + +import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.* + +import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator + +import org.openqa.selenium.WebDriver +import org.openqa.selenium.support.ui.ExpectedConditions +import org.openqa.selenium.By +import org.openqa.selenium.support.ui.WebDriverWait +import org.openqa.selenium.JavascriptExecutor + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration + + +final WebDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) +final WebDriverWait webdriverWait = binding.getVariable(FIREFOX_WEBDRIVER_WAIT_KEY) +final JavascriptExecutor javaScriptExecutor = binding.getVariable(JAVASCRIPTEXECUTOR_KEY) +final SecHubWebScanConfiguration sechubWebScanConfig = binding.getVariable(SECHUB_WEBSCAN_CONFIG_KEY) +final TOTPGenerator totpGenerator = binding.getVariable(TOTP_GENERATOR_KEY) + +final String user = binding.getVariable(USER_KEY) +final String password = binding.getVariable(PASSWORD_KEY) +final String loginUrl = binding.getVariable(LOGIN_URL_KEY) +final String targetUrl = binding.getVariable(TARGET_URL_KEY) + + +return diff --git a/sechub-wrapper-owasp-zap/src/main/resources/zap-ruleset-helper/requirements.txt b/sechub-wrapper-owasp-zap/zap-ruleset-helper/requirements.txt similarity index 100% rename from sechub-wrapper-owasp-zap/src/main/resources/zap-ruleset-helper/requirements.txt rename to sechub-wrapper-owasp-zap/zap-ruleset-helper/requirements.txt diff --git a/sechub-wrapper-owasp-zap/src/main/resources/zap-ruleset-helper/zap_ruleset_helper.py b/sechub-wrapper-owasp-zap/zap-ruleset-helper/zap_ruleset_helper.py similarity index 100% rename from sechub-wrapper-owasp-zap/src/main/resources/zap-ruleset-helper/zap_ruleset_helper.py rename to sechub-wrapper-owasp-zap/zap-ruleset-helper/zap_ruleset_helper.py From d0755f503682a4e4ea1c99c471ecae2876104559 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Mon, 18 Nov 2024 09:17:32 +0100 Subject: [PATCH 05/13] add groovy example to README.adoc and improve TOTP usability #3611 - add groovy script example to README.adoc - add short explanations - add method to TOTPGenerator to generate a currently valid TOTP - update examples --- sechub-wrapper-owasp-zap/README.adoc | 104 +++++++++++++++--- .../zapwrapper/cli/CommandLineSettings.java | 6 +- .../sechub/zapwrapper/util/TOTPGenerator.java | 17 ++- .../invalid-script.groovy | 4 +- .../login-script-examples/test-script.groovy | 4 +- 5 files changed, 106 insertions(+), 29 deletions(-) diff --git a/sechub-wrapper-owasp-zap/README.adoc b/sechub-wrapper-owasp-zap/README.adoc index b2333cebce..e52452255c 100644 --- a/sechub-wrapper-owasp-zap/README.adoc +++ b/sechub-wrapper-owasp-zap/README.adoc @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -== Owasp Zap Wrapper +== Zap Wrapper -Owasp Zap Wrapper CLI for PDS +Zap Wrapper CLI for PDS === Usage @@ -24,33 +24,50 @@ PROXY_PORT=1234 To use the wrapper see the help below: ---- -Usage: OwaspZapWrapper [options] +Usage: ZapWrapper [options] Options: --activeScan - Set this option to enable Owasp Zap active scan. + Set this option to enable Zap active scan. Default: false --ajaxSpider - Set this option to enable Owasp Zap ajaxSpider. + Set this option to enable Zap ajaxSpider. Default: false + --ajaxSpiderBrowserId + Set the browser id you want to use for the AjaxSpider module. Make sure + the browser you want to use is installed on the system running the scan. + Supported browsers are: [firefox-headless, firefox, chrome-headless, + chrome, htmlunit, safari]. + Default: firefox-headless --connectionCheck Set this option to enable an initial connection check performed by this wrapper application. Default: false --deactivateRules Specify references of rules you want to deactivate during the scan - inside the Owasp Zap. If you specifiy multiple rules use comma separated - values like: rule1,rule,rule3 + inside the Zap. If you specify multiple rules use comma separated values + like: rule1,rule,rule3 * --fullRulesetfile - Specify a file with all rules installed for the Owasp Zap. + Specify a file with all rules installed for the Zap. --help Shows help and provides information on how to use the wrapper. --jobUUID - The Job-UUID, which will be used as internal identifier for the Owasp - Zap scan context. + The Job-UUID, which will be used as internal identifier for the Zap scan + context. --maxNumberOfConnectionRetries Maximum number of times the wrapper tries to reach each URL. Including each URL constructed from the sechub includes. Default: 3 + --pdsEventFolder + Folder where the ZAP wrapper listens for events of the PDS, like cancel + requests for the current job. When using with SecHub+PDS solution this + is not needed since the PDS provides the env variable: + PDS_JOB_EVENTS_FOLDER. This env variable is automatically used if this + command line parameter is not set. + --pdsUserMessageFolder + Folder where the user messages are written to. When using with + SecHub+PDS solution this is not needed since the PDS provides the env + variable: PDS_JOB_USER_MESSAGES_FOLDER. This env variable is + automatically used if this command line parameter is not set. --proxyHost Specify a proxy host. You can also set the environment variable PROXY_HOST, instead of using this parameter. @@ -65,25 +82,29 @@ Usage: OwaspZapWrapper [options] value cannot be less than 1000 milliseconds. Default: 1000 --rulesDeactivationfile - Specify a file with rules to deactivate during the scan inside the Owasp - Zap. + Specify a file with rules to deactivate during the scan inside the Zap. --sechubConfigfile The SecHub config file, containing additonal configurations for the scan. * --targetURL Specifies the target url to be scanned. + --templateFolder + Folder where the ZAP wrapper fetches the logins script from. This is not + needed since the PDS provides the env variable: PDS_TEMPLATE_FOLDER. + This env variable is automatically used if this command line parameter + is not set. --verbose Set this option to provide additional output while scanning. Default: false --zapApiKey - Specifies the Owasp Zap host api key. You can also set the environment + Specifies the Zap host api key. You can also set the environment variable ZAP_API_KEY, instead of using this parameter. --zapHost - Specifies the Owasp Zap host address. You can also set the environment + Specifies the Zap host address. You can also set the environment variable ZAP_HOST, instead of using this parameter. --zapPort - Specifies the Owasp Zap host port. You can also set the environment - variable ZAP_PORT, instead of using this parameter. + Specifies the Zap host port. You can also set the environment variable + ZAP_PORT, instead of using this parameter. Default: 0 ---- @@ -175,4 +196,53 @@ ZAP_DEACTIVATED_RULE_REFERENCES=Directory-Browsing-0,Private-IP-Disclosure-2 But if the command line parameter `--deactivateRules` is set, the wrapper ignores this environment variable. The rules to deactivate specified via `--rulesDeactivationfile`, will always be added to the list of deactivated rules. To set the env variable you can use `zap.deactivation.rule.references=Directory-Browsing-0,Private-IP-Disclosure-2`, -inside the executor config. \ No newline at end of file +inside the executor config. + + +==== Groovy Script Login +To handle more complex authentication scenarios, the wrapper uses pre-defined groovy scripts. +Rhe groovy authentication scripts have access to certain data the wrapper application passes with the bindings for the script execution, as well as selenium support. +Some objects are already ready pre-configured and ready to use, like the firefox webdriver. Above you can see all available bindings, even if they are not used in this example script. +The script can also be created completely without using anything of the pre-defined data. + +The `TOTPGenerator` is an easy to use implementation of TOTP for two-factor-authentication if necessary. Using `totpGenerator.now()` returns the currently valid TOTP. +To make use of the script authentication the wrapper application expects a SecHub configuration json for the scan, which contains a template data definition and optionally a TOTP configuration. +See web scan example configurations for details. +The following example contains all available bindings, even if they are unused in the script below: + +[source,groovy] +---- +import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.* + +import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator + +import org.openqa.selenium.firefox.FirefoxDriver +import org.openqa.selenium.support.ui.ExpectedConditions +import org.openqa.selenium.By +import org.openqa.selenium.support.ui.WebDriverWait +import org.openqa.selenium.JavascriptExecutor + +import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration + +// all available bindings +final FirefoxDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) +final WebDriverWait webdriverWait = binding.getVariable(FIREFOX_WEBDRIVER_WAIT_KEY) +final JavascriptExecutor javaScriptExecutor = binding.getVariable(JAVASCRIPTEXECUTOR_KEY) +final SecHubWebScanConfiguration sechubWebScanConfig = binding.getVariable(SECHUB_WEBSCAN_CONFIG_KEY) +final TOTPGenerator totpGenerator = binding.getVariable(TOTP_GENERATOR_KEY) + +final String user = binding.getVariable(USER_KEY) +final String password = binding.getVariable(PASSWORD_KEY) +final String loginUrl = binding.getVariable(LOGIN_URL_KEY) +final String targetUrl = binding.getVariable(TARGET_URL_KEY) + +// example authentication script steps +firefox.get(loginUrl) + +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector(".close-dialog"))).click() +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("email"))).sendKeys(user) +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("password"))).sendKeys(password) +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("loginButton"))).click() +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("otp"))).sendKeys(totpGenerator.now()) +webdriverWait.until(ExpectedConditions.presenceOfElementLocated(By.id("submitOtp"))).click() +---- \ No newline at end of file diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java index 6f387f4ad7..ed1d71662b 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java @@ -55,8 +55,8 @@ public boolean isAjaxSpiderEnabled() { } @Parameter(names = { "--ajaxSpiderBrowserId" }, description = "Set the browser id you want to use for the AjaxSpider module. " - + "Make sure the browser you want to use is installed on the system the scan is running. " - + "Supported browser are: [firefox-headless, firefox, chrome-headless, chrome, htmlunit, safari].", required = false, validateWith = ZAPAcceptedBrowserIdValidator.class) + + "Make sure the browser you want to use is installed on the system running the scan. " + + "Supported browsers are: [firefox-headless, firefox, chrome-headless, chrome, htmlunit, safari].", required = false, validateWith = ZAPAcceptedBrowserIdValidator.class) private String ajaxSpiderBrowserId = ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId(); public String getAjaxSpiderBrowserId() { @@ -132,7 +132,7 @@ public File getRulesDeactvationFile() { } @Parameter(names = { "--deactivateRules" }, description = "Specify references of rules you want to deactivate during the scan inside the Zap. " - + "If you specifiy multiple rules use comma separated values like: rule1,rule,rule3", required = false) + + "If you specify multiple rules use comma separated values like: rule1,rule,rule3", required = false) private String deactivatedRuleReferences; public String getDeactivatedRuleReferences() { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java index 8f8b98f391..7df87fcaba 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java @@ -36,7 +36,7 @@ public TOTPGenerator(String seed) { public TOTPGenerator(String seed, int totpLength, TOTPHashAlgorithm hashAlgorithm, int tokenValidityTimeInSeconds) { if (seed == null) { - throw new IllegalArgumentException("The specified seed must not be null!"); + throw new IllegalArgumentException("The specified TOTP seed must not be null!"); } this.seed = CryptoAccess.CRYPTO_STRING.seal(seed); @@ -48,13 +48,20 @@ public TOTPGenerator(String seed, int totpLength, TOTPHashAlgorithm hashAlgorith } /** - * This method generates a TOTP from the seed (must be raw bytes no encoding) - * and the current time stamp in milliseconds. Make sure encoded seeds like hex, - * base32 or base64 are decoded before passing them to this method. + * This method generates a TOTP for the current times stamp in milliseconds. + * + * @return totp currently valid + */ + public String now() { + return generateTOTP(System.currentTimeMillis()); + } + + /** + * This method generates a TOTP for a time stamp in milliseconds. * * @param seed * @param currentTimeMillis - * @return + * @return totp of give timestamp */ public String generateTOTP(long currentTimeMillis) { byte[] hash = computeHash(currentTimeMillis); diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy index 0f8fdd132d..e4cb516a73 100644 --- a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy @@ -3,7 +3,7 @@ import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator -import org.openqa.selenium.WebDriver +import org.openqa.selenium.firefox.FirefoxDriver import org.openqa.selenium.support.ui.ExpectedConditions import org.openqa.selenium.By import org.openqa.selenium.support.ui.WebDriverWait @@ -12,7 +12,7 @@ import org.openqa.selenium.JavascriptExecutor import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration -final WebDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) +final FirefoxDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) final WebDriverWait webdriverWait = binding.getVariable(FIREFOX_WEBDRIVER_WAIT_KEY) final JavascriptExecutor javaScriptExecutor = binding.getVariable(JAVASCRIPTEXECUTOR_KEY) final SecHubWebScanConfiguration sechubWebScanConfig = binding.getVariable(SECHUB_WEBSCAN_CONFIG_KEY) diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy index 182de33c7e..b6db9d6909 100644 --- a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy @@ -3,7 +3,7 @@ import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator -import org.openqa.selenium.WebDriver +import org.openqa.selenium.firefox.FirefoxDriver import org.openqa.selenium.support.ui.ExpectedConditions import org.openqa.selenium.By import org.openqa.selenium.support.ui.WebDriverWait @@ -12,7 +12,7 @@ import org.openqa.selenium.JavascriptExecutor import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration -final WebDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) +final FirefoxDriver firefox = binding.getVariable(FIREFOX_WEBDRIVER_KEY) final WebDriverWait webdriverWait = binding.getVariable(FIREFOX_WEBDRIVER_WAIT_KEY) final JavascriptExecutor javaScriptExecutor = binding.getVariable(JAVASCRIPTEXECUTOR_KEY) final SecHubWebScanConfiguration sechubWebScanConfig = binding.getVariable(SECHUB_WEBSCAN_CONFIG_KEY) From a29183ba289aa6f5e003f1a79dedd5a2c666429b Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Mon, 18 Nov 2024 13:06:48 +0100 Subject: [PATCH 06/13] Remove static mock parts in tests and create new mocks for each test #3622 --- .../config/ZapScanContextFactoryTest.java | 133 +++-- .../zapwrapper/scan/ZapScannerTest.java | 531 +++++++++--------- .../ZapScriptLoginSessionGrabberTest.java | 96 ++-- .../scan/login/ZapScriptLoginTest.java | 84 +-- 4 files changed, 425 insertions(+), 419 deletions(-) diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index dc33ce4cf8..4fe6c25cde 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -18,7 +18,6 @@ import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mockito; import com.mercedesbenz.sechub.zapwrapper.cli.CommandLineSettings; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; @@ -33,9 +32,8 @@ class ZapScanContextFactoryTest { private ZapScanContextFactory factoryToTest; - private static final EnvironmentVariableReader ENVIRONMENT_VARIABLE_READER = mock(); - - private static final RuleProvider RULE_PROVIDER = mock(); + private EnvironmentVariableReader envVariableReader; + private RuleProvider ruleProvider; private File fullRulesetFile; private File deactivationFile; @@ -45,18 +43,19 @@ class ZapScanContextFactoryTest { @BeforeEach void beforeEach() { - Mockito.reset(ENVIRONMENT_VARIABLE_READER, RULE_PROVIDER); + envVariableReader = mock(); + ruleProvider = mock(); // create object to test - factoryToTest = new ZapScanContextFactory(ENVIRONMENT_VARIABLE_READER, new BaseTargetUriFactory(), RULE_PROVIDER, - new ZapWrapperDataSectionFileSupport(), new SecHubScanConfigProvider(), new IncludeExcludeToZapURLHelper()); + factoryToTest = new ZapScanContextFactory(envVariableReader, new BaseTargetUriFactory(), ruleProvider, new ZapWrapperDataSectionFileSupport(), + new SecHubScanConfigProvider(), new IncludeExcludeToZapURLHelper()); // create test data fullRulesetFile = new File("src/test/resources/zap-available-rules/zap-full-ruleset.json"); deactivationFile = new File("src/test/resources/wrapper-deactivated-rule-examples/zap-rules-to-deactivate.json"); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)).thenReturn(tempDir.getAbsolutePath()); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); + when(envVariableReader.readAsString(PDS_JOB_USER_MESSAGES_FOLDER)).thenReturn(tempDir.getAbsolutePath()); + when(envVariableReader.readAsString(PDS_JOB_EVENTS_FOLDER)).thenReturn(""); } @Test @@ -72,7 +71,7 @@ void context_name_is_used_from_settings_when_defined() { String jobUUID = "12345"; when(settings.getJobUUID()).thenReturn(jobUUID); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -87,7 +86,7 @@ void context_name_is_created_as_UUID_when_not_defined() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getJobUUID()).thenReturn(null); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -109,7 +108,7 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ when(settings.getZapApiKey()).thenReturn(apiKey); when(settings.getProxyHost()).thenReturn(proxy); when(settings.getProxyPort()).thenReturn(proxyPort); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -124,12 +123,12 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ assertEquals(proxy, result.getProxyInformation().getHost()); assertEquals(proxyPort, result.getProxyInformation().getPort()); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); } @ParameterizedTest @@ -139,13 +138,13 @@ void result_contains_server_config_with_arguments_from_environment_when_command_ /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getTargetURL()).thenReturn("https://www.targeturl.com"); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); - when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); - when(ENVIRONMENT_VARIABLE_READER.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(envVariableReader.readAsString(ZAP_HOST_ENV_VARIABLE_NAME)).thenReturn(host); + when(envVariableReader.readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME)).thenReturn(apiKey); + when(envVariableReader.readAsInt(ZAP_PORT_ENV_VARIABLE_NAME)).thenReturn(port); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); - when(ENVIRONMENT_VARIABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); + when(envVariableReader.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); + when(envVariableReader.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -166,10 +165,10 @@ void proxy_set_or_not_is_valid_result_returned_contains_null_as_proxyinformation CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.getProxyHost()).thenReturn(null); when(settings.getProxyPort()).thenReturn(0); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); - when(ENVIRONMENT_VARIABLE_READER.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); + when(envVariableReader.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(null); + when(envVariableReader.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(0); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -191,7 +190,7 @@ void fails_when_host_port_or_apikey_not_in_commandline_and_also_not_in_env(Strin /* prepare */ CommandLineSettings settings = mock(CommandLineSettings.class); when(settings.getZapHost()).thenReturn(host); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); if (port != null) { // when not defined in CSV, null is used. The mock does use int primitive, // so we just do not set it. @@ -216,7 +215,7 @@ void targetURI_calculated_by_factory_is_in_result() { when(settings.getTargetURL()).thenReturn(targetUri); URI createdUri = URI.create("https://fromfactory.example.com"); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -232,7 +231,7 @@ void verbose_from_settings_is_in_result(boolean verboseEnabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isVerboseEnabled()).thenReturn(verboseEnabled); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -248,7 +247,7 @@ void ajaxspider_enabled_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isAjaxSpiderEnabled()).thenReturn(enabled); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -264,7 +263,7 @@ void active_scan_enabled_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isActiveScanEnabled()).thenReturn(enabled); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -280,7 +279,7 @@ void report_file_from_setting_is_used_in_result() { CommandLineSettings settings = createSettingsMockWithNecessaryParts(); Path path = new File("not-existing").toPath(); when(settings.getReportFile()).thenReturn(path); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -300,8 +299,8 @@ void commandline_settings_null_throws_zap_wrapper_runtime_exception() { void fullruleset_returned_by_provider_is_in_result() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - when(RULE_PROVIDER.fetchFullRuleset(fullRulesetFile)).thenReturn(createZapFullRuleset()); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchFullRuleset(fullRulesetFile)).thenReturn(createZapFullRuleset()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -309,7 +308,7 @@ void fullruleset_returned_by_provider_is_in_result() { ZapFullRuleset fullRuleset = result.getFullRuleset(); /* test */ - verify(RULE_PROVIDER, times(1)).fetchFullRuleset(any()); + verify(ruleProvider, times(1)).fetchFullRuleset(any()); assertNotNull(fullRuleset); assertNotNull(fullRuleset.getRules()); assertEquals("https://www.zaproxy.org/docs/alerts/", fullRuleset.getOrigin()); @@ -321,14 +320,14 @@ void fullruleset_returned_by_provider_is_in_result() { void rules_to_deactivate_returned_by_provider_is_inside_result() { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(deactivationFile)).thenReturn(createDeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(deactivationFile)).thenReturn(createDeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); DeactivatedRuleReferences deactivatedRuleReferences = result.getDeactivatedRuleReferences(); /* test */ - verify(RULE_PROVIDER, times(1)).fetchDeactivatedRuleReferences(any()); + verify(ruleProvider, times(1)).fetchDeactivatedRuleReferences(any()); assertNotNull(deactivatedRuleReferences); assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(2, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); @@ -342,8 +341,8 @@ void rules_to_deactivate_returned_by_provider_is_inside_result() { void rules_to_deactivate_returned_by_env_variable_is_inside_result(String value) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - when(ENVIRONMENT_VARIABLE_READER.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(envVariableReader.readAsString(ZAP_DEACTIVATED_RULE_REFERENCES)).thenReturn(value); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); String[] arrayToTestExpectedLength = {}; if (value != null) { @@ -367,7 +366,7 @@ void rules_to_deactivate_returned_by_command_line_parameter_is_inside_result(Str /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getDeactivatedRuleReferences()).thenReturn(value); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); String[] arrayToTestExpectedLength = {}; if (value != null) { @@ -383,7 +382,7 @@ void rules_to_deactivate_returned_by_command_line_parameter_is_inside_result(Str assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(arrayToTestExpectedLength.length, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(envVariableReader, never()).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @ParameterizedTest @@ -392,60 +391,60 @@ void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_r /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getDeactivatedRuleReferences()).thenReturn(value); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(envVariableReader, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @Test void api_definition_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File( "src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(envVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(envVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(1, result.getApiDefinitionFiles().size()); } @Test void client_certificate_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/client-certificate-auth.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(envVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(envVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertNotNull(result.getClientCertificateFile()); } @Test void includes_and_excludes_from_sechub_json_are_inside_result() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/no-auth-include-exclude.json"); @@ -463,7 +462,7 @@ void includes_and_excludes_from_sechub_json_are_inside_result() { @Test void includes_and_excludes_empty_from_sechub_json_result_in_empty_exclude_and_target_url_as_single_include() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File( @@ -486,7 +485,7 @@ void connection_check_from_settings_is_in_result(boolean enabled) { /* prepare */ CommandLineSettings settings = createSettingsMockWithNecessaryParts(); when(settings.isConnectionCheckEnabled()).thenReturn(enabled); - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ ZapScanContext result = factoryToTest.create(settings); @@ -499,20 +498,20 @@ void connection_check_from_settings_is_in_result(boolean enabled) { @Test void header_config_file_from_sechub_scan_config_is_inside_result() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File("src/test/resources/sechub-config-examples/header-config.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(envVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(envVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(2, result.getHeaderValueFiles().size()); assertEquals(extractedSourcesPath + "/header-token.txt", result.getHeaderValueFiles().get("Key").toString()); assertEquals(extractedSourcesPath + "/token.txt", result.getHeaderValueFiles().get("Other").toString()); @@ -521,74 +520,74 @@ void header_config_file_from_sechub_scan_config_is_inside_result() { @Test void header_config_without_data_section_no_file_is_inside_result() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); File sechubScanConfigFile = new File( "src/test/resources/sechub-config-examples/header-config-without-data-section.json"); String extractedSourcesPath = "path/to/extracted/sources"; when(settings.getSecHubConfigFile()).thenReturn(sechubScanConfigFile); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) + when(envVariableReader.readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER)) .thenReturn(extractedSourcesPath); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); + verify(envVariableReader, atLeast(1)).readAsString(PDS_JOB_EXTRACTED_SOURCES_FOLDER); assertEquals(0, result.getHeaderValueFiles().size()); } @Test void no_template_data_results_in_no_template_data_set() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); when(settings.getTemplateFolder()).thenReturn(null); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(PDS_TEMPLATE_FOLDER); + verify(envVariableReader, times(1)).readAsString(PDS_TEMPLATE_FOLDER); assertNull(result.getGroovyScriptLoginFile()); } @Test void cmd_param_set_results_in_environment_variable_reader_not_being_called() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); String templateDir = "templateDir"; when(settings.getTemplateFolder()).thenReturn(templateDir); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, never()).readAsString(PDS_TEMPLATE_FOLDER); + verify(envVariableReader, never()).readAsString(PDS_TEMPLATE_FOLDER); assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); } @Test void cmd_param_not_set_results_in_environment_variable_reader_being_called_as_fallback() { /* prepare */ - when(RULE_PROVIDER.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); + when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); String templateDir = "templateDir"; when(settings.getTemplateFolder()).thenReturn(null); - when(ENVIRONMENT_VARIABLE_READER.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(templateDir); + when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(templateDir); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(ENVIRONMENT_VARIABLE_READER, times(1)).readAsString(PDS_TEMPLATE_FOLDER); + verify(envVariableReader, times(1)).readAsString(PDS_TEMPLATE_FOLDER); assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java index a2855d7b04..0fab91ec18 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java @@ -20,7 +20,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mockito; import org.zaproxy.clientapi.core.ApiResponse; import org.zaproxy.clientapi.core.ClientApiException; @@ -54,77 +53,77 @@ class ZapScannerTest { private ZapScanner scannerToTest; - private static final ClientApiSupport CLIENT_API_SUPPORT = mock(); - private static final ZapScanContext SCAN_CONTEXT = mock(); - private static final ZapPDSEventHandler ZAP_PDS_EVENT_HANDLER = mock(); - private static final SystemUtil SYSTEM_UTIL = mock(); - private static final ZapScriptLogin SCRIPT_LOGIN = mock(); - private static final ZapProductMessageHelper MESSAGE_HELPER = mock(); + private ClientApiSupport clientApiSupport; + private ZapScanContext scanContext; + private ZapPDSEventHandler zapPDSEventHandler; + private SystemUtil systemUtil; + private ZapScriptLogin scriptLogin; + private ZapProductMessageHelper messageHelper; - private static final ApiResponse RESPONSE = mock(); + private ApiResponse apiResponse; private static final String BROWSER_ID = ZAPAcceptedBrowserId.FIREFOX_HEADLESS.getBrowserId(); private static final String CONTEXT_NAME = "context-name"; @BeforeEach void beforeEach() { - // Reset mocks - /* @formatter:off */ - Mockito.reset(CLIENT_API_SUPPORT, - SCAN_CONTEXT, - ZAP_PDS_EVENT_HANDLER, - SYSTEM_UTIL, - SCRIPT_LOGIN, - MESSAGE_HELPER); - /* @formatter:on */ + clientApiSupport = mock(); + scanContext = mock(); + zapPDSEventHandler = mock(); + systemUtil = mock(); + scriptLogin = mock(); + messageHelper = mock(); + + apiResponse = mock(); // create scanner to test /* @formatter:off */ - scannerToTest = new ZapScanner(CLIENT_API_SUPPORT, - SCAN_CONTEXT, + scannerToTest = new ZapScanner(clientApiSupport, + scanContext, new ScanDurationHelper(), new UrlUtil(), - SYSTEM_UTIL, SCRIPT_LOGIN); + systemUtil, + scriptLogin); /* @formatter:on */ // set global behavior - when(SCAN_CONTEXT.getContextName()).thenReturn(CONTEXT_NAME); - when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(MESSAGE_HELPER); - when(SCAN_CONTEXT.getZapPDSEventHandler()).thenReturn(ZAP_PDS_EVENT_HANDLER); - when(SCAN_CONTEXT.getAjaxSpiderBrowserId()).thenReturn(BROWSER_ID); + when(scanContext.getContextName()).thenReturn(CONTEXT_NAME); + when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); + when(scanContext.getZapPDSEventHandler()).thenReturn(zapPDSEventHandler); + when(scanContext.getAjaxSpiderBrowserId()).thenReturn(BROWSER_ID); - when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("authSessionId"); - doNothing().when(SCRIPT_LOGIN).cleanUpScriptLoginData(anyString(), eq(CLIENT_API_SUPPORT)); + when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("authSessionId"); + doNothing().when(scriptLogin).cleanUpScriptLoginData(anyString(), eq(clientApiSupport)); - doNothing().when(MESSAGE_HELPER).writeProductError(any()); - doNothing().when(MESSAGE_HELPER).writeProductMessages(any()); - doNothing().when(MESSAGE_HELPER).writeSingleProductMessage(any()); + doNothing().when(messageHelper).writeProductError(any()); + doNothing().when(messageHelper).writeProductMessages(any()); + doNothing().when(messageHelper).writeSingleProductMessage(any()); - doNothing().when(SYSTEM_UTIL).waitForMilliseconds(anyInt()); - when(SYSTEM_UTIL.getCurrentTimeInMilliseconds()).thenCallRealMethod(); + doNothing().when(systemUtil).waitForMilliseconds(anyInt()); + when(systemUtil.getCurrentTimeInMilliseconds()).thenCallRealMethod(); - doNothing().when(SCRIPT_LOGIN).cleanUpScriptLoginData(any(), eq(CLIENT_API_SUPPORT)); + doNothing().when(scriptLogin).cleanUpScriptLoginData(any(), eq(clientApiSupport)); } @Test void setup_standard_configuration_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(CLIENT_API_SUPPORT.createNewSession(SCAN_CONTEXT.getContextName(), "true")).thenReturn(null); - when(CLIENT_API_SUPPORT.configureMaximumAlertsForEachRule("0")).thenReturn(null); - when(CLIENT_API_SUPPORT.enableAllPassiveScannerRules()).thenReturn(null); - when(CLIENT_API_SUPPORT.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); - when(CLIENT_API_SUPPORT.setAjaxSpiderBrowserId(BROWSER_ID)) + when(clientApiSupport.createNewSession(scanContext.getContextName(), "true")).thenReturn(null); + when(clientApiSupport.configureMaximumAlertsForEachRule("0")).thenReturn(null); + when(clientApiSupport.enableAllPassiveScannerRules()).thenReturn(null); + when(clientApiSupport.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); + when(clientApiSupport.setAjaxSpiderBrowserId(BROWSER_ID)) .thenReturn(null); /* execute */ scannerToTest.setupStandardConfiguration(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).createNewSession(SCAN_CONTEXT.getContextName(), "true"); - verify(CLIENT_API_SUPPORT, times(1)).configureMaximumAlertsForEachRule("0"); - verify(CLIENT_API_SUPPORT, times(1)).enableAllPassiveScannerRules(); - verify(CLIENT_API_SUPPORT, times(1)).enableAllActiveScannerRulesForPolicy(null); - verify(CLIENT_API_SUPPORT, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); + verify(clientApiSupport, times(1)).createNewSession(scanContext.getContextName(), "true"); + verify(clientApiSupport, times(1)).configureMaximumAlertsForEachRule("0"); + verify(clientApiSupport, times(1)).enableAllPassiveScannerRules(); + verify(clientApiSupport, times(1)).enableAllActiveScannerRulesForPolicy(null); + verify(clientApiSupport, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); } @Test @@ -140,8 +139,8 @@ void deactivate_rules_ruleset_or_rules_to_deactivate_null_results_in_nothing_is_ scannerToTest.deactivateRules(new ZapFullRuleset(), deactivatedReferences); /* test */ - verify(CLIENT_API_SUPPORT, never()).disablePassiveScannerRule(any()); - verify(CLIENT_API_SUPPORT, never()).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiSupport, never()).disablePassiveScannerRule(any()); + verify(clientApiSupport, never()).disableActiveScannerRuleForPolicy(any(), any()); } @Test @@ -157,28 +156,28 @@ void deactivate_rules_results_in_rules_are_deactivated() throws ClientApiExcepti String json = TestFileReader.readTextFromFile("src/test/resources/zap-available-rules/zap-full-ruleset.json"); ZapFullRuleset ruleSet = new ZapFullRuleset().fromJSON(json); - when(CLIENT_API_SUPPORT.disablePassiveScannerRule(any())).thenReturn(null); - when(CLIENT_API_SUPPORT.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); + when(clientApiSupport.disablePassiveScannerRule(any())).thenReturn(null); + when(clientApiSupport.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); /* execute */ scannerToTest.deactivateRules(ruleSet, deactivatedReferences); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).disablePassiveScannerRule(any()); - verify(CLIENT_API_SUPPORT, times(2)).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiSupport, times(1)).disablePassiveScannerRule(any()); + verify(clientApiSupport, times(2)).disableActiveScannerRuleForPolicy(any(), any()); } @Test void setup_addtional_proxy_information_with_proxy_information_null_results_in_proxy_disabled() throws ClientApiException { /* prepare */ - when(CLIENT_API_SUPPORT.setHttpProxyEnabled("false")).thenReturn(null); + when(clientApiSupport.setHttpProxyEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(null); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyEnabled("false"); + verify(clientApiSupport, times(1)).setHttpProxyEnabled("false"); } @Test @@ -189,47 +188,47 @@ void setup_addtional_proxy_information_results_in_proxy_enabled() throws ClientA var portAsString = String.valueOf(port); ProxyInformation proxyInformation = new ProxyInformation(host, port); - when(CLIENT_API_SUPPORT.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); - when(CLIENT_API_SUPPORT.setHttpProxyEnabled("true")).thenReturn(null); - when(CLIENT_API_SUPPORT.setHttpProxyAuthEnabled("false")).thenReturn(null); + when(clientApiSupport.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); + when(clientApiSupport.setHttpProxyEnabled("true")).thenReturn(null); + when(clientApiSupport.setHttpProxyAuthEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(proxyInformation); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).configureHttpProxy(host, portAsString, null, null, null); - verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyEnabled("true"); - verify(CLIENT_API_SUPPORT, times(1)).setHttpProxyAuthEnabled("false"); + verify(clientApiSupport, times(1)).configureHttpProxy(host, portAsString, null, null, null); + verify(clientApiSupport, times(1)).setHttpProxyEnabled("true"); + verify(clientApiSupport, times(1)).setHttpProxyAuthEnabled("false"); } @Test void create_context_results_in_expected_calls() throws ClientApiException { /* prepare */ String expectedContextId = "random-id"; - when(CLIENT_API_SUPPORT.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); + when(clientApiSupport.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); /* execute */ String contextId = scannerToTest.createContext(); /* test */ assertEquals(expectedContextId, contextId); - verify(SCAN_CONTEXT, times(2)).getContextName(); - verify(CLIENT_API_SUPPORT, times(1)).createNewContext(CONTEXT_NAME); + verify(scanContext, times(2)).getContextName(); + verify(clientApiSupport, times(1)).createNewContext(CONTEXT_NAME); } @Test void add_replacer_rules_for_headers_with_no_headers_results_add_replacer_rule_is_never_called() throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(CLIENT_API_SUPPORT, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiSupport, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -238,16 +237,16 @@ void add_replacer_rules_for_headers_with_no_onlyForUrls_results_add_replacer_rul throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(CLIENT_API_SUPPORT, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiSupport, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -256,9 +255,9 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); @@ -271,7 +270,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i times += header.getOnlyForUrls().get().size() - 1; } } - verify(CLIENT_API_SUPPORT, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiSupport, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @Test @@ -309,21 +308,21 @@ void add_replacer_rules_for_headers_with_data_section_results_add_replacer_rule_ """; SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubConfigWithfilesystemPartHasMoreThanOneFile).getWebScan() .get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); Map headerFiles = new HashMap<>(); headerFiles.put("Key", new File("src/test/resources/header-value-files/header-token.txt")); headerFiles.put("Other", new File("src/test/resources/header-value-files/token.txt")); - when(SCAN_CONTEXT.getHeaderValueFiles()).thenReturn(headerFiles); + when(scanContext.getHeaderValueFiles()).thenReturn(headerFiles); - when(CLIENT_API_SUPPORT.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); - verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); + verify(clientApiSupport, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); + verify(clientApiSupport, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); } @ParameterizedTest @@ -339,15 +338,15 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o URL targetUrl = sechubWebScanConfig.getUrl().toURL(); List includesList = sechubWebScanConfig.getIncludes().get(); Set includes = new HashSet<>(helper.createListOfUrls(targetUrl, includesList)); - when(SCAN_CONTEXT.getZapURLsIncludeSet()).thenReturn(includes); + when(scanContext.getZapURLsIncludeSet()).thenReturn(includes); List excludesList = sechubWebScanConfig.getExcludes().get(); Set excludes = new HashSet<>(helper.createListOfUrls(targetUrl, excludesList)); - when(SCAN_CONTEXT.getZapURLsExcludeSet()).thenReturn(excludes); + when(scanContext.getZapURLsExcludeSet()).thenReturn(excludes); - when(CLIENT_API_SUPPORT.addIncludeUrlPatternToContext(any(), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.accessUrlViaZap(any(), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.addExcludeUrlPatternToContext(any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.addIncludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); + when(clientApiSupport.accessUrlViaZap(any(), any())).thenReturn(apiResponse); + when(clientApiSupport.addExcludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); /* @formatter:off */ int includesWithoutWildcards = (int) includes.stream() @@ -359,10 +358,10 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o scannerToTest.addIncludedAndExcludedUrlsToContext(); /* test */ - verify(CLIENT_API_SUPPORT, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); + verify(clientApiSupport, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); // make sure this method is only called for includes without wildcards - verify(CLIENT_API_SUPPORT, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); - verify(CLIENT_API_SUPPORT, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); + verify(clientApiSupport, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); + verify(clientApiSupport, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); } @Test @@ -370,16 +369,16 @@ void import_openapi_file_but_api_file_is_null_api_support_is_never_called() thro /* prepare */ String contextId = "context-id"; - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); - when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(RESPONSE); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); + when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiSupport.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); - verify(CLIENT_API_SUPPORT, never()).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiSupport, never()).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @@ -393,16 +392,16 @@ void import_openapi_file_api_support_is_called_once(String sechubConfigFile) thr List apiFiles = new ArrayList<>(); apiFiles.add(new File("openapi3.json")); - when(SCAN_CONTEXT.getApiDefinitionFiles()).thenReturn(apiFiles); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).importOpenApiFile(any(), any(), any()); + verify(clientApiSupport, times(1)).importOpenApiFile(any(), any(), any()); } @ParameterizedTest @@ -412,17 +411,17 @@ void import_openapi_defintion_from_url_api_support_is_called_once(String sechubC String contextId = "context-id"; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiSupport.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); - verify(CLIENT_API_SUPPORT, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiSupport, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @@ -436,29 +435,29 @@ void import_openapi_from_file_and_from_url_api_support_is_called_once(String sec List apiFiles = new ArrayList<>(); apiFiles.add(new File("openapi3.json")); - when(SCAN_CONTEXT.getApiDefinitionFiles()).thenReturn(apiFiles); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.importOpenApiFile(any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).importOpenApiFile(any(), any(), any()); - verify(CLIENT_API_SUPPORT, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiSupport, times(1)).importOpenApiFile(any(), any(), any()); + verify(clientApiSupport, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @Test void import_client_certificate_file_but_client_certificate_file_is_null_api_support_is_never_called() throws ClientApiException { /* prepare */ - when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(CLIENT_API_SUPPORT, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); } @Test @@ -477,16 +476,16 @@ void try_import_without_client_certificate_file_api_support_is_never_called() th File clientCertificateFile = new File("backend-cert.p12"); - when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(CLIENT_API_SUPPORT, never()).importPkcs12ClientCertificate(any(), any()); + verify(clientApiSupport, never()).importPkcs12ClientCertificate(any(), any()); } @Test @@ -510,18 +509,18 @@ void import_client_certificate_file_api_support_is_called_once() throws ClientAp File clientCertificateFile = mock(File.class); - when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(clientCertificateFile.exists()).thenReturn(true); - when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiSupport, times(1)).importPkcs12ClientCertificate(any(), any()); } @Test @@ -544,17 +543,17 @@ void import_client_certificate_file_but_without_password_api_support_is_called_o File clientCertificateFile = mock(File.class); - when(SCAN_CONTEXT.getClientCertificateFile()).thenReturn(clientCertificateFile); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(clientCertificateFile.exists()).thenReturn(true); - when(CLIENT_API_SUPPORT.importPkcs12ClientCertificate(any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiSupport, times(1)).importPkcs12ClientCertificate(any(), any()); } @ParameterizedTest @@ -566,7 +565,7 @@ void configure_login_inside_zap_using_no_auth_and_unsupported_auth_return_null(S String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); @@ -589,15 +588,15 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr String zapAuthenticationMethod = AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); String zapSessionManagementMethod = SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getTargetUrl()).thenReturn(targetUrl); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); - when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); + when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); @@ -606,14 +605,14 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr assertEquals(userName, userInformation.userName()); assertEquals(userId, userInformation.zapuserId()); - verify(SCAN_CONTEXT, times(2)).getTargetUrl(); + verify(scanContext, times(2)).getTargetUrl(); - verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(CLIENT_API_SUPPORT, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); - verify(CLIENT_API_SUPPORT, times(1)).createNewUser(contextId, userName); - verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(CLIENT_API_SUPPORT, times(1)).setForcedUser(contextId, userId); - verify(CLIENT_API_SUPPORT, times(1)).setForcedUserModeEnabled(true); + verify(clientApiSupport, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiSupport, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiSupport, times(1)).createNewUser(contextId, userName); + verify(clientApiSupport, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiSupport, times(1)).setForcedUser(contextId, userId); + verify(clientApiSupport, times(1)).setForcedUserModeEnabled(true); } @Test @@ -631,26 +630,26 @@ void configure_login_inside_zap_using_script_auth_without_script_file_results_in String zapAuthenticationMethod = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("zap-auth-session"); + when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("zap-auth-session"); - when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(SCAN_CONTEXT.getGroovyScriptLoginFile()).thenReturn(null); + when(scanContext.getTargetUrl()).thenReturn(targetUrl); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getGroovyScriptLoginFile()).thenReturn(null); - when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); - when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); + when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); /* test */ assertNull(userInformation); - verify(SCRIPT_LOGIN, never()).login(SCAN_CONTEXT, CLIENT_API_SUPPORT); - verify(SCAN_CONTEXT, times(1)).getGroovyScriptLoginFile(); + verify(scriptLogin, never()).login(scanContext, clientApiSupport); + verify(scanContext, times(1)).getGroovyScriptLoginFile(); } @Test @@ -669,18 +668,18 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); - when(SCRIPT_LOGIN.login(SCAN_CONTEXT, CLIENT_API_SUPPORT)).thenReturn("zap-auth-session"); + when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("zap-auth-session"); - when(SCAN_CONTEXT.getTargetUrl()).thenReturn(targetUrl); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(SCAN_CONTEXT.getGroovyScriptLoginFile()).thenReturn(scriptFile); + when(scanContext.getTargetUrl()).thenReturn(targetUrl); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getGroovyScriptLoginFile()).thenReturn(scriptFile); - when(CLIENT_API_SUPPORT.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.createNewUser(contextId, userName)).thenReturn(userId); - when(CLIENT_API_SUPPORT.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUser(contextId, userId)).thenReturn(RESPONSE); - when(CLIENT_API_SUPPORT.setForcedUserModeEnabled(true)).thenReturn(RESPONSE); + when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); @@ -689,31 +688,31 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu assertEquals(userName, userInformation.userName()); assertEquals(userId, userInformation.zapuserId()); - verify(SCRIPT_LOGIN, times(1)).login(SCAN_CONTEXT, CLIENT_API_SUPPORT); - verify(SCAN_CONTEXT, times(2)).getGroovyScriptLoginFile(); + verify(scriptLogin, times(1)).login(scanContext, clientApiSupport); + verify(scanContext, times(2)).getGroovyScriptLoginFile(); - verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(CLIENT_API_SUPPORT, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); - verify(CLIENT_API_SUPPORT, times(1)).createNewUser(contextId, userName); - verify(CLIENT_API_SUPPORT, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(CLIENT_API_SUPPORT, times(1)).setForcedUser(contextId, userId); - verify(CLIENT_API_SUPPORT, times(1)).setForcedUserModeEnabled(true); + verify(clientApiSupport, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiSupport, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiSupport, times(1)).createNewUser(contextId, userName); + verify(clientApiSupport, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiSupport, times(1)).setForcedUser(contextId, userId); + verify(clientApiSupport, times(1)).setForcedUserModeEnabled(true); } @Test void generate_report_calls_api_support_once() throws ClientApiException { /* prepare */ - when(SCAN_CONTEXT.getReportFile()) + when(scanContext.getReportFile()) .thenReturn(Paths.get("src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json")); - when(CLIENT_API_SUPPORT.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), - any(), any(), any())).thenReturn(RESPONSE); + when(clientApiSupport.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), + any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.generateZapReport(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), + verify(clientApiSupport, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); } @@ -721,15 +720,15 @@ void generate_report_calls_api_support_once() throws ClientApiException { void cleanup_after_scan() throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); + when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); /* test */ - verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); } @ParameterizedTest @@ -737,18 +736,18 @@ void cleanup_after_scan() throws ClientApiException { void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_rules(String sechubScanConfigJSON) throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); + when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(CLIENT_API_SUPPORT, times(times + 1)).removeReplacerRule(any()); - verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiSupport, times(times + 1)).removeReplacerRule(any()); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); } @ParameterizedTest @@ -756,9 +755,9 @@ void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_r void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rules(String sechubScanConfigJSON) throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); - when(SCAN_CONTEXT.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); + when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(CLIENT_API_SUPPORT.removeReplacerRule(any())).thenReturn(RESPONSE); + when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); @@ -771,22 +770,22 @@ void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rule times += header.getOnlyForUrls().get().size() - 1; } } - verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(CLIENT_API_SUPPORT, times(times + 1)).removeReplacerRule(any()); - verify(SCRIPT_LOGIN, times(1)).cleanUpScriptLoginData(SCAN_CONTEXT.getTargetUrlAsString(), CLIENT_API_SUPPORT); + verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiSupport, times(times + 1)).removeReplacerRule(any()); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); } @Test void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { /* prepare */ - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); long scanDuration = 20000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); + when(clientApiSupport.stopAjaxSpider()).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -795,29 +794,29 @@ void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_e /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); + verify(zapPDSEventHandler, times(2)).isScanCancelled(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(clientApiSupport, times(1)).stopAjaxSpider(); } @Test void wait_for_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); long scanDuration = 1000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); - when(CLIENT_API_SUPPORT.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiSupport.stopAjaxSpider()).thenReturn(null); + when(clientApiSupport.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ scannerToTest.waitForAjaxSpiderResults(scanDuration); /* test */ - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(CLIENT_API_SUPPORT, atLeast(1)).getAjaxSpiderStatus(); - verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(clientApiSupport, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiSupport, times(1)).stopAjaxSpider(); } @Test @@ -825,13 +824,13 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ /* prepare */ String scanId = "12345"; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); long scanDuration = 20000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -840,9 +839,9 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); + verify(zapPDSEventHandler, times(2)).isScanCancelled(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(clientApiSupport, times(1)).stopSpiderScan(scanId); } @Test @@ -850,39 +849,39 @@ void wait_for_spider_scan_ended_results_in_expected_calls() throws ClientApiExce /* prepare */ String scanId = "12345"; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); long scanDuration = 1000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); - when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(messageHelper); + when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); - when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); - when(CLIENT_API_SUPPORT.getSpiderStatusForScan(scanId)).thenReturn(42); - when(CLIENT_API_SUPPORT.logFullSpiderResults(scanId)).thenReturn(0L); + when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiSupport.getSpiderStatusForScan(scanId)).thenReturn(42); + when(clientApiSupport.logFullSpiderResults(scanId)).thenReturn(0L); /* execute */ scannerToTest.waitForSpiderResults(scanId, scanDuration); /* test */ - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(SCAN_CONTEXT, times(1)).getZapProductMessageHelper(); - verify(CLIENT_API_SUPPORT, atLeast(1)).getSpiderStatusForScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).logFullSpiderResults(scanId); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(scanContext, times(1)).getZapProductMessageHelper(); + verify(clientApiSupport, atLeast(1)).getSpiderStatusForScan(scanId); + verify(clientApiSupport, times(1)).stopSpiderScan(scanId); + verify(clientApiSupport, times(1)).logFullSpiderResults(scanId); } @Test void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { /* prepare */ - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); long scanDuration = 20000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(false); - when(SCAN_CONTEXT.isAjaxSpiderEnabled()).thenReturn(false); + when(scanContext.isActiveScanEnabled()).thenReturn(false); + when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); - when(CLIENT_API_SUPPORT.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); + when(clientApiSupport.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -891,30 +890,30 @@ void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_ /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(SCAN_CONTEXT, times(1)).isAjaxSpiderEnabled(); - verify(CLIENT_API_SUPPORT, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(zapPDSEventHandler, times(2)).isScanCancelled(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(scanContext, times(1)).isAjaxSpiderEnabled(); + verify(clientApiSupport, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); long scanDuration = 20000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(false); - when(SCAN_CONTEXT.isAjaxSpiderEnabled()).thenReturn(false); + when(scanContext.isActiveScanEnabled()).thenReturn(false); + when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); - when(CLIENT_API_SUPPORT.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); + when(clientApiSupport.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); /* execute */ scannerToTest.passiveScan(scanDuration); /* test */ - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(SCAN_CONTEXT, times(1)).isAjaxSpiderEnabled(); - verify(CLIENT_API_SUPPORT, times(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(scanContext, times(1)).isAjaxSpiderEnabled(); + verify(clientApiSupport, times(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test @@ -923,11 +922,11 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e String scanId = "12345"; long scanDuration = 20000L; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(true); - doCallRealMethod().when(ZAP_PDS_EVENT_HANDLER).cancelScan(CONTEXT_NAME); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); + doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); - when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(42); - when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); + when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(42); + when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -936,9 +935,9 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); - verify(ZAP_PDS_EVENT_HANDLER, times(2)).isScanCancelled(); - verify(CLIENT_API_SUPPORT, never()).getActiveScannerStatusForScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); + verify(zapPDSEventHandler, times(2)).isScanCancelled(); + verify(clientApiSupport, never()).getActiveScannerStatusForScan(scanId); + verify(clientApiSupport, times(1)).stopActiveScan(scanId); } @Test @@ -947,37 +946,37 @@ void wait_for_activeScan_scan_is_ended_results_in_expected_calls() throws Client String scanId = "12345"; long scanDuration = 20000L; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); + when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); /* execute */ scannerToTest.waitForActiveScanResults(scanId, scanDuration); /* test */ - verify(CLIENT_API_SUPPORT, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); + verify(clientApiSupport, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(clientApiSupport, times(1)).stopActiveScan(scanId); } @Test void run_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); long scanDuration = 1000L; - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(CLIENT_API_SUPPORT.stopAjaxSpider()).thenReturn(null); - when(CLIENT_API_SUPPORT.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiSupport.stopAjaxSpider()).thenReturn(null); + when(clientApiSupport.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ scannerToTest.runAjaxSpider(scanDuration); /* test */ - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(CLIENT_API_SUPPORT, atLeast(1)).getAjaxSpiderStatus(); - verify(CLIENT_API_SUPPORT, times(1)).stopAjaxSpider(); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(clientApiSupport, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiSupport, times(1)).stopAjaxSpider(); } @Test @@ -986,27 +985,27 @@ void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException String scanId = "12345"; long scanDuration = 1000L; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(SCAN_CONTEXT.isActiveScanEnabled()).thenReturn(true); + when(scanContext.isActiveScanEnabled()).thenReturn(true); ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); - when(SCAN_CONTEXT.getZapProductMessageHelper()).thenReturn(messageHelper); + when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); - when(CLIENT_API_SUPPORT.stopSpiderScan(scanId)).thenReturn(null); - when(CLIENT_API_SUPPORT.getSpiderStatusForScan(scanId)).thenReturn(42); - when(CLIENT_API_SUPPORT.logFullSpiderResults(scanId)).thenReturn(0L); - when(CLIENT_API_SUPPORT.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiSupport.getSpiderStatusForScan(scanId)).thenReturn(42); + when(clientApiSupport.logFullSpiderResults(scanId)).thenReturn(0L); + when(clientApiSupport.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); /* execute */ scannerToTest.runSpider(scanDuration); /* test */ - verify(SCAN_CONTEXT, times(1)).isActiveScanEnabled(); - verify(SCAN_CONTEXT, times(1)).getZapProductMessageHelper(); - verify(CLIENT_API_SUPPORT, atLeast(1)).getSpiderStatusForScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).stopSpiderScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).logFullSpiderResults(scanId); - verify(CLIENT_API_SUPPORT, times(1)).startSpiderScan(any(), any(), any(), any(), any()); + verify(scanContext, times(1)).isActiveScanEnabled(); + verify(scanContext, times(1)).getZapProductMessageHelper(); + verify(clientApiSupport, atLeast(1)).getSpiderStatusForScan(scanId); + verify(clientApiSupport, times(1)).stopSpiderScan(scanId); + verify(clientApiSupport, times(1)).logFullSpiderResults(scanId); + verify(clientApiSupport, times(1)).startSpiderScan(any(), any(), any(), any(), any()); } @Test @@ -1016,20 +1015,20 @@ void run_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiEx long scanDuration = 20000L; - when(ZAP_PDS_EVENT_HANDLER.isScanCancelled()).thenReturn(false); + when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(CLIENT_API_SUPPORT.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(CLIENT_API_SUPPORT.stopActiveScan(scanId)).thenReturn(null); - when(CLIENT_API_SUPPORT.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); - when(CLIENT_API_SUPPORT.atLeastOneURLDetected()).thenReturn(true); + when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); + when(clientApiSupport.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiSupport.atLeastOneURLDetected()).thenReturn(true); /* execute */ scannerToTest.runActiveScan(scanDuration); /* test */ - verify(CLIENT_API_SUPPORT, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).stopActiveScan(scanId); - verify(CLIENT_API_SUPPORT, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); + verify(clientApiSupport, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(clientApiSupport, times(1)).stopActiveScan(scanId); + verify(clientApiSupport, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); } static Stream headerPartWithoutOnlyForUrlsTestNamedArguments() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java index 6aef545162..7b79b39526 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java @@ -11,7 +11,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.openqa.selenium.Cookie; @@ -26,24 +25,29 @@ class ZapScriptLoginSessionGrabberTest { private ZapScriptLoginSessionGrabber sessionGrabberToTest; - private static final ClientApiSupport CLIENT_API_SUPPORT = mock(ClientApiSupport.class, new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - // Return the same response for any method call - return ZAP_API_RESPONSE; - } - }); - private static final FirefoxDriver FIREFOX = mock(); - private static final Options WEBDRIVER_OPTIONS = mock(); + private ClientApiSupport clientApiSupport; + private FirefoxDriver firefox; + private Options webDriverOptions; - private static final ApiResponse ZAP_API_RESPONSE = mock(); + private ApiResponse zapApiResponse; private static final String TARGET_URL = "http://example.com"; private static final String FOLLOW_REDIRECTS = "true"; @BeforeEach void beforeEach() { - Mockito.reset(CLIENT_API_SUPPORT, FIREFOX, WEBDRIVER_OPTIONS); + zapApiResponse = mock(); + firefox = mock(); + webDriverOptions = mock(); + + clientApiSupport = mock(ClientApiSupport.class, new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + // Return the same response for any method call + return zapApiResponse; + } + }); + sessionGrabberToTest = new ZapScriptLoginSessionGrabber(); } @@ -58,62 +62,62 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE storage.put("jwt", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); - when(FIREFOX.manage()).thenReturn(WEBDRIVER_OPTIONS); + when(firefox.manage()).thenReturn(webDriverOptions); - when(WEBDRIVER_OPTIONS.getCookies()).thenReturn(cookies); - when(FIREFOX.executeScript(anyString())).thenReturn(storage); + when(webDriverOptions.getCookies()).thenReturn(cookies); + when(firefox.executeScript(anyString())).thenReturn(storage); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(FIREFOX, TARGET_URL, CLIENT_API_SUPPORT); + sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiSupport); /* test */ - verify(FIREFOX, times(1)).manage(); - verify(WEBDRIVER_OPTIONS, times(1)).getCookies(); - verify(FIREFOX, times(1)).executeScript(anyString()); - - verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(any()); - verify(CLIENT_API_SUPPORT, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); - verify(CLIENT_API_SUPPORT, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); - - verify(CLIENT_API_SUPPORT, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(firefox, times(1)).manage(); + verify(webDriverOptions, times(1)).getCookies(); + verify(firefox, times(1)).executeScript(anyString()); + + verify(clientApiSupport, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).removeReplacerRule(any()); + verify(clientApiSupport, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); + verify(clientApiSupport, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + + verify(clientApiSupport, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } @Test void no_cookie_and_no_jwt_results_clienapisupport_not_adding_replacer_rule() throws ClientApiException { /* prepare */ - when(FIREFOX.manage()).thenReturn(WEBDRIVER_OPTIONS); + when(firefox.manage()).thenReturn(webDriverOptions); - when(WEBDRIVER_OPTIONS.getCookies()).thenReturn(Collections.emptySet()); - when(FIREFOX.executeScript(anyString())).thenReturn(Collections.emptyMap()); + when(webDriverOptions.getCookies()).thenReturn(Collections.emptySet()); + when(firefox.executeScript(anyString())).thenReturn(Collections.emptyMap()); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(FIREFOX, TARGET_URL, CLIENT_API_SUPPORT); + sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiSupport); /* test */ // both browser storages are checked now without JWT - verify(FIREFOX, times(2)).executeScript(anyString()); + verify(firefox, times(2)).executeScript(anyString()); // no JWT can be added - verify(CLIENT_API_SUPPORT, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiSupport, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); // no cookie can be added - verify(CLIENT_API_SUPPORT, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); + verify(clientApiSupport, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); // the other calls must be the same as on every execution without error - verify(FIREFOX, times(1)).manage(); - verify(WEBDRIVER_OPTIONS, times(1)).getCookies(); + verify(firefox, times(1)).manage(); + verify(webDriverOptions, times(1)).getCookies(); - verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).removeReplacerRule(any()); - verify(CLIENT_API_SUPPORT, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).removeReplacerRule(any()); + verify(clientApiSupport, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiSupport, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(CLIENT_API_SUPPORT, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(clientApiSupport, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java index 68a1212563..f5a54fc763 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java @@ -15,7 +15,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; import org.openqa.selenium.firefox.FirefoxDriver; import org.zaproxy.clientapi.core.ClientApiException; @@ -31,17 +30,22 @@ class ZapScriptLoginTest { private ZapScriptLogin scriptLoginToTest; - private static final ZapScriptLoginWebDriverFactory WEB_DRIVER_FACTORY = mock(); - private static final ZapWrapperGroovyScriptExecutor GROOVY_SCRIPT_EXECUTOR = mock(); - private static final ZapScriptLoginSessionGrabber SESSION_GRABBER = mock(); + private ZapScriptLoginWebDriverFactory webDriverFactory = mock(); + private ZapWrapperGroovyScriptExecutor groovyScriptExecutor = mock(); + private ZapScriptLoginSessionGrabber sessionGrabber = mock(); - private static final ClientApiSupport CLIENT_API_SUPPORT = mock(); - private static final FirefoxDriver FIREFOX = mock(); + private ClientApiSupport clientApiSupport = mock(); + private FirefoxDriver firefox = mock(); @BeforeEach void beforeEach() { - Mockito.reset(WEB_DRIVER_FACTORY, GROOVY_SCRIPT_EXECUTOR, SESSION_GRABBER, FIREFOX, CLIENT_API_SUPPORT); - scriptLoginToTest = new ZapScriptLogin(WEB_DRIVER_FACTORY, GROOVY_SCRIPT_EXECUTOR, SESSION_GRABBER); + webDriverFactory = mock(); + groovyScriptExecutor = mock(); + sessionGrabber = mock(); + clientApiSupport = mock(); + firefox = mock(); + + scriptLoginToTest = new ZapScriptLogin(webDriverFactory, groovyScriptExecutor, sessionGrabber); } @Test @@ -50,18 +54,18 @@ void script_login_execution_is_perfomed_as_expected() throws Exception { ZapScanContext scanContext = createValidZapScanContext(); - when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); - doNothing().when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); + doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); /* execute */ - scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT); + scriptLoginToTest.login(scanContext, clientApiSupport); /* test */ - verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - verify(SESSION_GRABBER, times(1)).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); - verify(FIREFOX, times(1)).quit(); + verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(firefox, times(1)).quit(); } @Test @@ -69,18 +73,18 @@ void script_can_not_be_read_results_in_firefox_closed_and_session_grabber_never_ /* prepare */ ZapScanContext scanContext = createValidZapScanContext(); - when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); - doThrow(IOException.class).when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); + doThrow(IOException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); /* test */ - verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - verify(SESSION_GRABBER, never()).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); - verify(FIREFOX, times(1)).quit(); + verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(firefox, times(1)).quit(); } @Test @@ -88,18 +92,18 @@ void script_login_execution_fails_results_in_firefox_closed_and_session_grabber_ /* prepare */ ZapScanContext scanContext = createValidZapScanContext(); - when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); - doThrow(ScriptException.class).when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - when(SESSION_GRABBER.extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT)).thenReturn(AUTH_SESSION); + when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); + doThrow(ScriptException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); /* test */ - verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - verify(SESSION_GRABBER, never()).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); - verify(FIREFOX, times(1)).quit(); + verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(firefox, times(1)).quit(); } @Test @@ -107,18 +111,18 @@ void session_grabbing_fails_results_in_firefox_closed() throws Exception { /* prepare */ ZapScanContext scanContext = createValidZapScanContext(); - when(WEB_DRIVER_FACTORY.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(FIREFOX); - doNothing().when(GROOVY_SCRIPT_EXECUTOR).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - doThrow(ClientApiException.class).when(SESSION_GRABBER).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); + when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); + doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + doThrow(ClientApiException.class).when(sessionGrabber).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, CLIENT_API_SUPPORT)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); /* test */ - verify(WEB_DRIVER_FACTORY, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(GROOVY_SCRIPT_EXECUTOR, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), FIREFOX, scanContext); - verify(SESSION_GRABBER, times(1)).extractSessionAndPassToZAP(FIREFOX, scanContext.getTargetUrlAsString(), CLIENT_API_SUPPORT); - verify(FIREFOX, times(1)).quit(); + verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); + verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(firefox, times(1)).quit(); } private ZapScanContext createValidZapScanContext() throws MalformedURLException, URISyntaxException { From e0de38830927abcc6ff4a05aa95dabd96a9f7f22 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Thu, 21 Nov 2024 15:28:03 +0100 Subject: [PATCH 07/13] PR review changes part one #3622 - update documentation and fix typos - change implementation of fetching groovy script file, now the file must be specified directly via cli or ENV - other minor changes --- .../commons/model/login/EncodingType.java | 12 +- .../shared/configuration/sechub_config.adoc | 4 +- sechub-wrapper-owasp-zap/README.adoc | 37 +- .../zapwrapper/cli/CommandLineSettings.java | 22 +- .../zapwrapper/config/ZapScanContext.java | 52 +-- .../config/ZapScanContextFactory.java | 12 +- .../zapwrapper/config/ZapScannerFactory.java | 6 +- ...onType.java => ZapAuthenticationType.java} | 4 +- ...ype.java => ZapSessionManagementType.java} | 4 +- ...tApiSupport.java => ClientApiWrapper.java} | 6 +- .../sechub/zapwrapper/scan/ZapScanner.java | 146 ++++---- .../zapwrapper/scan/login/ZapScriptLogin.java | 12 +- .../login/ZapScriptLoginSessionGrabber.java | 36 +- .../util/EnvironmentVariableConstants.java | 2 +- .../sechub/zapwrapper/util/StringDecoder.java | 2 +- .../config/ZapScanContextFactoryTest.java | 26 +- .../zapwrapper/scan/ZapScannerTest.java | 338 +++++++++--------- .../ZapScriptLoginSessionGrabberTest.java | 48 +-- .../scan/login/ZapScriptLoginTest.java | 30 +- .../zapwrapper/util/StringDecoderTest.java | 25 +- 20 files changed, 421 insertions(+), 403 deletions(-) rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/{AuthenticationType.java => ZapAuthenticationType.java} (90%) rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/{SessionManagementType.java => ZapSessionManagementType.java} (85%) rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/{ClientApiSupport.java => ClientApiWrapper.java} (99%) diff --git a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java index 8c0f9857e8..9365f94976 100644 --- a/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java +++ b/sechub-commons-model/src/main/java/com/mercedesbenz/sechub/commons/model/login/EncodingType.java @@ -1,23 +1,25 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.commons.model.login; +import static com.fasterxml.jackson.annotation.JsonFormat.Feature.*; + import com.fasterxml.jackson.annotation.JsonFormat; public enum EncodingType { - @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES) AUTODETECT, - @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES) HEX, - @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES) BASE32, - @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES) BASE64, - @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) + @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES) PLAIN, ; diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc index 83f1644c72..1a0df3d6d2 100644 --- a/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc +++ b/sechub-doc/src/docs/asciidoc/documents/shared/configuration/sechub_config.adoc @@ -329,8 +329,8 @@ The currently available hash algorithms are: - `HMAC_SHA256` - `HMAC_SHA512` <6> The `encodingType` is an __optional__ field, representing the encoding of the __mandatory__ field `seed`. -Sechub has a default configured if nothing is specified or the encoding type is not known. -The default value is `AUTODETECT` where SecHub tries to detect the encoding of one of the four other available types. +{sechub} has a default configured if nothing is specified or the encoding type is not known. +The default value is `AUTODETECT` where {sechub} tries to detect the encoding of one of the four other available types. The currently available encoding types for `seed` are, which are treated case-insensitive: - `BASE64` - `BASE32` diff --git a/sechub-wrapper-owasp-zap/README.adoc b/sechub-wrapper-owasp-zap/README.adoc index e52452255c..6e0ad59d67 100644 --- a/sechub-wrapper-owasp-zap/README.adoc +++ b/sechub-wrapper-owasp-zap/README.adoc @@ -48,6 +48,10 @@ Usage: ZapWrapper [options] like: rule1,rule,rule3 * --fullRulesetfile Specify a file with all rules installed for the Zap. + --groovyLoginScriptFile + Groovy script file the ZAP wrapper uses for script based authentication + when templates are defined. You can also set the environment variable + ZAP_GROOVY_LOGIN_SCRIPT_FILE, instead of using this parameter. --help Shows help and provides information on how to use the wrapper. --jobUUID @@ -59,15 +63,12 @@ Usage: ZapWrapper [options] Default: 3 --pdsEventFolder Folder where the ZAP wrapper listens for events of the PDS, like cancel - requests for the current job. When using with SecHub+PDS solution this - is not needed since the PDS provides the env variable: - PDS_JOB_EVENTS_FOLDER. This env variable is automatically used if this - command line parameter is not set. + requests for the current job. You can also set the environment variable + PDS_JOB_EVENTS_FOLDER, instead of using this parameter. --pdsUserMessageFolder - Folder where the user messages are written to. When using with - SecHub+PDS solution this is not needed since the PDS provides the env - variable: PDS_JOB_USER_MESSAGES_FOLDER. This env variable is - automatically used if this command line parameter is not set. + Folder where the user messages are written to. You can also set the + environment variable PDS_JOB_USER_MESSAGES_FOLDER, instead of using this + parameter. --proxyHost Specify a proxy host. You can also set the environment variable PROXY_HOST, instead of using this parameter. @@ -88,11 +89,6 @@ Usage: ZapWrapper [options] scan. * --targetURL Specifies the target url to be scanned. - --templateFolder - Folder where the ZAP wrapper fetches the logins script from. This is not - needed since the PDS provides the env variable: PDS_TEMPLATE_FOLDER. - This env variable is automatically used if this command line parameter - is not set. --verbose Set this option to provide additional output while scanning. Default: false @@ -201,8 +197,19 @@ inside the executor config. ==== Groovy Script Login To handle more complex authentication scenarios, the wrapper uses pre-defined groovy scripts. -Rhe groovy authentication scripts have access to certain data the wrapper application passes with the bindings for the script execution, as well as selenium support. -Some objects are already ready pre-configured and ready to use, like the firefox webdriver. Above you can see all available bindings, even if they are not used in this example script. +The groovy authentication scripts have access to certain data from the wrapper application: + +- An initialized selenium `FirefoxDriver` object that can be used directly +- An initialized selenium `WebDriverWait` object that can be used directly, implicitly using the firefox web driver +- An initialized selenium `JavascriptExecutor` object, which on default is the previously introduced `FirefoxDriver` +- The `SecHubWebScanConfiguration` that was used to configure the scan +- The `TOTPGenerator` that can be used for two-factor-authentication +- The `user` configured for the authentication +- The `password` of the `user` +- The `loginUrl` necessary to authenticate. +- The `targetUrl`, which is the base URL specified for the scan. + +The example script below shows how these bindings can be accessed and used. In the example script all bindings are listed, even the ones not used by the script. The script can also be created completely without using anything of the pre-defined data. The `TOTPGenerator` is an easy to use implementation of TOTP for two-factor-authentication if necessary. Using `totpGenerator.now()` returns the currently valid TOTP. diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java index ed1d71662b..d943089647 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java @@ -166,10 +166,8 @@ public int getRetryWaittimeInMilliseconds() { return retryWaittimeInMilliseconds; } - @Parameter(names = { - "--pdsUserMessageFolder" }, description = "Folder where the user messages are written to. When using with SecHub+PDS solution this is not needed since the PDS provides the env variable: " - + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER - + ". This env variable is automatically used if this command line parameter is not set.", required = false) + @Parameter(names = { "--pdsUserMessageFolder" }, description = "Folder where the user messages are written to. You can also set the environment variable " + + EnvironmentVariableConstants.PDS_JOB_USER_MESSAGES_FOLDER + ", instead of using this parameter.", required = false) private String pdsUserMessageFolder; public String getPDSUserMessageFolder() { @@ -177,9 +175,8 @@ public String getPDSUserMessageFolder() { } @Parameter(names = { - "--pdsEventFolder" }, description = "Folder where the ZAP wrapper listens for events of the PDS, like cancel requests for the current job. When using with SecHub+PDS solution this is not needed since the PDS provides the env variable: " - + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER - + ". This env variable is automatically used if this command line parameter is not set.", required = false) + "--pdsEventFolder" }, description = "Folder where the ZAP wrapper listens for events of the PDS, like cancel requests for the current job. You can also set the environment variable " + + EnvironmentVariableConstants.PDS_JOB_EVENTS_FOLDER + ", instead of using this parameter.", required = false) private String pdsEventFolder; public String getPDSEventFolder() { @@ -187,12 +184,11 @@ public String getPDSEventFolder() { } @Parameter(names = { - "--templateFolder" }, description = "Folder where the ZAP wrapper fetches the logins script from. This is not needed since the PDS provides the env variable: " - + EnvironmentVariableConstants.PDS_TEMPLATE_FOLDER - + ". This env variable is automatically used if this command line parameter is not set.", required = false) - private String templateFolder; + "--groovyLoginScriptFile" }, description = "Groovy script file the ZAP wrapper uses for script based authentication when templates are defined. You can also set the environment variable " + + EnvironmentVariableConstants.ZAP_GROOVY_LOGIN_SCRIPT_FILE + ", instead of using this parameter.", required = false) + private String groovyLoginScriptFile; - public String getTemplateFolder() { - return templateFolder; + public String getGroovyLoginScriptFile() { + return groovyLoginScriptFile; } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java index 4fed08ed68..609e217724 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java @@ -351,47 +351,47 @@ public ZapScanContextBuilder setGroovyScriptLoginFile(File groovyScriptLoginFile } public ZapScanContext build() { - ZapScanContext zapScanConfiguration = new ZapScanContext(); - zapScanConfiguration.serverConfig = this.serverConfig; - zapScanConfiguration.verboseOutput = this.verboseOutput; - zapScanConfiguration.ajaxSpiderEnabled = this.ajaxSpiderEnabled; - zapScanConfiguration.activeScanEnabled = this.activeScanEnabled; - zapScanConfiguration.reportFile = this.reportFile; - zapScanConfiguration.contextName = this.contextName; - zapScanConfiguration.targetUrl = this.targetUrl; + ZapScanContext zapScanContext = new ZapScanContext(); + zapScanContext.serverConfig = this.serverConfig; + zapScanContext.verboseOutput = this.verboseOutput; + zapScanContext.ajaxSpiderEnabled = this.ajaxSpiderEnabled; + zapScanContext.activeScanEnabled = this.activeScanEnabled; + zapScanContext.reportFile = this.reportFile; + zapScanContext.contextName = this.contextName; + zapScanContext.targetUrl = this.targetUrl; - zapScanConfiguration.maxScanDurationInMilliSeconds = this.maxScanDurationInMilliSeconds; + zapScanContext.maxScanDurationInMilliSeconds = this.maxScanDurationInMilliSeconds; - zapScanConfiguration.secHubWebScanConfiguration = this.secHubWebScanConfiguration; + zapScanContext.secHubWebScanConfiguration = this.secHubWebScanConfiguration; - zapScanConfiguration.proxyInformation = this.proxyInformation; + zapScanContext.proxyInformation = this.proxyInformation; - zapScanConfiguration.fullRuleset = this.fullRuleset; - zapScanConfiguration.deactivatedRuleReferences = this.deactivatedRuleReferences; + zapScanContext.fullRuleset = this.fullRuleset; + zapScanContext.deactivatedRuleReferences = this.deactivatedRuleReferences; - zapScanConfiguration.apiDefinitionFiles = this.apiDefinitionFiles; + zapScanContext.apiDefinitionFiles = this.apiDefinitionFiles; - zapScanConfiguration.zapURLsIncludeSet.addAll(this.zapURLsIncludeSet); - zapScanConfiguration.zapURLsExcludeSet.addAll(this.zapURLsExcludeSet); + zapScanContext.zapURLsIncludeSet.addAll(this.zapURLsIncludeSet); + zapScanContext.zapURLsExcludeSet.addAll(this.zapURLsExcludeSet); - zapScanConfiguration.connectionCheckEnabled = this.connectionCheckEnabled; + zapScanContext.connectionCheckEnabled = this.connectionCheckEnabled; - zapScanConfiguration.maxNumberOfConnectionRetries = this.maxNumberOfConnectionRetries; - zapScanConfiguration.retryWaittimeInMilliseconds = this.setRetryWaittimeInMilliseconds; + zapScanContext.maxNumberOfConnectionRetries = this.maxNumberOfConnectionRetries; + zapScanContext.retryWaittimeInMilliseconds = this.setRetryWaittimeInMilliseconds; - zapScanConfiguration.zapProductMessageHelper = this.zapProductMessageHelper; + zapScanContext.zapProductMessageHelper = this.zapProductMessageHelper; - zapScanConfiguration.zapPDSEventHandler = this.zapPDSEventHandler; + zapScanContext.zapPDSEventHandler = this.zapPDSEventHandler; - zapScanConfiguration.clientCertificateFile = this.clientCertificateFile; + zapScanContext.clientCertificateFile = this.clientCertificateFile; - zapScanConfiguration.headerValueFiles = this.headerValueFiles; + zapScanContext.headerValueFiles = this.headerValueFiles; - zapScanConfiguration.ajaxSpiderBrowserId = this.ajaxSpiderBrowserId; + zapScanContext.ajaxSpiderBrowserId = this.ajaxSpiderBrowserId; - zapScanConfiguration.groovyScriptLoginFile = this.groovyScriptLoginFile; + zapScanContext.groovyScriptLoginFile = this.groovyScriptLoginFile; - return zapScanConfiguration; + return zapScanContext; } } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java index 9a3932bf1e..d9b5738286 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java @@ -35,8 +35,6 @@ public class ZapScanContextFactory { private static final int DAYS_IN_MS = 24 * HOURS_IN_MS; private static final int DEFAULT_MAX_SCAN_DURATION = 8 * HOURS_IN_MS; - private static final String GROOVY_LOGIN_SCRIPTFILE_NAME = "script.groovy"; - private final EnvironmentVariableReader environmentVariableReader; private final BaseTargetUriFactory targetUriFactory; private final RuleProvider ruleProvider; @@ -317,13 +315,13 @@ private long fetchMaxScanDurationInMillis(SecHubWebScanConfiguration sechubWebCo } private File fetchGroovyScriptFile(CommandLineSettings settings) { - String templateDir = settings.getTemplateFolder(); - if (templateDir == null) { - templateDir = environmentVariableReader.readAsString(EnvironmentVariableConstants.PDS_TEMPLATE_FOLDER); + String groovyScriptFile = settings.getGroovyLoginScriptFile(); + if (groovyScriptFile == null) { + groovyScriptFile = environmentVariableReader.readAsString(EnvironmentVariableConstants.ZAP_GROOVY_LOGIN_SCRIPT_FILE); } - if (templateDir == null) { + if (groovyScriptFile == null) { return null; } - return new File(templateDir, GROOVY_LOGIN_SCRIPTFILE_NAME); + return new File(groovyScriptFile); } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java index 89fec8d613..b2bd6015ae 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScannerFactory.java @@ -7,7 +7,7 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; import com.mercedesbenz.sechub.zapwrapper.scan.ZapScanner; public class ZapScannerFactory { @@ -26,9 +26,9 @@ public ZapScanner create(ZapScanContext scanContext) { String zaproxyApiKey = serverConfig.getZaproxyApiKey(); ClientApi clientApi = new ClientApi(zaproxyHost, zaproxyPort, zaproxyApiKey); - ClientApiSupport clientApiSupport = new ClientApiSupport(clientApi); + ClientApiWrapper clientApiWrapper = new ClientApiWrapper(clientApi); - return new ZapScanner(clientApiSupport, scanContext); + return new ZapScanner(clientApiWrapper, scanContext); } private void assertValidServerConfig(ZapServerConfiguration serverConfig) { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapAuthenticationType.java similarity index 90% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapAuthenticationType.java index 2253dd6e23..29ad03a24e 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/AuthenticationType.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapAuthenticationType.java @@ -6,7 +6,7 @@ * Zap API easier to use. * */ -public enum AuthenticationType { +public enum ZapAuthenticationType { UNAUTHENTICATED(null), @@ -24,7 +24,7 @@ public enum AuthenticationType { private String zapAuthenticationMethod; - private AuthenticationType(String methodName) { + private ZapAuthenticationType(String methodName) { this.zapAuthenticationMethod = methodName; } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/SessionManagementType.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapSessionManagementType.java similarity index 85% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/SessionManagementType.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapSessionManagementType.java index e5f11ae28e..294bb8152f 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/SessionManagementType.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/auth/ZapSessionManagementType.java @@ -6,7 +6,7 @@ * the ZAP API easier to use. * */ -public enum SessionManagementType { +public enum ZapSessionManagementType { HTTP_AUTH_SESSION_MANAGEMENT("httpAuthSessionManagement"), @@ -18,7 +18,7 @@ public enum SessionManagementType { private String zapSessionManagementMethod; - private SessionManagementType(String zapSessionManagementMethod) { + private ZapSessionManagementType(String zapSessionManagementMethod) { this.zapSessionManagementMethod = zapSessionManagementMethod; } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java similarity index 99% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java index 75f3ad4487..efd04dfe31 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiSupport.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java @@ -14,18 +14,18 @@ import org.zaproxy.clientapi.core.ClientApi; import org.zaproxy.clientapi.core.ClientApiException; -public class ClientApiSupport { +public class ClientApiWrapper { private static final String URL_KEY = "url"; private static final String STATUS_CODE_KEY = "statusCode"; private static final String STATUS_REASON_KEY = "statusReason"; private static final String METHOD_KEY = "method"; - private static final Logger LOG = LoggerFactory.getLogger(ClientApiSupport.class); + private static final Logger LOG = LoggerFactory.getLogger(ClientApiWrapper.class); private ClientApi clientApi; - public ClientApiSupport(ClientApi clientApi) { + public ClientApiWrapper(ClientApi clientApi) { this.clientApi = clientApi; } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java index 9f9515b8a2..1029c555fa 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java @@ -25,15 +25,15 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; import com.mercedesbenz.sechub.zapwrapper.config.ProxyInformation; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; -import com.mercedesbenz.sechub.zapwrapper.config.auth.SessionManagementType; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapAuthenticationType; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapSessionManagementType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.Rule; import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLogin; import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginSessionGrabber; import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginWebDriverFactory; @@ -49,7 +49,7 @@ public class ZapScanner implements ZapScan { private static final int CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS = 5000; private static final int DEFAULT_MAX_DEPTH = 10; - private final ClientApiSupport clientApiSupport; + private final ClientApiWrapper clientApiWrapper; private final ZapScanContext scanContext; private final ZapScriptLogin scriptLogin; @@ -57,8 +57,8 @@ public class ZapScanner implements ZapScan { private final UrlUtil urlUtil; private final SystemUtil systemUtil; - public ZapScanner(ClientApiSupport clientApiSupport, ZapScanContext scanContext) { - this.clientApiSupport = clientApiSupport; + public ZapScanner(ClientApiWrapper clientApiWrapper, ZapScanContext scanContext) { + this.clientApiWrapper = clientApiWrapper; this.scanContext = scanContext; this.scanDurationHelper = new ScanDurationHelper(); @@ -68,9 +68,9 @@ public ZapScanner(ClientApiSupport clientApiSupport, ZapScanContext scanContext) this.scriptLogin = new ZapScriptLogin(new ZapScriptLoginWebDriverFactory(), new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionGrabber()); } - ZapScanner(ClientApiSupport clientApiSupport, ZapScanContext scanContext, ScanDurationHelper scanDurationHelper, UrlUtil urlUtil, SystemUtil systemUtil, + ZapScanner(ClientApiWrapper clientApiWrapper, ZapScanContext scanContext, ScanDurationHelper scanDurationHelper, UrlUtil urlUtil, SystemUtil systemUtil, ZapScriptLogin scriptLogin) { - this.clientApiSupport = clientApiSupport; + this.clientApiWrapper = clientApiWrapper; this.scanContext = scanContext; this.scanDurationHelper = scanDurationHelper; @@ -115,28 +115,28 @@ public void scan() throws ZapWrapperRuntimeException { void setupStandardConfiguration() throws ClientApiException { LOG.info("Creating new session inside the Zap"); // to ensure parts from previous scan are deleted - clientApiSupport.createNewSession(scanContext.getContextName(), "true"); + clientApiWrapper.createNewSession(scanContext.getContextName(), "true"); LOG.info("Setting default maximum number of alerts for each rule."); // setting this value to zero means unlimited - clientApiSupport.configureMaximumAlertsForEachRule("0"); + clientApiWrapper.configureMaximumAlertsForEachRule("0"); LOG.info("Enable all passive scan rules before configuration begins."); // enable all passive scanner rules by default - clientApiSupport.enableAllPassiveScannerRules(); + clientApiWrapper.enableAllPassiveScannerRules(); LOG.info("Enable all active scan rules before configuration begins."); // enable all passive scanner rules by default // null specifies the default scan policy - clientApiSupport.enableAllActiveScannerRulesForPolicy(null); + clientApiWrapper.enableAllActiveScannerRulesForPolicy(null); LOG.info("Set browser for ajaxSpider."); // use firefox in headless mode by default - clientApiSupport.setAjaxSpiderBrowserId(scanContext.getAjaxSpiderBrowserId()); + clientApiWrapper.setAjaxSpiderBrowserId(scanContext.getAjaxSpiderBrowserId()); LOG.info("Set max directory depth of spider and ajaxSpider to: {}", DEFAULT_MAX_DEPTH); - clientApiSupport.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); - clientApiSupport.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); + clientApiWrapper.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); + clientApiWrapper.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); } void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deactivatedRuleReferences) throws ClientApiException { @@ -152,11 +152,11 @@ void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deact Rule ruleToDeactivate = fullRuleset.findRuleByReference(ruleRef.getReference()); if (isPassiveRule(ruleToDeactivate.getType())) { LOG.info("Deactivate passive scanner rule: {} ", ruleRef.getReference()); - clientApiSupport.disablePassiveScannerRule(ruleToDeactivate.getId()); + clientApiWrapper.disablePassiveScannerRule(ruleToDeactivate.getId()); } else if (isActiveRule(ruleToDeactivate.getType())) { LOG.info("Deactivate active scanner rule: {} ", ruleRef.getReference()); // null specifies the default scan policy - clientApiSupport.disableActiveScannerRuleForPolicy(ruleToDeactivate.getId(), null); + clientApiWrapper.disableActiveScannerRuleForPolicy(ruleToDeactivate.getId(), null); } } } @@ -166,12 +166,12 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws String proxyHost = proxyInformation.getHost(); int proxyPort = proxyInformation.getPort(); LOG.info("Using proxy {}:{} to reach target.", proxyHost, proxyPort); - clientApiSupport.configureHttpProxy(proxyHost, "" + proxyPort, null, null, null); - clientApiSupport.setHttpProxyEnabled("true"); - clientApiSupport.setHttpProxyAuthEnabled("false"); + clientApiWrapper.configureHttpProxy(proxyHost, "" + proxyPort, null, null, null); + clientApiWrapper.setHttpProxyEnabled("true"); + clientApiWrapper.setHttpProxyAuthEnabled("false"); } else { LOG.info("No proxy was set, continuing without proxy."); - clientApiSupport.setHttpProxyEnabled("false"); + clientApiWrapper.setHttpProxyEnabled("false"); } } @@ -183,7 +183,7 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws */ String createContext() throws ClientApiException { LOG.info("Creating context: {}", scanContext.getContextName()); - return clientApiSupport.createNewContext(scanContext.getContextName()); + return clientApiWrapper.createNewContext(scanContext.getContextName()); } void addReplacerRulesForHeaders() throws ClientApiException { @@ -224,13 +224,13 @@ void addReplacerRulesForHeaders() throws ClientApiException { if (httpHeader.getOnlyForUrls().isEmpty()) { // if there are no onlyForUrl patterns, there is only one rule for each header description = httpHeader.getName(); - clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiWrapper.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } else { for (String onlyForUrl : httpHeader.getOnlyForUrls().get()) { // we need to create a rule for each onlyForUrl pattern on each header description = onlyForUrl; url = urlUtil.replaceWebScanWildCardsWithRegexInString(onlyForUrl); - clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiWrapper.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } } } @@ -245,19 +245,19 @@ void addIncludedAndExcludedUrlsToContext() throws ClientApiException { LOG.info("For scan {}: Adding include parts.", scanContext.getContextName()); String followRedirects = "false"; for (String url : scanContext.getZapURLsIncludeSet()) { - clientApiSupport.addIncludeUrlPatternToContext(scanContext.getContextName(), url); + clientApiWrapper.addIncludeUrlPatternToContext(scanContext.getContextName(), url); // Cannot not perform initial connection check to included URL with wildcards if (url.contains(".*")) { LOG.info("For scan {}: Cannot not perform initial connection check to included URL: {} because it contains wildcards.", scanContext.getContextName(), url); } else { - clientApiSupport.accessUrlViaZap(url, followRedirects); + clientApiWrapper.accessUrlViaZap(url, followRedirects); } } LOG.info("For scan {}: Adding exclude parts.", scanContext.getContextName()); for (String url : scanContext.getZapURLsExcludeSet()) { - clientApiSupport.addExcludeUrlPatternToContext(scanContext.getContextName(), url); + clientApiWrapper.addExcludeUrlPatternToContext(scanContext.getContextName(), url); } } @@ -275,11 +275,11 @@ void loadApiDefinitions(String zapContextId) throws ClientApiException { URL apiDefinitionUrl = secHubWebScanApiConfiguration.getApiDefinitionUrl(); if (apiDefinitionUrl != null) { LOG.info("For scan {}: Loading openAPI definition from : {}", scanContext.getContextName(), apiDefinitionUrl.toString()); - clientApiSupport.importOpenApiDefintionFromUrl(apiDefinitionUrl, scanContext.getTargetUrlAsString(), zapContextId); + clientApiWrapper.importOpenApiDefintionFromUrl(apiDefinitionUrl, scanContext.getTargetUrlAsString(), zapContextId); } for (File apiFile : scanContext.getApiDefinitionFiles()) { LOG.info("For scan {}: Loading openAPI file: {}", scanContext.getContextName(), apiFile.toString()); - clientApiSupport.importOpenApiFile(apiFile.toString(), scanContext.getTargetUrlAsString(), zapContextId); + clientApiWrapper.importOpenApiFile(apiFile.toString(), scanContext.getTargetUrlAsString(), zapContextId); } break; default: @@ -316,8 +316,8 @@ void importClientCertificate() throws ClientApiException { password = new String(clientCertificateConfig.getPassword()); } LOG.info("For scan {}: Loading client certificate file: {}", scanContext.getContextName(), clientCertificateFile.getAbsolutePath()); - clientApiSupport.importPkcs12ClientCertificate(clientCertificateFile.getAbsolutePath(), password); - clientApiSupport.enableClientCertificate(); + clientApiWrapper.importPkcs12ClientCertificate(clientCertificateFile.getAbsolutePath(), password); + clientApiWrapper.enableClientCertificate(); } void executeScan(String zapContextId) throws ClientApiException { @@ -369,7 +369,7 @@ UserInformation setupLoginInsideZapContext(String zapContextId) throws ClientApi setupAuthenticationAndSessionManagementMethodForScriptLogin(zapContextId); LOG.info("For scan {}: Performing script authentication.", scanContext.getContextName()); - String zapAuthSessionName = scriptLogin.login(scanContext, clientApiSupport); + String zapAuthSessionName = scriptLogin.login(scanContext, clientApiWrapper); // TODO read the username from templateData as soon as it is implemented String username = "DUMMY"; @@ -410,7 +410,7 @@ void generateZapReport() throws ClientApiException { String display = null; /* @formatter:off */ // we use the context name as report title - clientApiSupport.generateReport( + clientApiWrapper.generateReport( title, template, theme, @@ -438,7 +438,7 @@ void cleanUp() { // to ensure parts from previous scan are deleted try { LOG.info("Cleaning up by starting new and empty session...", scanContext.getContextName()); - clientApiSupport.createNewSession("Cleaned after scan", "true"); + clientApiWrapper.createNewSession("Cleaned after scan", "true"); LOG.info("New and empty session inside Zap created."); // Replacer rules are persistent even after restarting ZAP @@ -448,15 +448,15 @@ void cleanUp() { // Remove x-sechub-dast header replacer rule LOG.info("Remove '{}' replacer rule.", X_SECHUB_DAST_HEADER_NAME); - clientApiSupport.removeReplacerRule(X_SECHUB_DAST_HEADER_NAME); + clientApiWrapper.removeReplacerRule(X_SECHUB_DAST_HEADER_NAME); // disable client certificate here, the imported client certificate will be // removed on ZAP shutdown automatically anyway LOG.info("Disable client certificate if one was used for the scan."); - clientApiSupport.disableClientCertificate(); + clientApiWrapper.disableClientCertificate(); LOG.info("Cleaning up script login data."); - scriptLogin.cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); + scriptLogin.cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); LOG.info("Cleanup successful."); } catch (ClientApiException e) { @@ -473,7 +473,7 @@ long runSpider(long remainingScanDurationInMillis) throws ClientApiException { LOG.info("For scan {}: Starting Spider.", contextName); /* @formatter:off */ String scanId = - clientApiSupport.startSpiderScan( + clientApiWrapper.startSpiderScan( targetUrlAsString, maxChildren, recurse, @@ -490,7 +490,7 @@ long runAjaxSpider(long remainingScanDurationInMillis) throws ClientApiException String targetUrlAsString = scanContext.getTargetUrlAsString(); LOG.info("For scan {}: Starting AjaxSpider.", scanContext.getContextName()); /* @formatter:off */ - clientApiSupport.startAjaxSpiderScan( + clientApiWrapper.startAjaxSpiderScan( targetUrlAsString, inScope, contextName, @@ -502,7 +502,7 @@ long runAjaxSpider(long remainingScanDurationInMillis) throws ClientApiException void runActiveScan(long remainingScanDurationInMillis) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before - if (!clientApiSupport.atLeastOneURLDetected()) { + if (!clientApiWrapper.atLeastOneURLDetected()) { LOG.warn("For {} skipping active scan, since no URLs where detected by spider or ajaxSpider!", scanContext.getContextName()); scanContext.getZapProductMessageHelper().writeSingleProductMessage( new SecHubMessage(SecHubMessageType.WARNING, "Skipped the active scan, because no URLs were detected by the crawler! " @@ -518,7 +518,7 @@ void runActiveScan(long remainingScanDurationInMillis) throws ClientApiException LOG.info("For scan {}: Starting ActiveScan.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiSupport.startActiveScan( + clientApiWrapper.startActiveScan( targetUrlAsString, recurse, inScopeOnly, @@ -537,7 +537,7 @@ long runSpiderAsUser(String contextId, String userId, long remainingScanDuration LOG.info("For scan {}: Starting authenticated Spider.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiSupport.startSpiderScanAsUser( + clientApiWrapper.startSpiderScanAsUser( contextId, userId, url, @@ -554,7 +554,7 @@ long runAjaxSpiderAsUser(String username, long remainingScanDurationInMillis) th String subtreeonly = "true"; LOG.info("For scan {}: Starting authenticated Ajax Spider.", scanContext.getContextName()); /* @formatter:off */ - clientApiSupport.startAjaxSpiderScanAsUser( + clientApiWrapper.startAjaxSpiderScanAsUser( contextname, username, url, @@ -566,7 +566,7 @@ long runAjaxSpiderAsUser(String username, long remainingScanDurationInMillis) th void runActiveScanAsUser(String contextId, String userId, long remainingScanDurationInMillis) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before - if (!clientApiSupport.atLeastOneURLDetected()) { + if (!clientApiWrapper.atLeastOneURLDetected()) { LOG.warn("For {} skipping active scan, since no URLs where detected by spider or ajaxSpider!", scanContext.getContextName()); scanContext.getZapProductMessageHelper().writeSingleProductMessage( new SecHubMessage(SecHubMessageType.WARNING, "Skipped the active scan, because no URLs were detected by the crawler! " @@ -581,7 +581,7 @@ void runActiveScanAsUser(String contextId, String userId, long remainingScanDura LOG.info("For scan {}: Starting authenticated ActiveScan.", scanContext.getContextName()); /* @formatter:off */ String scanId = - clientApiSupport.startActiveScanAsUser( + clientApiWrapper.startActiveScanAsUser( url, contextId, userId, @@ -613,16 +613,16 @@ long waitForAjaxSpiderResults(long remainingScanDurationInMillis) throws ClientA while (!isAjaxSpiderStopped(ajaxSpiderStatus) && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiSupport.stopAjaxSpider(); + clientApiWrapper.stopAjaxSpider(); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - ajaxSpiderStatus = clientApiSupport.getAjaxSpiderStatus(); + ajaxSpiderStatus = clientApiWrapper.getAjaxSpiderStatus(); LOG.info("For scan {}: AjaxSpider status {}", scanContext.getContextName(), ajaxSpiderStatus); timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > maxDuration; } /* stop spider - otherwise running in background */ - clientApiSupport.stopAjaxSpider(); + clientApiWrapper.stopAjaxSpider(); LOG.info("For scan {}: AjaxSpider completed.", scanContext.getContextName()); return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } @@ -648,18 +648,18 @@ long waitForSpiderResults(String scanId, long remainingScanDurationInMillis) thr while (progressSpider < 100 && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiSupport.stopSpiderScan(scanId); + clientApiWrapper.stopSpiderScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - progressSpider = clientApiSupport.getSpiderStatusForScan(scanId); + progressSpider = clientApiWrapper.getSpiderStatusForScan(scanId); LOG.info("For scan {}: Spider progress {}%", scanContext.getContextName(), progressSpider); timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } /* stop spider - otherwise running in background */ - clientApiSupport.stopSpiderScan(scanId); + clientApiWrapper.stopSpiderScan(scanId); - long numberOfSpiderResults = clientApiSupport.logFullSpiderResults(scanId); + long numberOfSpiderResults = clientApiWrapper.logFullSpiderResults(scanId); scanContext.getZapProductMessageHelper() .writeSingleProductMessage(new SecHubMessage(SecHubMessageType.INFO, "Scanned %s URLs during the scan.".formatted(numberOfSpiderResults))); LOG.info("For scan {}: Spider completed.", scanContext.getContextName()); @@ -680,7 +680,7 @@ long passiveScan(long remainingScanDurationInMillis) throws ClientApiException { long maxDuration = scanDurationHelper.computePassiveScanMaxScanDuration(scanContext.isActiveScanEnabled(), scanContext.isAjaxSpiderEnabled(), remainingScanDurationInMillis); - int numberOfRecords = clientApiSupport.getNumberOfPassiveScannerRecordsToScan(); + int numberOfRecords = clientApiWrapper.getNumberOfPassiveScannerRecordsToScan(); boolean timeOut = false; ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); @@ -689,7 +689,7 @@ long passiveScan(long remainingScanDurationInMillis) throws ClientApiException { zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - numberOfRecords = clientApiSupport.getNumberOfPassiveScannerRecordsToScan(); + numberOfRecords = clientApiWrapper.getNumberOfPassiveScannerRecordsToScan(); LOG.info("For scan {}: Passive scan number of records left for scanning: {}", scanContext.getContextName(), numberOfRecords); timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } @@ -715,16 +715,16 @@ void waitForActiveScanResults(String scanId, long remainingScanDurationInMillis) while (progressActive < 100 && !timeOut) { if (zapPDSEventHandler.isScanCancelled()) { - clientApiSupport.stopActiveScan(scanId); + clientApiWrapper.stopActiveScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); - progressActive = clientApiSupport.getActiveScannerStatusForScan(scanId); + progressActive = clientApiWrapper.getActiveScannerStatusForScan(scanId); LOG.info("For scan {}: Active scan progress {}%", scanContext.getContextName(), progressActive); timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > remainingScanDurationInMillis; } - clientApiSupport.stopActiveScan(scanId); + clientApiWrapper.stopActiveScan(scanId); LOG.info("For scan {}: Active scan completed.", scanContext.getContextName()); } @@ -749,15 +749,15 @@ private UserInformation initBasicAuthentication(String zapContextId, BasicLoginC .append("&port=").append(urlEncodeUTF8(port)); /* @formatter:on */ LOG.info("For scan {}: Setting basic authentication.", scanContext.getContextName()); - String authMethodName = AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); - clientApiSupport.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); + String authMethodName = ZapAuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); + clientApiWrapper.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); - String methodName = SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + String methodName = ZapSessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); // methodconfigparams in case of http basic auth is null, because it is // configured automatically String methodconfigparams = null; - clientApiSupport.setSessionManagementMethod(zapContextId, methodName, methodconfigparams); + clientApiWrapper.setSessionManagementMethod(zapContextId, methodName, methodconfigparams); /* @formatter:off */ String username = new String(basicLoginConfiguration.getUser()); @@ -771,15 +771,15 @@ private UserInformation initBasicAuthentication(String zapContextId, BasicLoginC } private UserInformation setupScanUserForZapContext(String zapContextId, String username, String authCredentialsConfigParams) throws ClientApiException { - String userId = clientApiSupport.createNewUser(zapContextId, username); + String userId = clientApiWrapper.createNewUser(zapContextId, username); LOG.info("For scan {}: Setting up user.", scanContext.getContextName()); - clientApiSupport.configureAuthenticationCredentials(zapContextId, userId, authCredentialsConfigParams.toString()); + clientApiWrapper.configureAuthenticationCredentials(zapContextId, userId, authCredentialsConfigParams.toString()); String enabled = "true"; - clientApiSupport.setUserEnabled(zapContextId, userId, enabled); + clientApiWrapper.setUserEnabled(zapContextId, userId, enabled); - clientApiSupport.setForcedUser(zapContextId, userId); - clientApiSupport.setForcedUserModeEnabled(true); + clientApiWrapper.setForcedUser(zapContextId, userId); + clientApiWrapper.setForcedUserModeEnabled(true); UserInformation userInfo = new UserInformation(username, userId); return userInfo; @@ -790,15 +790,15 @@ private void setupAuthenticationAndSessionManagementMethodForScriptLogin(String // because it is // configured automatically String authMethodConfigParams = null; - String authMethodName = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); - clientApiSupport.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams); + String authMethodName = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + clientApiWrapper.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams); // sessionMethodConfigparams in case of cookie based session management is null, // because it is // configured automatically String sessionMethodconfigparams = null; - String sessionMethodName = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - clientApiSupport.setSessionManagementMethod(zapContextId, sessionMethodName, sessionMethodconfigparams); + String sessionMethodName = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + clientApiWrapper.setSessionManagementMethod(zapContextId, sessionMethodName, sessionMethodconfigparams); } private boolean isAjaxSpiderStopped(String status) { @@ -854,11 +854,11 @@ private void cleanUpReplacerRules() throws ClientApiException { for (HTTPHeaderConfiguration httpHeader : httpHeaders) { if (httpHeader.getOnlyForUrls().isEmpty()) { String description = httpHeader.getName(); - clientApiSupport.removeReplacerRule(description); + clientApiWrapper.removeReplacerRule(description); } else { for (String onlyForUrl : httpHeader.getOnlyForUrls().get()) { String description = onlyForUrl; - clientApiSupport.removeReplacerRule(description); + clientApiWrapper.removeReplacerRule(description); } } } @@ -909,7 +909,7 @@ private void addXSecHubDASTHeader() throws ClientApiException { String url = null; LOG.info("Add '{}' replacer rule.", X_SECHUB_DAST_HEADER_NAME); - clientApiSupport.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiWrapper.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } private boolean isScriptLoginWanted() { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java index 06dee0f040..ce139751a5 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java @@ -14,7 +14,7 @@ import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; public class ZapScriptLogin { private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLogin.class); @@ -35,10 +35,10 @@ public ZapScriptLogin(ZapScriptLoginWebDriverFactory webDriverFactory, ZapWrappe * sessionGrabber will add all necessary session data to ZAP. * * @param scanContext - * @param clientApiSupport + * @param clientApiWrapper * @return the name/identifier of the authenticated session inside ZAP */ - public String login(ZapScanContext scanContext, ClientApiSupport clientApiSupport) { + public String login(ZapScanContext scanContext, ClientApiWrapper clientApiWrapper) { File groovyScriptLoginFile = scanContext.getGroovyScriptLoginFile(); if (groovyScriptLoginFile == null || !groovyScriptLoginFile.isFile()) { throw new ZapWrapperRuntimeException( @@ -53,7 +53,7 @@ public String login(ZapScanContext scanContext, ClientApiSupport clientApiSuppor groovyScriptExecutor.executeScript(groovyScriptLoginFile, firefox, scanContext); LOG.info("Calling session grabber to read the HTTP session data and pass them to ZAP."); - return sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + return sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); } catch (IOException e) { throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.IO_ERROR); } catch (ScriptException e) { @@ -65,8 +65,8 @@ public String login(ZapScanContext scanContext, ClientApiSupport clientApiSuppor } } - public void cleanUpScriptLoginData(String targetUrl, ClientApiSupport clientApiSupport) { - sessionGrabber.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiSupport); + public void cleanUpScriptLoginData(String targetUrl, ClientApiWrapper clientApiWrapper) { + sessionGrabber.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java index 70414fd669..68b7f8f8d1 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java @@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory; import org.zaproxy.clientapi.core.ClientApiException; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; public class ZapScriptLoginSessionGrabber { private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLoginSessionGrabber.class); @@ -30,31 +30,31 @@ public class ZapScriptLoginSessionGrabber { * * @param firefox * @param targetUrl - * @param clientApiSupport + * @param clientApiWrapper * @return the name/identifier of the authenticated session inside ZAP * @throws ClientApiException */ - public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl, ClientApiSupport clientApiSupport) throws ClientApiException { + public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { LOG.info("Removing old session data inside ZAP if necessary."); - cleanUpOldSessionDataIfNecessary(targetUrl, clientApiSupport); + cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); LOG.info("Add new HTTP session token: {} to ZAP.", SESSION_TOKEN_IDENTIFIER); - clientApiSupport.addHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); + clientApiWrapper.addHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); LOG.info("Create new empty HTTP session: {} in ZAP.", SESSION_IDENTIFIER); - clientApiSupport.createEmptyHTTPSession(targetUrl, SESSION_IDENTIFIER); + clientApiWrapper.createEmptyHTTPSession(targetUrl, SESSION_IDENTIFIER); LOG.info("Adding all cookies to ZAP HTTP session: {}", SESSION_IDENTIFIER); for (Cookie cookie : firefox.manage().getCookies()) { - clientApiSupport.setHTTPSessionTokenValue(targetUrl, SESSION_IDENTIFIER, cookie.getName(), cookie.getValue()); + clientApiWrapper.setHTTPSessionTokenValue(targetUrl, SESSION_IDENTIFIER, cookie.getName(), cookie.getValue()); } LOG.info("Set ZAP HTTP session: {} as active session to use.", SESSION_IDENTIFIER); - clientApiSupport.setActiveHTTPSession(targetUrl, SESSION_IDENTIFIER); + clientApiWrapper.setActiveHTTPSession(targetUrl, SESSION_IDENTIFIER); - addJwtAsReplacerRuleToZap(firefox, clientApiSupport); + addJwtAsReplacerRuleToZap(firefox, clientApiWrapper); String followRedirects = "true"; LOG.info("Accessing target URL: {} via ZAP to make sure it is added to the sites tree.", targetUrl); - clientApiSupport.accessUrlViaZap(targetUrl, followRedirects); + clientApiWrapper.accessUrlViaZap(targetUrl, followRedirects); return SESSION_IDENTIFIER; } @@ -64,27 +64,27 @@ public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl * a previous run. * * @param targetUrl - * @param clientApiSupport + * @param clientApiWrapper */ - public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiSupport clientApiSupport) { + public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiWrapper clientApiWrapper) { try { - clientApiSupport.removeHTTPSession(targetUrl, SESSION_IDENTIFIER); + clientApiWrapper.removeHTTPSession(targetUrl, SESSION_IDENTIFIER); } catch (ClientApiException e) { LOG.info("Could not find old HTTP session, nothing needs to be removed."); } try { - clientApiSupport.removeHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); + clientApiWrapper.removeHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); } catch (ClientApiException e) { LOG.info("Could not find old HTTP session token, nothing needs to be removed."); } try { - clientApiSupport.removeReplacerRule(JWT_REPLACER_DESCRIPTION); + clientApiWrapper.removeReplacerRule(JWT_REPLACER_DESCRIPTION); } catch (ClientApiException e) { LOG.info("Could not find old JWT repalcer rule, nothing needs to be removed."); } } - private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiSupport clientApiSupport) throws ClientApiException { + private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrapper clientApiWrapper) throws ClientApiException { String enabled = "true"; // "REQ_HEADER" means the header entry will be added to the requests if not // existing or replaced if already existing @@ -109,7 +109,7 @@ private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiSupport c String value = localStorage.get(key); if (isJWT(value)) { replacement = "Bearer %s".formatted(value); - clientApiSupport.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiWrapper.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); return; } } @@ -119,7 +119,7 @@ private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiSupport c String value = sessionStorage.get(key); if (isJWT(value)) { replacement = "Bearer %s".formatted(value); - clientApiSupport.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + clientApiWrapper.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); return; } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java index b7dd70be73..71405bca16 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java @@ -21,6 +21,6 @@ public class EnvironmentVariableConstants { public static final String PDS_JOB_EVENTS_FOLDER = "PDS_JOB_EVENTS_FOLDER"; - public static final String PDS_TEMPLATE_FOLDER = "PDS_TEMPLATE_FOLDER"; + public static final String ZAP_GROOVY_LOGIN_SCRIPT_FILE = "ZAP_GROOVY_LOGIN_SCRIPT_FILE"; } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java index 73168048f0..1a1fecbede 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java @@ -29,7 +29,7 @@ public byte[] decodeIfNecessary(String seed, EncodingType encodingType) { seed = seed.replaceAll("\\s", ""); EncodingType realEncodingType = encodingType; - if (encodingType == EncodingType.AUTODETECT) { + if (realEncodingType == null || realEncodingType == EncodingType.AUTODETECT) { realEncodingType = detectEncoding(seed); } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index 4fe6c25cde..158698c337 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -544,14 +544,14 @@ void no_template_data_results_in_no_template_data_set() { when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - when(settings.getTemplateFolder()).thenReturn(null); - when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + when(settings.getGroovyLoginScriptFile()).thenReturn(null); + when(envVariableReader.readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE)).thenReturn(null); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsString(PDS_TEMPLATE_FOLDER); + verify(envVariableReader, times(1)).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); assertNull(result.getGroovyScriptLoginFile()); } @@ -561,16 +561,16 @@ void cmd_param_set_results_in_environment_variable_reader_not_being_called() { when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - String templateDir = "templateDir"; - when(settings.getTemplateFolder()).thenReturn(templateDir); - when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(null); + String groovyScriptFile = "script.groovy"; + when(settings.getGroovyLoginScriptFile()).thenReturn(groovyScriptFile); + when(envVariableReader.readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE)).thenReturn(null); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, never()).readAsString(PDS_TEMPLATE_FOLDER); - assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); + verify(envVariableReader, never()).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); + assertEquals(groovyScriptFile, result.getGroovyScriptLoginFile().getName()); } @Test @@ -579,16 +579,16 @@ void cmd_param_not_set_results_in_environment_variable_reader_being_called_as_fa when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); CommandLineSettings settings = createSettingsMockWithNecessaryPartsWithoutRuleFiles(); - String templateDir = "templateDir"; - when(settings.getTemplateFolder()).thenReturn(null); - when(envVariableReader.readAsString(PDS_TEMPLATE_FOLDER)).thenReturn(templateDir); + String groovyScriptFile = "script.groovy"; + when(settings.getGroovyLoginScriptFile()).thenReturn(null); + when(envVariableReader.readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE)).thenReturn(groovyScriptFile); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsString(PDS_TEMPLATE_FOLDER); - assertEquals(templateDir, result.getGroovyScriptLoginFile().getParent()); + verify(envVariableReader, times(1)).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); + assertEquals(groovyScriptFile, result.getGroovyScriptLoginFile().getName()); } private CommandLineSettings createSettingsMockWithNecessaryParts() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java index 0fab91ec18..b96cd0ed04 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java @@ -34,8 +34,8 @@ import com.mercedesbenz.sechub.zapwrapper.config.ProxyInformation; import com.mercedesbenz.sechub.zapwrapper.config.ZAPAcceptedBrowserId; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; -import com.mercedesbenz.sechub.zapwrapper.config.auth.AuthenticationType; -import com.mercedesbenz.sechub.zapwrapper.config.auth.SessionManagementType; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapAuthenticationType; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapSessionManagementType; import com.mercedesbenz.sechub.zapwrapper.config.data.DeactivatedRuleReferences; import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; @@ -43,7 +43,7 @@ import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; import com.mercedesbenz.sechub.zapwrapper.helper.ZapProductMessageHelper; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; import com.mercedesbenz.sechub.zapwrapper.scan.ZapScanner.UserInformation; import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLogin; import com.mercedesbenz.sechub.zapwrapper.util.SystemUtil; @@ -53,7 +53,7 @@ class ZapScannerTest { private ZapScanner scannerToTest; - private ClientApiSupport clientApiSupport; + private ClientApiWrapper clientApiWrapper; private ZapScanContext scanContext; private ZapPDSEventHandler zapPDSEventHandler; private SystemUtil systemUtil; @@ -67,7 +67,7 @@ class ZapScannerTest { @BeforeEach void beforeEach() { - clientApiSupport = mock(); + clientApiWrapper = mock(); scanContext = mock(); zapPDSEventHandler = mock(); systemUtil = mock(); @@ -78,7 +78,7 @@ void beforeEach() { // create scanner to test /* @formatter:off */ - scannerToTest = new ZapScanner(clientApiSupport, + scannerToTest = new ZapScanner(clientApiWrapper, scanContext, new ScanDurationHelper(), new UrlUtil(), @@ -92,8 +92,8 @@ void beforeEach() { when(scanContext.getZapPDSEventHandler()).thenReturn(zapPDSEventHandler); when(scanContext.getAjaxSpiderBrowserId()).thenReturn(BROWSER_ID); - when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("authSessionId"); - doNothing().when(scriptLogin).cleanUpScriptLoginData(anyString(), eq(clientApiSupport)); + when(scriptLogin.login(scanContext, clientApiWrapper)).thenReturn("authSessionId"); + doNothing().when(scriptLogin).cleanUpScriptLoginData(anyString(), eq(clientApiWrapper)); doNothing().when(messageHelper).writeProductError(any()); doNothing().when(messageHelper).writeProductMessages(any()); @@ -102,28 +102,28 @@ void beforeEach() { doNothing().when(systemUtil).waitForMilliseconds(anyInt()); when(systemUtil.getCurrentTimeInMilliseconds()).thenCallRealMethod(); - doNothing().when(scriptLogin).cleanUpScriptLoginData(any(), eq(clientApiSupport)); + doNothing().when(scriptLogin).cleanUpScriptLoginData(any(), eq(clientApiWrapper)); } @Test void setup_standard_configuration_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(clientApiSupport.createNewSession(scanContext.getContextName(), "true")).thenReturn(null); - when(clientApiSupport.configureMaximumAlertsForEachRule("0")).thenReturn(null); - when(clientApiSupport.enableAllPassiveScannerRules()).thenReturn(null); - when(clientApiSupport.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); - when(clientApiSupport.setAjaxSpiderBrowserId(BROWSER_ID)) + when(clientApiWrapper.createNewSession(scanContext.getContextName(), "true")).thenReturn(null); + when(clientApiWrapper.configureMaximumAlertsForEachRule("0")).thenReturn(null); + when(clientApiWrapper.enableAllPassiveScannerRules()).thenReturn(null); + when(clientApiWrapper.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); + when(clientApiWrapper.setAjaxSpiderBrowserId(BROWSER_ID)) .thenReturn(null); /* execute */ scannerToTest.setupStandardConfiguration(); /* test */ - verify(clientApiSupport, times(1)).createNewSession(scanContext.getContextName(), "true"); - verify(clientApiSupport, times(1)).configureMaximumAlertsForEachRule("0"); - verify(clientApiSupport, times(1)).enableAllPassiveScannerRules(); - verify(clientApiSupport, times(1)).enableAllActiveScannerRulesForPolicy(null); - verify(clientApiSupport, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); + verify(clientApiWrapper, times(1)).createNewSession(scanContext.getContextName(), "true"); + verify(clientApiWrapper, times(1)).configureMaximumAlertsForEachRule("0"); + verify(clientApiWrapper, times(1)).enableAllPassiveScannerRules(); + verify(clientApiWrapper, times(1)).enableAllActiveScannerRulesForPolicy(null); + verify(clientApiWrapper, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); } @Test @@ -139,8 +139,8 @@ void deactivate_rules_ruleset_or_rules_to_deactivate_null_results_in_nothing_is_ scannerToTest.deactivateRules(new ZapFullRuleset(), deactivatedReferences); /* test */ - verify(clientApiSupport, never()).disablePassiveScannerRule(any()); - verify(clientApiSupport, never()).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiWrapper, never()).disablePassiveScannerRule(any()); + verify(clientApiWrapper, never()).disableActiveScannerRuleForPolicy(any(), any()); } @Test @@ -156,28 +156,28 @@ void deactivate_rules_results_in_rules_are_deactivated() throws ClientApiExcepti String json = TestFileReader.readTextFromFile("src/test/resources/zap-available-rules/zap-full-ruleset.json"); ZapFullRuleset ruleSet = new ZapFullRuleset().fromJSON(json); - when(clientApiSupport.disablePassiveScannerRule(any())).thenReturn(null); - when(clientApiSupport.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); + when(clientApiWrapper.disablePassiveScannerRule(any())).thenReturn(null); + when(clientApiWrapper.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); /* execute */ scannerToTest.deactivateRules(ruleSet, deactivatedReferences); /* test */ - verify(clientApiSupport, times(1)).disablePassiveScannerRule(any()); - verify(clientApiSupport, times(2)).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiWrapper, times(1)).disablePassiveScannerRule(any()); + verify(clientApiWrapper, times(2)).disableActiveScannerRuleForPolicy(any(), any()); } @Test void setup_addtional_proxy_information_with_proxy_information_null_results_in_proxy_disabled() throws ClientApiException { /* prepare */ - when(clientApiSupport.setHttpProxyEnabled("false")).thenReturn(null); + when(clientApiWrapper.setHttpProxyEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(null); /* test */ - verify(clientApiSupport, times(1)).setHttpProxyEnabled("false"); + verify(clientApiWrapper, times(1)).setHttpProxyEnabled("false"); } @Test @@ -188,24 +188,24 @@ void setup_addtional_proxy_information_results_in_proxy_enabled() throws ClientA var portAsString = String.valueOf(port); ProxyInformation proxyInformation = new ProxyInformation(host, port); - when(clientApiSupport.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); - when(clientApiSupport.setHttpProxyEnabled("true")).thenReturn(null); - when(clientApiSupport.setHttpProxyAuthEnabled("false")).thenReturn(null); + when(clientApiWrapper.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); + when(clientApiWrapper.setHttpProxyEnabled("true")).thenReturn(null); + when(clientApiWrapper.setHttpProxyAuthEnabled("false")).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(proxyInformation); /* test */ - verify(clientApiSupport, times(1)).configureHttpProxy(host, portAsString, null, null, null); - verify(clientApiSupport, times(1)).setHttpProxyEnabled("true"); - verify(clientApiSupport, times(1)).setHttpProxyAuthEnabled("false"); + verify(clientApiWrapper, times(1)).configureHttpProxy(host, portAsString, null, null, null); + verify(clientApiWrapper, times(1)).setHttpProxyEnabled("true"); + verify(clientApiWrapper, times(1)).setHttpProxyAuthEnabled("false"); } @Test void create_context_results_in_expected_calls() throws ClientApiException { /* prepare */ String expectedContextId = "random-id"; - when(clientApiSupport.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); + when(clientApiWrapper.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); /* execute */ String contextId = scannerToTest.createContext(); @@ -213,7 +213,7 @@ void create_context_results_in_expected_calls() throws ClientApiException { /* test */ assertEquals(expectedContextId, contextId); verify(scanContext, times(2)).getContextName(); - verify(clientApiSupport, times(1)).createNewContext(CONTEXT_NAME); + verify(clientApiWrapper, times(1)).createNewContext(CONTEXT_NAME); } @Test @@ -222,13 +222,13 @@ void add_replacer_rules_for_headers_with_no_headers_results_add_replacer_rule_is SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiSupport, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -239,14 +239,14 @@ void add_replacer_rules_for_headers_with_no_onlyForUrls_results_add_replacer_rul SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiSupport, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @ParameterizedTest @@ -257,7 +257,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); @@ -270,7 +270,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiSupport, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); } @Test @@ -315,14 +315,14 @@ void add_replacer_rules_for_headers_with_data_section_results_add_replacer_rule_ headerFiles.put("Other", new File("src/test/resources/header-value-files/token.txt")); when(scanContext.getHeaderValueFiles()).thenReturn(headerFiles); - when(clientApiSupport.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiSupport, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); - verify(clientApiSupport, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); + verify(clientApiWrapper, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); + verify(clientApiWrapper, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); } @ParameterizedTest @@ -344,9 +344,9 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o Set excludes = new HashSet<>(helper.createListOfUrls(targetUrl, excludesList)); when(scanContext.getZapURLsExcludeSet()).thenReturn(excludes); - when(clientApiSupport.addIncludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); - when(clientApiSupport.accessUrlViaZap(any(), any())).thenReturn(apiResponse); - when(clientApiSupport.addExcludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addIncludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.accessUrlViaZap(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addExcludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); /* @formatter:off */ int includesWithoutWildcards = (int) includes.stream() @@ -358,10 +358,10 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o scannerToTest.addIncludedAndExcludedUrlsToContext(); /* test */ - verify(clientApiSupport, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); + verify(clientApiWrapper, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); // make sure this method is only called for includes without wildcards - verify(clientApiSupport, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); - verify(clientApiSupport, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); + verify(clientApiWrapper, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); + verify(clientApiWrapper, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); } @Test @@ -370,15 +370,15 @@ void import_openapi_file_but_api_file_is_null_api_support_is_never_called() thro String contextId = "context-id"; when(scanContext.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); - when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); - when(clientApiSupport.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiSupport, never()).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @@ -395,13 +395,13 @@ void import_openapi_file_api_support_is_called_once(String sechubConfigFile) thr when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiSupport, times(1)).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), any()); } @ParameterizedTest @@ -413,15 +413,15 @@ void import_openapi_defintion_from_url_api_support_is_called_once(String sechubC SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); - when(clientApiSupport.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiSupport, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @ParameterizedTest @@ -438,26 +438,26 @@ void import_openapi_from_file_and_from_url_api_support_is_called_once(String sec when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiSupport, times(1)).importOpenApiFile(any(), any(), any()); - verify(clientApiSupport, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); } @Test void import_client_certificate_file_but_client_certificate_file_is_null_api_support_is_never_called() throws ClientApiException { /* prepare */ - when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiSupport, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); } @Test @@ -479,13 +479,13 @@ void try_import_without_client_certificate_file_api_support_is_never_called() th when(scanContext.getClientCertificateFile()).thenReturn(clientCertificateFile); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiSupport, never()).importPkcs12ClientCertificate(any(), any()); + verify(clientApiWrapper, never()).importPkcs12ClientCertificate(any(), any()); } @Test @@ -514,13 +514,13 @@ void import_client_certificate_file_api_support_is_called_once() throws ClientAp when(clientCertificateFile.exists()).thenReturn(true); - when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiSupport, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiWrapper, times(1)).importPkcs12ClientCertificate(any(), any()); } @Test @@ -547,13 +547,13 @@ void import_client_certificate_file_but_without_password_api_support_is_called_o when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(clientCertificateFile.exists()).thenReturn(true); - when(clientApiSupport.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importPkcs12ClientCertificate(any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.importClientCertificate(); /* test */ - verify(clientApiSupport, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiWrapper, times(1)).importPkcs12ClientCertificate(any(), any()); } @ParameterizedTest @@ -585,18 +585,18 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr BasicLoginConfiguration basicLoginConfiguration = sechubWebScanConfig.getLogin().get().getBasic().get(); String userName = new String(basicLoginConfiguration.getUser()); - String zapAuthenticationMethod = AuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); - String zapSessionManagementMethod = SessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + String zapAuthenticationMethod = ZapAuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = ZapSessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); when(scanContext.getTargetUrl()).thenReturn(targetUrl); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); - when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); - when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); - when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); + when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); @@ -607,12 +607,12 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr verify(scanContext, times(2)).getTargetUrl(); - verify(clientApiSupport, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(clientApiSupport, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); - verify(clientApiSupport, times(1)).createNewUser(contextId, userName); - verify(clientApiSupport, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(clientApiSupport, times(1)).setForcedUser(contextId, userId); - verify(clientApiSupport, times(1)).setForcedUserModeEnabled(true); + verify(clientApiWrapper, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiWrapper, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); + verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiWrapper, times(1)).setForcedUser(contextId, userId); + verify(clientApiWrapper, times(1)).setForcedUserModeEnabled(true); } @Test @@ -627,28 +627,28 @@ void configure_login_inside_zap_using_script_auth_without_script_file_results_in WebLoginConfiguration login = new WebLoginConfiguration(); sechubWebScanConfig.setLogin(Optional.of(login)); - String zapAuthenticationMethod = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); - String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + String zapAuthenticationMethod = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("zap-auth-session"); + when(scriptLogin.login(scanContext, clientApiWrapper)).thenReturn("zap-auth-session"); when(scanContext.getTargetUrl()).thenReturn(targetUrl); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(scanContext.getGroovyScriptLoginFile()).thenReturn(null); - when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); - when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); - when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); - when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); + when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); /* test */ assertNull(userInformation); - verify(scriptLogin, never()).login(scanContext, clientApiSupport); + verify(scriptLogin, never()).login(scanContext, clientApiWrapper); verify(scanContext, times(1)).getGroovyScriptLoginFile(); } @@ -664,22 +664,22 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu WebLoginConfiguration login = new WebLoginConfiguration(); sechubWebScanConfig.setLogin(Optional.of(login)); - String zapAuthenticationMethod = AuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); - String zapSessionManagementMethod = SessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + String zapAuthenticationMethod = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + String zapSessionManagementMethod = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); - when(scriptLogin.login(scanContext, clientApiSupport)).thenReturn("zap-auth-session"); + when(scriptLogin.login(scanContext, clientApiWrapper)).thenReturn("zap-auth-session"); when(scanContext.getTargetUrl()).thenReturn(targetUrl); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(scanContext.getGroovyScriptLoginFile()).thenReturn(scriptFile); - when(clientApiSupport.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); - when(clientApiSupport.createNewUser(contextId, userName)).thenReturn(userId); - when(clientApiSupport.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); - when(clientApiSupport.setForcedUser(contextId, userId)).thenReturn(apiResponse); - when(clientApiSupport.setForcedUserModeEnabled(true)).thenReturn(apiResponse); + when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); + when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUser(contextId, userId)).thenReturn(apiResponse); + when(clientApiWrapper.setForcedUserModeEnabled(true)).thenReturn(apiResponse); /* execute */ UserInformation userInformation = scannerToTest.setupLoginInsideZapContext(contextId); @@ -688,15 +688,15 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu assertEquals(userName, userInformation.userName()); assertEquals(userId, userInformation.zapuserId()); - verify(scriptLogin, times(1)).login(scanContext, clientApiSupport); + verify(scriptLogin, times(1)).login(scanContext, clientApiWrapper); verify(scanContext, times(2)).getGroovyScriptLoginFile(); - verify(clientApiSupport, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(clientApiSupport, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); - verify(clientApiSupport, times(1)).createNewUser(contextId, userName); - verify(clientApiSupport, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(clientApiSupport, times(1)).setForcedUser(contextId, userId); - verify(clientApiSupport, times(1)).setForcedUserModeEnabled(true); + verify(clientApiWrapper, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiWrapper, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); + verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiWrapper, times(1)).setForcedUser(contextId, userId); + verify(clientApiWrapper, times(1)).setForcedUserModeEnabled(true); } @Test @@ -705,14 +705,14 @@ void generate_report_calls_api_support_once() throws ClientApiException { when(scanContext.getReportFile()) .thenReturn(Paths.get("src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json")); - when(clientApiSupport.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), + when(clientApiWrapper.generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.generateZapReport(); /* test */ - verify(clientApiSupport, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), + verify(clientApiWrapper, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); } @@ -721,14 +721,14 @@ void cleanup_after_scan() throws ClientApiException { /* prepare */ SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); + when(clientApiWrapper.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); /* test */ - verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); + verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @ParameterizedTest @@ -738,16 +738,16 @@ void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_r SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); + when(clientApiWrapper.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(clientApiSupport, times(times + 1)).removeReplacerRule(any()); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); + verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiWrapper, times(times + 1)).removeReplacerRule(any()); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @ParameterizedTest @@ -757,7 +757,7 @@ void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rule SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiSupport.removeReplacerRule(any())).thenReturn(apiResponse); + when(clientApiWrapper.removeReplacerRule(any())).thenReturn(apiResponse); /* execute */ scannerToTest.cleanUp(); @@ -770,9 +770,9 @@ void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rule times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiSupport, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(clientApiSupport, times(times + 1)).removeReplacerRule(any()); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiSupport); + verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiWrapper, times(times + 1)).removeReplacerRule(any()); + verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test @@ -785,7 +785,7 @@ void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_e long scanDuration = 20000L; when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiSupport.stopAjaxSpider()).thenReturn(null); + when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -796,7 +796,7 @@ void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_e assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiSupport, times(1)).stopAjaxSpider(); + verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @Test @@ -807,16 +807,16 @@ void wait_for_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApi long scanDuration = 1000L; when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiSupport.stopAjaxSpider()).thenReturn(null); - when(clientApiSupport.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); + when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ scannerToTest.waitForAjaxSpiderResults(scanDuration); /* test */ verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiSupport, atLeast(1)).getAjaxSpiderStatus(); - verify(clientApiSupport, times(1)).stopAjaxSpider(); + verify(clientApiWrapper, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @Test @@ -830,7 +830,7 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ long scanDuration = 20000L; when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -841,7 +841,7 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiSupport, times(1)).stopSpiderScan(scanId); + verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); } @Test @@ -855,9 +855,9 @@ void wait_for_spider_scan_ended_results_in_expected_calls() throws ClientApiExce ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); - when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiSupport.getSpiderStatusForScan(scanId)).thenReturn(42); - when(clientApiSupport.logFullSpiderResults(scanId)).thenReturn(0L); + when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiWrapper.getSpiderStatusForScan(scanId)).thenReturn(42); + when(clientApiWrapper.logFullSpiderResults(scanId)).thenReturn(0L); /* execute */ scannerToTest.waitForSpiderResults(scanId, scanDuration); @@ -865,9 +865,9 @@ void wait_for_spider_scan_ended_results_in_expected_calls() throws ClientApiExce /* test */ verify(scanContext, times(1)).isActiveScanEnabled(); verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiSupport, atLeast(1)).getSpiderStatusForScan(scanId); - verify(clientApiSupport, times(1)).stopSpiderScan(scanId); - verify(clientApiSupport, times(1)).logFullSpiderResults(scanId); + verify(clientApiWrapper, atLeast(1)).getSpiderStatusForScan(scanId); + verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); + verify(clientApiWrapper, times(1)).logFullSpiderResults(scanId); } @Test @@ -881,7 +881,7 @@ void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_ when(scanContext.isActiveScanEnabled()).thenReturn(false); when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); - when(clientApiSupport.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); + when(clientApiWrapper.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -893,7 +893,7 @@ void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_ verify(zapPDSEventHandler, times(2)).isScanCancelled(); verify(scanContext, times(1)).isActiveScanEnabled(); verify(scanContext, times(1)).isAjaxSpiderEnabled(); - verify(clientApiSupport, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(clientApiWrapper, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test @@ -905,7 +905,7 @@ void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws Clien when(scanContext.isActiveScanEnabled()).thenReturn(false); when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); - when(clientApiSupport.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); + when(clientApiWrapper.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); /* execute */ scannerToTest.passiveScan(scanDuration); @@ -913,7 +913,7 @@ void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws Clien /* test */ verify(scanContext, times(1)).isActiveScanEnabled(); verify(scanContext, times(1)).isAjaxSpiderEnabled(); - verify(clientApiSupport, times(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(clientApiWrapper, times(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test @@ -925,8 +925,8 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); - when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(42); - when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); + when(clientApiWrapper.getActiveScannerStatusForScan(scanId)).thenReturn(42); + when(clientApiWrapper.stopActiveScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { @@ -936,8 +936,8 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(clientApiSupport, never()).getActiveScannerStatusForScan(scanId); - verify(clientApiSupport, times(1)).stopActiveScan(scanId); + verify(clientApiWrapper, never()).getActiveScannerStatusForScan(scanId); + verify(clientApiWrapper, times(1)).stopActiveScan(scanId); } @Test @@ -948,15 +948,15 @@ void wait_for_activeScan_scan_is_ended_results_in_expected_calls() throws Client when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); + when(clientApiWrapper.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(clientApiWrapper.stopActiveScan(scanId)).thenReturn(null); /* execute */ scannerToTest.waitForActiveScanResults(scanId, scanDuration); /* test */ - verify(clientApiSupport, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiSupport, times(1)).stopActiveScan(scanId); + verify(clientApiWrapper, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(clientApiWrapper, times(1)).stopActiveScan(scanId); } @Test @@ -967,16 +967,16 @@ void run_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiExcep long scanDuration = 1000L; when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiSupport.stopAjaxSpider()).thenReturn(null); - when(clientApiSupport.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); + when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("stopped"); /* execute */ scannerToTest.runAjaxSpider(scanDuration); /* test */ verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiSupport, atLeast(1)).getAjaxSpiderStatus(); - verify(clientApiSupport, times(1)).stopAjaxSpider(); + verify(clientApiWrapper, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @Test @@ -991,10 +991,10 @@ void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); - when(clientApiSupport.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiSupport.getSpiderStatusForScan(scanId)).thenReturn(42); - when(clientApiSupport.logFullSpiderResults(scanId)).thenReturn(0L); - when(clientApiSupport.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); + when(clientApiWrapper.getSpiderStatusForScan(scanId)).thenReturn(42); + when(clientApiWrapper.logFullSpiderResults(scanId)).thenReturn(0L); + when(clientApiWrapper.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); /* execute */ scannerToTest.runSpider(scanDuration); @@ -1002,10 +1002,10 @@ void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException /* test */ verify(scanContext, times(1)).isActiveScanEnabled(); verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiSupport, atLeast(1)).getSpiderStatusForScan(scanId); - verify(clientApiSupport, times(1)).stopSpiderScan(scanId); - verify(clientApiSupport, times(1)).logFullSpiderResults(scanId); - verify(clientApiSupport, times(1)).startSpiderScan(any(), any(), any(), any(), any()); + verify(clientApiWrapper, atLeast(1)).getSpiderStatusForScan(scanId); + verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); + verify(clientApiWrapper, times(1)).logFullSpiderResults(scanId); + verify(clientApiWrapper, times(1)).startSpiderScan(any(), any(), any(), any(), any()); } @Test @@ -1017,18 +1017,18 @@ void run_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiEx when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(clientApiSupport.getActiveScannerStatusForScan(scanId)).thenReturn(100); - when(clientApiSupport.stopActiveScan(scanId)).thenReturn(null); - when(clientApiSupport.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); - when(clientApiSupport.atLeastOneURLDetected()).thenReturn(true); + when(clientApiWrapper.getActiveScannerStatusForScan(scanId)).thenReturn(100); + when(clientApiWrapper.stopActiveScan(scanId)).thenReturn(null); + when(clientApiWrapper.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiWrapper.atLeastOneURLDetected()).thenReturn(true); /* execute */ scannerToTest.runActiveScan(scanDuration); /* test */ - verify(clientApiSupport, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiSupport, times(1)).stopActiveScan(scanId); - verify(clientApiSupport, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(clientApiWrapper, times(1)).stopActiveScan(scanId); + verify(clientApiWrapper, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); } static Stream headerPartWithoutOnlyForUrlsTestNamedArguments() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java index 7b79b39526..7ada85c687 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java @@ -19,13 +19,13 @@ import org.zaproxy.clientapi.core.ApiResponse; import org.zaproxy.clientapi.core.ClientApiException; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; class ZapScriptLoginSessionGrabberTest { private ZapScriptLoginSessionGrabber sessionGrabberToTest; - private ClientApiSupport clientApiSupport; + private ClientApiWrapper clientApiWrapper; private FirefoxDriver firefox; private Options webDriverOptions; @@ -40,7 +40,7 @@ void beforeEach() { firefox = mock(); webDriverOptions = mock(); - clientApiSupport = mock(ClientApiSupport.class, new Answer() { + clientApiWrapper = mock(ClientApiWrapper.class, new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { // Return the same response for any method call @@ -68,27 +68,27 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE when(firefox.executeScript(anyString())).thenReturn(storage); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiSupport); + sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); /* test */ verify(firefox, times(1)).manage(); verify(webDriverOptions, times(1)).getCookies(); verify(firefox, times(1)).executeScript(anyString()); - verify(clientApiSupport, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).removeReplacerRule(any()); - verify(clientApiSupport, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); - verify(clientApiSupport, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).removeReplacerRule(any()); + verify(clientApiWrapper, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); + verify(clientApiWrapper, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); - verify(clientApiSupport, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } @Test - void no_cookie_and_no_jwt_results_clienapisupport_not_adding_replacer_rule() throws ClientApiException { + void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() throws ClientApiException { /* prepare */ when(firefox.manage()).thenReturn(webDriverOptions); @@ -96,28 +96,28 @@ void no_cookie_and_no_jwt_results_clienapisupport_not_adding_replacer_rule() thr when(firefox.executeScript(anyString())).thenReturn(Collections.emptyMap()); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiSupport); + sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); /* test */ // both browser storages are checked now without JWT verify(firefox, times(2)).executeScript(anyString()); // no JWT can be added - verify(clientApiSupport, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); // no cookie can be added - verify(clientApiSupport, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); + verify(clientApiWrapper, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); // the other calls must be the same as on every execution without error verify(firefox, times(1)).manage(); verify(webDriverOptions, times(1)).getCookies(); - verify(clientApiSupport, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).removeReplacerRule(any()); - verify(clientApiSupport, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).removeReplacerRule(any()); + verify(clientApiWrapper, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(clientApiSupport, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java index f5a54fc763..bac27a65e4 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java @@ -22,7 +22,7 @@ import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; -import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiSupport; +import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; class ZapScriptLoginTest { @@ -34,7 +34,7 @@ class ZapScriptLoginTest { private ZapWrapperGroovyScriptExecutor groovyScriptExecutor = mock(); private ZapScriptLoginSessionGrabber sessionGrabber = mock(); - private ClientApiSupport clientApiSupport = mock(); + private ClientApiWrapper clientApiWrapper = mock(); private FirefoxDriver firefox = mock(); @BeforeEach @@ -42,7 +42,7 @@ void beforeEach() { webDriverFactory = mock(); groovyScriptExecutor = mock(); sessionGrabber = mock(); - clientApiSupport = mock(); + clientApiWrapper = mock(); firefox = mock(); scriptLoginToTest = new ZapScriptLogin(webDriverFactory, groovyScriptExecutor, sessionGrabber); @@ -56,15 +56,15 @@ void script_login_execution_is_perfomed_as_expected() throws Exception { when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ - scriptLoginToTest.login(scanContext, clientApiSupport); + scriptLoginToTest.login(scanContext, clientApiWrapper); /* test */ verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); verify(firefox, times(1)).quit(); } @@ -75,15 +75,15 @@ void script_can_not_be_read_results_in_firefox_closed_and_session_grabber_never_ when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); doThrow(IOException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); verify(firefox, times(1)).quit(); } @@ -94,15 +94,15 @@ void script_login_execution_fails_results_in_firefox_closed_and_session_grabber_ when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); doThrow(ScriptException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport)).thenReturn(AUTH_SESSION); + when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); verify(firefox, times(1)).quit(); } @@ -113,15 +113,15 @@ void session_grabbing_fails_results_in_firefox_closed() throws Exception { when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - doThrow(ClientApiException.class).when(sessionGrabber).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + doThrow(ClientApiException.class).when(sessionGrabber).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); /* execute */ - assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiSupport)); + assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiSupport); + verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); verify(firefox, times(1)).quit(); } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java index 77aee2a729..7e5daa73c2 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java @@ -4,6 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.nio.charset.StandardCharsets; + import org.apache.commons.codec.DecoderException; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -13,16 +15,29 @@ class StringDecoderTest { - private StringDecoder supportToTest = new StringDecoder(); + private StringDecoder decoderToTest = new StringDecoder(); @Test - void when_secret_key_is_null_an_exception_is_thrown() { + void when_seed_is_null_an_exception_is_thrown() { /* execute + test */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> supportToTest.decodeIfNecessary(null, EncodingType.AUTODETECT)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> decoderToTest.decodeIfNecessary(null, EncodingType.AUTODETECT)); assertEquals("The secret key must not be null!", exception.getMessage()); } + @Test + void when_encoding_type_is_null_autodetect_is_performed() { + /* prepare */ + String seed = "dGVzdC1zdHJpbmc="; + String expected = "test-string"; + + /* execute */ + byte[] decodedSeed = decoderToTest.decodeIfNecessary(seed, null); + + /* test */ + assertEquals(expected, new String(decodedSeed, StandardCharsets.UTF_8)); + } + /* @formatter:off */ @ParameterizedTest @ValueSource(strings = { "746573742d737472696e67", @@ -39,7 +54,7 @@ void encoded_values_are_decoded_correctly_ignoring_spaces_or_tabs(String value) String expected = "test-string"; /* execute */ - byte[] decoded = supportToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); + byte[] decoded = decoderToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); /* test */ assertEquals(expected, new String(decoded)); @@ -49,7 +64,7 @@ void encoded_values_are_decoded_correctly_ignoring_spaces_or_tabs(String value) @ValueSource(strings = { "���", "NotEncoded!", "@:_DASF2daagjtz", "HelloWorld" }) void not_encoded_values_are_correctly_treated_ignoring_spaces_or_tabs(String value) throws DecoderException { /* execute */ - byte[] decoded = supportToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); + byte[] decoded = decoderToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); /* test */ assertEquals(value, new String(decoded)); From 223b86852bfde5eba178b5825b89bba4dd3fb014 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Fri, 22 Nov 2024 14:51:51 +0100 Subject: [PATCH 08/13] PR review changes part two #3622 - refactored ClientApiWrapper by using real datatypes instead of strings - updated test cases - moved logging to ClientApiWrapper - add additional data to proxy settings --- .../zapwrapper/cli/CommandLineSettings.java | 24 ++ .../zapwrapper/config/ProxyInformation.java | 66 +++- .../zapwrapper/config/ZapScanContext.java | 15 - .../config/ZapScanContextFactory.java | 62 ++-- .../zapwrapper/helper/ScanDurationHelper.java | 72 ---- .../helper/ScanPercentageConstants.java | 44 --- .../internal/scan/ClientApiWrapper.java | 226 ++++++++----- .../sechub/zapwrapper/scan/ZapScanner.java | 310 +++++++----------- .../zapwrapper/scan/login/JWTSupport.java | 26 ++ .../zapwrapper/scan/login/ZapScriptLogin.java | 17 +- .../login/ZapScriptLoginSessionGrabber.java | 74 ++--- .../login/ZapScriptLoginWebDriverFactory.java | 12 +- .../login/ZapWrapperGroovyScriptExecutor.java | 11 +- .../util/EnvironmentVariableConstants.java | 8 +- .../sechub/zapwrapper/util/TOTPGenerator.java | 7 - ...oder.java => ZapWrapperStringDecoder.java} | 13 +- .../config/ZapScanContextFactoryTest.java | 26 +- .../helper/ScanDurationHelperTest.java | 96 ------ .../helper/ZapPDSEventHandlerTest.java | 13 +- .../zapwrapper/scan/ZapScannerTest.java | 252 +++++--------- .../zapwrapper/scan/login/JWTSupportTest.java | 33 ++ .../ZapScriptLoginSessionGrabberTest.java | 16 +- .../zapwrapper/util/TOTPGeneratorTest.java | 4 +- ....java => ZapWrapperStringDecoderTest.java} | 19 +- 24 files changed, 660 insertions(+), 786 deletions(-) delete mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelper.java delete mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanPercentageConstants.java create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/{StringDecoder.java => ZapWrapperStringDecoder.java} (89%) delete mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelperTest.java create mode 100644 sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java rename sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/{StringDecoderTest.java => ZapWrapperStringDecoderTest.java} (80%) diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java index d943089647..eb5bd8ad53 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/cli/CommandLineSettings.java @@ -117,6 +117,30 @@ public int getProxyPort() { return proxyPort; } + @Parameter(names = { "--proxyRealm" }, description = "Specify a proxy realm. You can also set the environment variable " + + EnvironmentVariableConstants.PROXY_REALM_ENV_VARIABLE_NAME + ", instead of using this parameter.", required = false) + private String proxyRealm; + + public String getProxyRealm() { + return proxyRealm; + } + + @Parameter(names = { "--proxyUsername" }, description = "Specify a proxy username. You can also set the environment variable " + + EnvironmentVariableConstants.PROXY_USERNAME_ENV_VARIABLE_NAME + ", instead of using this parameter.", required = false) + private String proxyUsername; + + public String getProxyUsername() { + return proxyUsername; + } + + @Parameter(names = { "--proxyPassword" }, description = "Specify a proxy password. You can also set the environment variable " + + EnvironmentVariableConstants.PROXY_PASSWORD_ENV_VARIABLE_NAME + ", instead of using this parameter.", required = false) + private String proxyPassword; + + public String getProxyPassword() { + return proxyPassword; + } + @Parameter(names = { "--fullRulesetfile" }, description = "Specify a file with all rules installed for the Zap.", required = true) private String fullRulesetFile; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ProxyInformation.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ProxyInformation.java index 3bb5385675..95d933bb8e 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ProxyInformation.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ProxyInformation.java @@ -1,13 +1,24 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.config; +import javax.crypto.SealedObject; + +import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; + public class ProxyInformation { private String host; private int port; - public ProxyInformation(String host, int port) { + private String realm; + private String username; + private SealedObject password; + + private ProxyInformation(String host, int port, String realm, String username, String password) { this.host = host; this.port = port; + this.realm = realm; + this.username = username; + this.password = CryptoAccess.CRYPTO_STRING.seal(password); } public String getHost() { @@ -18,4 +29,57 @@ public int getPort() { return port; } + public String getRealm() { + return realm; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return CryptoAccess.CRYPTO_STRING.unseal(password); + } + + public static ProxyInformationBuilder builder() { + return new ProxyInformationBuilder(); + } + + public static class ProxyInformationBuilder { + private String host; + private int port; + private String realm; + private String username; + private String password; + + public ProxyInformationBuilder setHost(String host) { + this.host = host; + return this; + } + + public ProxyInformationBuilder setPort(int port) { + this.port = port; + return this; + } + + public ProxyInformationBuilder setRealm(String realm) { + this.realm = realm; + return this; + } + + public ProxyInformationBuilder setUsername(String username) { + this.username = username; + return this; + } + + public ProxyInformationBuilder setPassword(String password) { + this.password = password; + return this; + } + + public ProxyInformation build() { + return new ProxyInformation(host, port, realm, username, password); + } + } + } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java index 609e217724..8648d6f688 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContext.java @@ -32,8 +32,6 @@ public class ZapScanContext { private URL targetUrl; - private long maxScanDurationInMilliSeconds; - private SecHubWebScanConfiguration secHubWebScanConfiguration; private ProxyInformation proxyInformation; @@ -96,10 +94,6 @@ public URL getTargetUrl() { return targetUrl; } - public long getMaxScanDurationInMilliSeconds() { - return maxScanDurationInMilliSeconds; - } - public SecHubWebScanConfiguration getSecHubWebScanConfiguration() { return secHubWebScanConfiguration; } @@ -197,8 +191,6 @@ public static class ZapScanContextBuilder { private URL targetUrl; - private long maxScanDurationInMilliSeconds; - private SecHubWebScanConfiguration secHubWebScanConfiguration; private ProxyInformation proxyInformation; @@ -265,11 +257,6 @@ public ZapScanContextBuilder setTargetUrl(URL targetUrl) { return this; } - public ZapScanContextBuilder setMaxScanDurationInMilliSeconds(long maxScanDurationInMilliSeconds) { - this.maxScanDurationInMilliSeconds = maxScanDurationInMilliSeconds; - return this; - } - public ZapScanContextBuilder setSecHubWebScanConfiguration(SecHubWebScanConfiguration secHubWebScanConfiguration) { this.secHubWebScanConfiguration = secHubWebScanConfiguration; return this; @@ -360,8 +347,6 @@ public ZapScanContext build() { zapScanContext.contextName = this.contextName; zapScanContext.targetUrl = this.targetUrl; - zapScanContext.maxScanDurationInMilliSeconds = this.maxScanDurationInMilliSeconds; - zapScanContext.secHubWebScanConfiguration = this.secHubWebScanConfiguration; zapScanContext.proxyInformation = this.proxyInformation; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java index d9b5738286..80fcca8584 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactory.java @@ -3,17 +3,12 @@ import java.io.File; import java.net.URL; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration; -import com.mercedesbenz.sechub.commons.model.SecHubTimeUnit; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; import com.mercedesbenz.sechub.zapwrapper.cli.CommandLineSettings; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperExitCode; @@ -29,12 +24,6 @@ public class ZapScanContextFactory { private static final Logger LOG = LoggerFactory.getLogger(ZapScanContextFactory.class); - private static final int SECONDS_IN_MS = 1000; - private static final int MINUTES_IN_MS = 60 * SECONDS_IN_MS; - private static final int HOURS_IN_MS = 60 * MINUTES_IN_MS; - private static final int DAYS_IN_MS = 24 * HOURS_IN_MS; - private static final int DEFAULT_MAX_SCAN_DURATION = 8 * HOURS_IN_MS; - private final EnvironmentVariableReader environmentVariableReader; private final BaseTargetUriFactory targetUriFactory; private final RuleProvider ruleProvider; @@ -84,7 +73,6 @@ public ZapScanContext create(CommandLineSettings settings) { SecHubScanConfiguration sechubScanConfig = secHubScanConfigProvider.getSecHubWebConfiguration(settings.getSecHubConfigFile()); SecHubWebScanConfiguration sechubWebConfig = getSecHubWebConfiguration(sechubScanConfig); - long maxScanDurationInMillis = fetchMaxScanDurationInMillis(sechubWebConfig); List apiDefinitionFiles = fetchApiDefinitionFiles(sechubScanConfig); @@ -115,7 +103,6 @@ public ZapScanContext create(CommandLineSettings settings) { .setAjaxSpiderBrowserId(settings.getAjaxSpiderBrowserId()) .setActiveScanEnabled(settings.isActiveScanEnabled()) .setServerConfig(serverConfig) - .setMaxScanDurationInMilliSeconds(maxScanDurationInMillis) .setSecHubWebScanConfiguration(sechubWebConfig) .setProxyInformation(proxyInformation) .setFullRuleset(fullRuleset) @@ -200,6 +187,9 @@ private ZapServerConfiguration createZapServerConfig(CommandLineSettings setting private ProxyInformation createProxyInformation(CommandLineSettings settings) { String proxyHost = settings.getProxyHost(); int proxyPort = settings.getProxyPort(); + String proxyRealm = settings.getProxyRealm(); + String proxyUsername = settings.getProxyUsername(); + String proxyPassword = settings.getProxyPassword(); if (proxyHost == null) { proxyHost = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_HOST_ENV_VARIABLE_NAME); @@ -207,12 +197,30 @@ private ProxyInformation createProxyInformation(CommandLineSettings settings) { if (proxyPort <= 0) { proxyPort = environmentVariableReader.readAsInt(EnvironmentVariableConstants.PROXY_PORT_ENV_VARIABLE_NAME); } + // optional values + if (proxyRealm == null) { + proxyRealm = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_REALM_ENV_VARIABLE_NAME); + } + if (proxyUsername == null) { + proxyUsername = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_USERNAME_ENV_VARIABLE_NAME); + } + if (proxyPassword == null) { + proxyPassword = environmentVariableReader.readAsString(EnvironmentVariableConstants.PROXY_PASSWORD_ENV_VARIABLE_NAME); + } if (proxyHost == null || proxyPort <= 0) { LOG.info("No proxy settings were provided. Continuing without proxy..."); return null; } - return new ProxyInformation(proxyHost, proxyPort); + /* @formatter:off */ + return ProxyInformation.builder() + .setHost(proxyHost) + .setPort(proxyPort) + .setRealm(proxyRealm) + .setUsername(proxyUsername) + .setPassword(proxyPassword) + .build(); + /* @formatter:on */ } private SecHubWebScanConfiguration getSecHubWebConfiguration(SecHubScanConfiguration sechubConfig) { @@ -290,30 +298,6 @@ private ZapPDSEventHandler createZapEventhandler(CommandLineSettings settings) { return new ZapPDSEventHandler(pdsJobEventsFolder); } - private long fetchMaxScanDurationInMillis(SecHubWebScanConfiguration sechubWebConfig) { - if (sechubWebConfig.getMaxScanDuration().isEmpty()) { - return DEFAULT_MAX_SCAN_DURATION; - } - - SecHubTimeUnit sechubTimeUnit = sechubWebConfig.getMaxScanDuration().get().getUnit(); - int maxScanDuration = sechubWebConfig.getMaxScanDuration().get().getDuration(); - - switch (sechubTimeUnit) { - case DAY: - return maxScanDuration * DAYS_IN_MS; - case HOUR: - return maxScanDuration * HOURS_IN_MS; - case MINUTE: - return maxScanDuration * MINUTES_IN_MS; - case SECOND: - return maxScanDuration * SECONDS_IN_MS; - case MILLISECOND: - return maxScanDuration; - default: - return DEFAULT_MAX_SCAN_DURATION; - } - } - private File fetchGroovyScriptFile(CommandLineSettings settings) { String groovyScriptFile = settings.getGroovyLoginScriptFile(); if (groovyScriptFile == null) { diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelper.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelper.java deleted file mode 100644 index 0c9c7dbe8a..0000000000 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelper.java +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.helper; - -import static com.mercedesbenz.sechub.zapwrapper.helper.ScanPercentageConstants.*; - -public class ScanDurationHelper { - - /** - * - * Computes the max duration for the Zap spider. The computed time depends on - * how many of the other modules are enabled. - * - * @param isActiveScanEnabled - * @param isAjaxSpiderEnabled - * @param maxScanDurationInMinutes - * @return max duration of spider - */ - public long computeSpiderMaxScanDuration(boolean isActiveScanEnabled, boolean isAjaxSpiderEnabled, long maxScanDurationInMinutes) { - double percentage = 0; - - if (isActiveScanEnabled && isAjaxSpiderEnabled) { - percentage = MAX_DURATION_PERCENTAGE_FOR_BOTH_ACTIVE; - } else if (isActiveScanEnabled || isAjaxSpiderEnabled) { - percentage = SPIDER_MAX_DURATION_PERCENTAGE_WHEN_ONLY_ONE_ACTIVE; - } else { - percentage = MAX_DURATION_PERCENTAGE_WHEN_NONE_ACTIVE; - } - return (long) (maxScanDurationInMinutes * percentage); - } - - /** - * Computes the max duration for the Zap spider. The computed time depends on - * how many of the other modules are enabled. - * - * @param isActiveScanEnabled - * @param maxScanDurationInMinutes - * @return max duration of ajax spider - */ - public long computeAjaxSpiderMaxScanDuration(boolean isActiveScanEnabled, long maxScanDurationInMinutes) { - double percentage = 0; - - if (isActiveScanEnabled) { - percentage = AJAX_SPIDER_MAX_DURATION_PERCENTAGE_WHEN_ACTIVE; - } else { - percentage = AJAX_SPIDER_MAX_DURATION_PERCENTAGE_WHEN_NONE_ACTIVE; - } - return (long) (maxScanDurationInMinutes * percentage); - } - - /** - * Computes the max duration for the Zap spider. The computed time depends on - * how many of the other modules are enabled. - * - * @param isActiveScanEnabled - * @param isAjaxSpiderEnabled - * @param maxScanDurationInMinutes - * @return max duration of active spider - */ - public long computePassiveScanMaxScanDuration(boolean isActiveScanEnabled, boolean isAjaxSpiderEnabled, long maxScanDurationInMinutes) { - double percentage = 0; - - if (isActiveScanEnabled && isAjaxSpiderEnabled) { - percentage = MAX_DURATION_PERCENTAGE_FOR_BOTH_ACTIVE; - } else if (isActiveScanEnabled && !isAjaxSpiderEnabled) { - percentage = PASSIVE_SCAN_MAX_DURATION_PERCENTAGE_WHEN_ACTIVE; - } else { - return maxScanDurationInMinutes; - } - return (long) (maxScanDurationInMinutes * percentage); - } - -} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanPercentageConstants.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanPercentageConstants.java deleted file mode 100644 index 9f24480662..0000000000 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanPercentageConstants.java +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.helper; - -public class ScanPercentageConstants { - - /** - * if active scan and ajax spider are disabled spider and passive scan get this - * percentage of the remaining scan time - */ - public static final double MAX_DURATION_PERCENTAGE_WHEN_NONE_ACTIVE = 0.5; - - /** - * if active scan and ajax spider are enabled the spider and the passive scan - * get this percentage of the remaining scan time - */ - public static final double MAX_DURATION_PERCENTAGE_FOR_BOTH_ACTIVE = 0.1; - - /** - * if either active scan or ajax spider are enabled the spider gets this - * percentage of the remaining scan time - */ - public static final double SPIDER_MAX_DURATION_PERCENTAGE_WHEN_ONLY_ONE_ACTIVE = 0.3; - - /** - * if active scan is enabled the ajax spider gets this percentage of the - * remaining scan time - */ - public static final double AJAX_SPIDER_MAX_DURATION_PERCENTAGE_WHEN_ACTIVE = 0.4; - - /** - * if active scan is disabled the ajax spider gets this percentage of the - * remaining scan time - */ - public static final double AJAX_SPIDER_MAX_DURATION_PERCENTAGE_WHEN_NONE_ACTIVE = 0.7; - - /** - * if the active scan is enabled and the ajax spider is disabled the passive - * scan get this percentage of the remaining scan time. We need to check for - * ajax spider as well here, because it was already executed before the passive - * scan. - */ - public static final double PASSIVE_SCAN_MAX_DURATION_PERCENTAGE_WHEN_ACTIVE = 0.3; - -} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java index efd04dfe31..4404cc30f8 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/internal/scan/ClientApiWrapper.java @@ -1,18 +1,18 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.internal.scan; +import java.io.File; import java.net.URL; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.zaproxy.clientapi.core.ApiResponse; -import org.zaproxy.clientapi.core.ApiResponseElement; -import org.zaproxy.clientapi.core.ApiResponseList; -import org.zaproxy.clientapi.core.ApiResponseSet; -import org.zaproxy.clientapi.core.ClientApi; -import org.zaproxy.clientapi.core.ClientApiException; +import org.zaproxy.clientapi.core.*; + +import com.mercedesbenz.sechub.zapwrapper.config.ProxyInformation; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapAuthenticationType; +import com.mercedesbenz.sechub.zapwrapper.config.auth.ZapSessionManagementType; public class ClientApiWrapper { @@ -34,13 +34,13 @@ public ClientApiWrapper(ClientApi clientApi) { * * @param contextName context name that will be created inside the current ZAP * session - * @return api response of ZAP contextId returned by ZAP + * @return contextId returned by ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP * when anything goes wrong communicating with ZAP */ - public String createNewContext(String contextName) throws ClientApiException { + public int createNewContext(String contextName) throws ClientApiException { ApiResponseElement createContextResponse = ((ApiResponseElement) clientApi.context.newContext(contextName)); - return getIdOfApiResponseElement(createContextResponse); + return Integer.parseInt(getIdOfApiResponseElement(createContextResponse)); } /** @@ -53,20 +53,22 @@ public String createNewContext(String contextName) throws ClientApiException { * * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse createNewSession(String contextName, String overwrite) throws ClientApiException { - return clientApi.core.newSession(contextName, overwrite); + public ApiResponse createNewSession(String contextName, boolean overwrite) throws ClientApiException { + LOG.info("Creating new session: {} inside the Zap", contextName); + // to ensure parts from previous scan are deleted + return clientApi.core.newSession(contextName, Boolean.toString(overwrite)); } /** - * Set maximum alerts a rule can raise. + * Set maximum alerts a rule can raise to unlimited. * - * @param maximum specifies the maximum number of alerts each rule can raise. - * Setting "0" means unlimited amount of alerts for each rule. * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse configureMaximumAlertsForEachRule(String maximum) throws ClientApiException { - return clientApi.core.setOptionMaximumAlertInstances(maximum); + public ApiResponse setMaximumAlertsForEachRuleToUnlimited() throws ClientApiException { + LOG.info("Setting default maximum number of alerts for each rule."); + // setting this value to zero means unlimited + return clientApi.core.setOptionMaximumAlertInstances("0"); } /** @@ -76,19 +78,22 @@ public ApiResponse configureMaximumAlertsForEachRule(String maximum) throws Clie * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse enableAllPassiveScannerRules() throws ClientApiException { + LOG.info("Enable all passive scan rules before configuration begins."); + // enable all passive scanner rules by default return clientApi.pscan.enableAllScanners(); } /** - * Enable all active rules for the given policy. + * Enable all active rules for the default policy. * - * @param policy specifies the policy that will be configured. Configuring - * null configures the default policy. * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse enableAllActiveScannerRulesForPolicy(String policy) throws ClientApiException { - return clientApi.ascan.enableAllScanners(policy); + public ApiResponse enableAllActiveScannerRulesForDefaultPolicy() throws ClientApiException { + LOG.info("Enable all active scan rules for default policy before configuration begins."); + // enable all passive scanner rules by default + // null specifies the default scan policy + return clientApi.ascan.enableAllScanners(null); } @@ -100,6 +105,7 @@ public ApiResponse enableAllActiveScannerRulesForPolicy(String policy) throws Cl * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse setAjaxSpiderBrowserId(String browserId) throws ClientApiException { + LOG.info("Set browser for ajaxSpider: {}.", browserId); return clientApi.ajaxSpider.setOptionBrowserId(browserId); } @@ -112,6 +118,7 @@ public ApiResponse setAjaxSpiderBrowserId(String browserId) throws ClientApiExce * @throws ClientApiException */ public ApiResponse setAjaxSpiderMaxDepth(int maxDepth) throws ClientApiException { + LOG.info("Set max directory depth of ajaxSpider to: {}", maxDepth); return clientApi.spider.setOptionMaxDepth(maxDepth); } @@ -123,6 +130,7 @@ public ApiResponse setAjaxSpiderMaxDepth(int maxDepth) throws ClientApiException * @throws ClientApiException */ public ApiResponse setSpiderMaxDepth(int maxDepth) throws ClientApiException { + LOG.info("Set max directory depth of spider to: {}", maxDepth); return clientApi.spider.setOptionMaxDepth(maxDepth); } @@ -134,6 +142,7 @@ public ApiResponse setSpiderMaxDepth(int maxDepth) throws ClientApiException { * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse disablePassiveScannerRule(String ruleId) throws ClientApiException { + LOG.info("Deactivate passive scanner rule: {} ", ruleId); return clientApi.pscan.disableScanners(ruleId); } @@ -146,23 +155,22 @@ public ApiResponse disablePassiveScannerRule(String ruleId) throws ClientApiExce * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse disableActiveScannerRuleForPolicy(String ruleId, String policy) throws ClientApiException { + public ApiResponse disableActiveScannerRuleForDefaultPolicy(String ruleId) throws ClientApiException { + LOG.info("Deactivate active scanner rule: {} ", ruleId); + // null specifies the default scan policy return clientApi.ascan.disableScanners(ruleId, null); } /** - * Set HTTP proxy with the given parameters. + * Configure http proxy inside ZAP. * - * @param host hostname of the proxy - * @param port port of the proxy - * @param realm realm of the proxy - * @param username username to access the proxy - * @param password password to access the proxy + * @param proxyInformation * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse configureHttpProxy(String host, String port, String realm, String username, String password) throws ClientApiException { - return clientApi.network.setHttpProxy(host, port, realm, username, password); + public ApiResponse configureHttpProxy(ProxyInformation proxyInformation) throws ClientApiException { + return clientApi.network.setHttpProxy(proxyInformation.getHost(), Integer.toString(proxyInformation.getPort()), proxyInformation.getRealm(), + proxyInformation.getUsername(), proxyInformation.getPassword()); } /** @@ -173,8 +181,8 @@ public ApiResponse configureHttpProxy(String host, String port, String realm, St * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse setHttpProxyEnabled(String enabled) throws ClientApiException { - return clientApi.network.setHttpProxyEnabled(enabled); + public ApiResponse setHttpProxyEnabled(boolean enabled) throws ClientApiException { + return clientApi.network.setHttpProxyEnabled(Boolean.toString(enabled)); } /** @@ -185,8 +193,8 @@ public ApiResponse setHttpProxyEnabled(String enabled) throws ClientApiException * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse setHttpProxyAuthEnabled(String enabled) throws ClientApiException { - return clientApi.network.setHttpProxyAuthEnabled(enabled); + public ApiResponse setHttpProxyAuthEnabled(boolean enabled) throws ClientApiException { + return clientApi.network.setHttpProxyAuthEnabled(Boolean.toString(enabled)); } /** @@ -209,16 +217,18 @@ public ApiResponse setHttpProxyAuthEnabled(String enabled) throws ClientApiExcep * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse addReplacerRule(String description, String enabled, String matchtype, String matchregex, String matchstring, String replacement, + public ApiResponse addReplacerRule(String description, boolean enabled, String matchtype, boolean matchregex, String matchstring, String replacement, String initiators, String url) throws ClientApiException { try { - return clientApi.replacer.addRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + return clientApi.replacer.addRule(description, Boolean.toString(enabled), matchtype, Boolean.toString(matchregex), matchstring, replacement, + initiators, url); } catch (ClientApiException e) { String message = e.getMessage(); if ("already exists".equalsIgnoreCase(message)) { clientApi.replacer.removeRule(description); } - return clientApi.replacer.addRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); + return clientApi.replacer.addRule(description, Boolean.toString(enabled), matchtype, Boolean.toString(matchregex), matchstring, replacement, + initiators, url); } } @@ -258,10 +268,11 @@ public ApiResponse addExcludeUrlPatternToContext(String contextName, String urlP * @return api response of ZAP ApiResponse of ZAP or null when URL * was not accessible. */ - public ApiResponse accessUrlViaZap(String url, String followRedirects) { + public ApiResponse accessUrlViaZap(String url, boolean followRedirects) { ApiResponse response = null; try { - response = clientApi.core.accessUrl(url, followRedirects); + LOG.info("Trying to access URL: {} via ZAP to make sure it is added to the sites tree with following redirects set to: {}.", url, followRedirects); + response = clientApi.core.accessUrl(url, Boolean.toString(followRedirects)); } catch (ClientApiException e) { LOG.error("While trying to access URL {} got the error: {}", url, e.getMessage()); } @@ -279,8 +290,9 @@ public ApiResponse accessUrlViaZap(String url, String followRedirects) { * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse importOpenApiFile(String openApiFile, String url, String contextId) throws ClientApiException { - return clientApi.openapi.importFile(openApiFile, url, contextId); + public ApiResponse importOpenApiFile(String openApiFile, String url, int contextId) throws ClientApiException { + LOG.info("Loading openAPI file: {}", openApiFile.toString()); + return clientApi.openapi.importFile(openApiFile, url, Integer.toString(contextId)); } /** @@ -296,8 +308,9 @@ public ApiResponse importOpenApiFile(String openApiFile, String url, String cont * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse importOpenApiDefintionFromUrl(URL apiDefinitionUrl, String targetUrl, String contextId) throws ClientApiException { - return clientApi.openapi.importUrl(apiDefinitionUrl.toString(), targetUrl, contextId); + public ApiResponse importOpenApiDefintionFromUrl(URL apiDefinitionUrl, String targetUrl, int contextId) throws ClientApiException { + LOG.info("Loading openAPI definition from : {}", apiDefinitionUrl.toString()); + return clientApi.openapi.importUrl(apiDefinitionUrl.toString(), targetUrl, Integer.toString(contextId)); } /** @@ -313,6 +326,7 @@ public ApiResponse importPkcs12ClientCertificate(String filepath, String passwor // add the client certificate to the list ZAP keeps inside the network add-on // the third parameter here always "0" is the index where to import inside the // ZAP internal list + LOG.info("Loading client certificate file: {}", filepath); return clientApi.network.addPkcs12ClientCertificate(filepath, password, "0"); } @@ -323,10 +337,14 @@ public ApiResponse importPkcs12ClientCertificate(String filepath, String passwor * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse enableClientCertificate() throws ClientApiException { + LOG.info("Enable client certificate."); return clientApi.network.setUseClientCertificate("true"); } public ApiResponse disableClientCertificate() throws ClientApiException { + // disable client certificate here, the imported client certificate will be + // removed on ZAP shutdown automatically anyway + LOG.info("Disable client certificate if one was used for the scan."); return clientApi.network.setUseClientCertificate("false"); } @@ -357,12 +375,15 @@ public boolean atLeastOneURLDetected() throws ClientApiException { * @throws ClientApiException when anything goes wrong communicating with ZAP */ public ApiResponse removeReplacerRule(String description) throws ClientApiException { + LOG.info("Remove replacer rule: {} if it exists.", description); return clientApi.replacer.removeRule(description); } public ApiResponse generateReport(String title, String template, String theme, String description, String contexts, String sites, String sections, String includedconfidences, String includedrisks, String reportfilename, String reportfilenamepattern, String reportdir, String display) throws ClientApiException { + File reportFile = new File(reportdir, reportfilename); + LOG.info("Writing scan report to: {}", reportFile.getAbsolutePath()); return clientApi.reports.generate(title, template, theme, description, contexts, sites, sections, includedconfidences, includedrisks, reportfilename, reportfilenamepattern, reportdir, display); } @@ -395,8 +416,8 @@ public ApiResponse stopAjaxSpider() throws ClientApiException { * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse stopSpiderScan(String scanId) throws ClientApiException { - return clientApi.spider.stop(scanId); + public ApiResponse stopSpiderScan(int scanId) throws ClientApiException { + return clientApi.spider.stop(Integer.toString(scanId)); } /** @@ -407,9 +428,9 @@ public ApiResponse stopSpiderScan(String scanId) throws ClientApiException { * @return the amount of spider results logged * @throws ClientApiException */ - public long logFullSpiderResults(String scanId) throws ClientApiException { + public long logFullSpiderResults(int scanId) throws ClientApiException { int numberOfSpiderResults = 0; - ApiResponseList results = (ApiResponseList) clientApi.spider.fullResults(scanId); + ApiResponseList results = (ApiResponseList) clientApi.spider.fullResults(Integer.toString(scanId)); for (ApiResponse resultItem : results.getItems()) { ApiResponseList elementList = (ApiResponseList) resultItem; @@ -447,8 +468,8 @@ public long logFullSpiderResults(String scanId) throws ClientApiException { * (percentage of scan completion) * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public int getSpiderStatusForScan(String scanId) throws ClientApiException { - ApiResponseElement status = (ApiResponseElement) clientApi.spider.status(scanId); + public int getSpiderStatusForScan(int scanId) throws ClientApiException { + ApiResponseElement status = (ApiResponseElement) clientApi.spider.status(Integer.toString(scanId)); return Integer.parseInt(status.getValue()); } @@ -471,8 +492,8 @@ public int getNumberOfPassiveScannerRecordsToScan() throws ClientApiException { * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse stopActiveScan(String scanId) throws ClientApiException { - return clientApi.ascan.stop(scanId); + public ApiResponse stopActiveScan(int scanId) throws ClientApiException { + return clientApi.ascan.stop(Integer.toString(scanId)); } /** @@ -483,8 +504,8 @@ public ApiResponse stopActiveScan(String scanId) throws ClientApiException { * (percentage of scan completion) * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public int getActiveScannerStatusForScan(String scanId) throws ClientApiException { - ApiResponseElement status = (ApiResponseElement) clientApi.ascan.status(scanId); + public int getActiveScannerStatusForScan(int scanId) throws ClientApiException { + ApiResponseElement status = (ApiResponseElement) clientApi.ascan.status(Integer.toString(scanId)); return Integer.parseInt(status.getValue()); } @@ -500,10 +521,10 @@ public int getActiveScannerStatusForScan(String scanId) throws ClientApiExceptio * @return api response of ZAP the ID of the started spider scan * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public String startSpiderScan(String targetUrlAsString, String maxChildren, String recurse, String contextName, String subTreeOnly) + public int startSpiderScan(String targetUrlAsString, String maxChildren, boolean recurse, String contextName, boolean subTreeOnly) throws ClientApiException { - ApiResponse response = clientApi.spider.scan(targetUrlAsString, maxChildren, recurse, contextName, subTreeOnly); - return getIdOfApiResponseElement((ApiResponseElement) response); + ApiResponse response = clientApi.spider.scan(targetUrlAsString, maxChildren, Boolean.toString(recurse), contextName, Boolean.toString(subTreeOnly)); + return Integer.parseInt(getIdOfApiResponseElement((ApiResponseElement) response)); } /** @@ -517,8 +538,8 @@ public String startSpiderScan(String targetUrlAsString, String maxChildren, Stri * @return api response of ZAP the response of the ZAP API call * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse startAjaxSpiderScan(String targetUrlAsString, String inScope, String contextName, String subTreeOnly) throws ClientApiException { - return clientApi.ajaxSpider.scan(targetUrlAsString, inScope, contextName, subTreeOnly); + public ApiResponse startAjaxSpiderScan(String targetUrlAsString, boolean inScope, String contextName, boolean subTreeOnly) throws ClientApiException { + return clientApi.ajaxSpider.scan(targetUrlAsString, Boolean.toString(inScope), contextName, Boolean.toString(subTreeOnly)); } /** @@ -533,13 +554,15 @@ public ApiResponse startAjaxSpiderScan(String targetUrlAsString, String inScope, * null means default * @param method method to use * @param postData explicit post data + * @param contextId the contextId of the context to use for the scan * @return api response of ZAP the ID of the started active scan * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public String startActiveScan(String targetUrlAsString, String recurse, String inScopeOnly, String scanPolicyName, String method, String postData) - throws ClientApiException { - ApiResponse response = clientApi.ascan.scan(targetUrlAsString, recurse, inScopeOnly, scanPolicyName, method, postData); - return getIdOfApiResponseElement((ApiResponseElement) response); + public int startActiveScan(String targetUrlAsString, boolean recurse, boolean inScopeOnly, String scanPolicyName, String method, String postData, + int contextId) throws ClientApiException { + ApiResponse response = clientApi.ascan.scan(targetUrlAsString, Boolean.toString(recurse), Boolean.toString(inScopeOnly), scanPolicyName, method, + postData, contextId); + return Integer.parseInt(getIdOfApiResponseElement((ApiResponseElement) response)); } /** @@ -551,14 +574,15 @@ public String startActiveScan(String targetUrlAsString, String recurse, String i * @param maxchildren limit the number of children scanned * @param recurse "true"/"false" to prevent the spider from seeding * recursively - * @param subtreeonly restrict the spider under a site's subtree + * @param subtreeOnly restrict the spider under a site's subtree * @return api response of ZAP the ID of the started spider scan * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public String startSpiderScanAsUser(String contextId, String userId, String url, String maxchildren, String recurse, String subtreeonly) + public int startSpiderScanAsUser(int contextId, int userId, String url, String maxchildren, boolean recurse, boolean subtreeOnly) throws ClientApiException { - ApiResponse response = clientApi.spider.scanAsUser(contextId, userId, url, maxchildren, recurse, subtreeonly); - return getIdOfApiResponseElement((ApiResponseElement) response); + ApiResponse response = clientApi.spider.scanAsUser(Integer.toString(contextId), Integer.toString(userId), url, maxchildren, Boolean.toString(recurse), + Boolean.toString(subtreeOnly)); + return Integer.parseInt(getIdOfApiResponseElement((ApiResponseElement) response)); } /** @@ -571,8 +595,8 @@ public String startSpiderScanAsUser(String contextId, String userId, String url, * @return api response of ZAP the response of the ZAP API call * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse startAjaxSpiderScanAsUser(String contextname, String username, String url, String subtreeonly) throws ClientApiException { - return clientApi.ajaxSpider.scanAsUser(contextname, username, url, subtreeonly); + public ApiResponse startAjaxSpiderScanAsUser(String contextname, String username, String url, boolean subtreeonly) throws ClientApiException { + return clientApi.ajaxSpider.scanAsUser(contextname, username, url, Boolean.toString(subtreeonly)); } /** @@ -590,10 +614,11 @@ public ApiResponse startAjaxSpiderScanAsUser(String contextname, String username * @return api response of ZAP the ID of the started active scan * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public String startActiveScanAsUser(String url, String contextId, String userId, String recurse, String scanpolicyname, String method, String postdata) + public int startActiveScanAsUser(String url, int contextId, int userId, boolean recurse, String scanpolicyname, String method, String postdata) throws ClientApiException { - ApiResponse response = clientApi.ascan.scanAsUser(url, contextId, userId, recurse, scanpolicyname, method, postdata); - return getIdOfApiResponseElement((ApiResponseElement) response); + ApiResponse response = clientApi.ascan.scanAsUser(url, Integer.toString(contextId), Integer.toString(userId), Boolean.toString(recurse), scanpolicyname, + method, postdata); + return Integer.parseInt(getIdOfApiResponseElement((ApiResponseElement) response)); } /** @@ -606,8 +631,21 @@ public String startActiveScanAsUser(String url, String contextId, String userId, * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse configureAuthenticationMethod(String contextId, String authMethodName, String authMethodConfigParams) throws ClientApiException { - return clientApi.authentication.setAuthenticationMethod(contextId, authMethodName, authMethodConfigParams); + public ApiResponse setAuthenticationMethod(int contextId, String authMethodName, String authMethodConfigParams) throws ClientApiException { + return clientApi.authentication.setAuthenticationMethod(Integer.toString(contextId), authMethodName, authMethodConfigParams); + } + + /** + * Configure manual authentication method for the given context. + * + * @param contextId Id of the context to use + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse setManualAuthenticationMethod(int contextId) throws ClientApiException { + String authMethodConfigParams = null; + String authMethodName = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); + return clientApi.authentication.setAuthenticationMethod(Integer.toString(contextId), authMethodName, authMethodConfigParams); } /** @@ -620,8 +658,21 @@ public ApiResponse configureAuthenticationMethod(String contextId, String authMe * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse setSessionManagementMethod(String contextId, String methodName, String methodconfigparams) throws ClientApiException { - return clientApi.sessionManagement.setSessionManagementMethod(contextId, methodName, methodconfigparams); + public ApiResponse setSessionManagementMethod(int contextId, String methodName, String methodconfigparams) throws ClientApiException { + return clientApi.sessionManagement.setSessionManagementMethod(Integer.toString(contextId), methodName, methodconfigparams); + } + + /** + * Set cookie based session management method for the given context. + * + * @param contextId Id of the context to use + * @return api response of ZAP + * @throws ClientApiException + */ + public ApiResponse setCookieBasedSessionManagementMethod(int contextId) throws ClientApiException { + String sessionMethodconfigparams = null; + String sessionMethodName = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); + return setSessionManagementMethod(contextId, sessionMethodName, sessionMethodconfigparams); } /** @@ -632,9 +683,9 @@ public ApiResponse setSessionManagementMethod(String contextId, String methodNam * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public String createNewUser(String contextId, String username) throws ClientApiException { - ApiResponseElement creatUserResponse = ((ApiResponseElement) clientApi.users.newUser(contextId, username)); - return getIdOfApiResponseElement(creatUserResponse); + public int createNewUser(int contextId, String username) throws ClientApiException { + ApiResponseElement creatUserResponse = ((ApiResponseElement) clientApi.users.newUser(Integer.toString(contextId), username)); + return Integer.parseInt(getIdOfApiResponseElement(creatUserResponse)); } /** @@ -648,8 +699,8 @@ public String createNewUser(String contextId, String username) throws ClientApiE * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse configureAuthenticationCredentials(String contextId, String userId, String authCredentialsConfigParams) throws ClientApiException { - return clientApi.users.setAuthenticationCredentials(contextId, userId, authCredentialsConfigParams); + public ApiResponse configureAuthenticationCredentials(int contextId, int userId, String authCredentialsConfigParams) throws ClientApiException { + return clientApi.users.setAuthenticationCredentials(Integer.toString(contextId), Integer.toString(userId), authCredentialsConfigParams); } /** @@ -661,8 +712,8 @@ public ApiResponse configureAuthenticationCredentials(String contextId, String u * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse setUserEnabled(String contextId, String userId, String enabled) throws ClientApiException { - return clientApi.users.setUserEnabled(contextId, userId, enabled); + public ApiResponse setUserEnabled(int contextId, int userId, boolean enabled) throws ClientApiException { + return clientApi.users.setUserEnabled(Integer.toString(contextId), Integer.toString(userId), Boolean.toString(enabled)); } /** @@ -673,8 +724,8 @@ public ApiResponse setUserEnabled(String contextId, String userId, String enable * @return api response of ZAP * @throws ClientApiException when anything goes wrong communicating with ZAP */ - public ApiResponse setForcedUser(String contextId, String userId) throws ClientApiException { - return clientApi.forcedUser.setForcedUser(contextId, userId); + public ApiResponse setForcedUser(int contextId, int userId) throws ClientApiException { + return clientApi.forcedUser.setForcedUser(Integer.toString(contextId), Integer.toString(userId)); } /** @@ -699,6 +750,7 @@ public ApiResponse setForcedUserModeEnabled(boolean enabled) throws ClientApiExc * @throws ClientApiException */ public ApiResponse addHTTPSessionToken(String targetUrl, String sessionTokenIdentifier) throws ClientApiException { + LOG.info("Add new HTTP session token: {} to ZAP for URL: {}.", sessionTokenIdentifier, targetUrl); return clientApi.httpSessions.addSessionToken(targetUrl, sessionTokenIdentifier); } @@ -712,6 +764,7 @@ public ApiResponse addHTTPSessionToken(String targetUrl, String sessionTokenIden * @throws ClientApiException */ public ApiResponse createEmptyHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + LOG.info("Create new empty HTTP session: {} in ZAP for URL: {}.", sessionIdentifier, targetUrl); return clientApi.httpSessions.createEmptySession(targetUrl, sessionIdentifier); } @@ -728,6 +781,7 @@ public ApiResponse createEmptyHTTPSession(String targetUrl, String sessionIdenti * @throws ClientApiException */ public ApiResponse setHTTPSessionTokenValue(String targetUrl, String sessionIdentifier, String name, String value) throws ClientApiException { + LOG.info("Adding session token value to ZAP HTTP session: {} for URL: {}", sessionIdentifier, targetUrl); return clientApi.httpSessions.setSessionTokenValue(targetUrl, sessionIdentifier, name, value); } @@ -742,6 +796,7 @@ public ApiResponse setHTTPSessionTokenValue(String targetUrl, String sessionIden * @throws ClientApiException */ public ApiResponse setActiveHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + LOG.info("Set ZAP HTTP session: {} with URL: {} as active session to use.", sessionIdentifier, targetUrl); return clientApi.httpSessions.setActiveSession(targetUrl, sessionIdentifier); } @@ -754,6 +809,7 @@ public ApiResponse setActiveHTTPSession(String targetUrl, String sessionIdentifi * @throws ClientApiException */ public ApiResponse removeHTTPSession(String targetUrl, String sessionIdentifier) throws ClientApiException { + LOG.info("Remove session: {} for url: {} if it exists.", sessionIdentifier, targetUrl); return clientApi.httpSessions.removeSession(targetUrl, sessionIdentifier); } @@ -763,11 +819,11 @@ public ApiResponse removeHTTPSession(String targetUrl, String sessionIdentifier) * * @param targetUrl * @param sessionIdentifier - * @return * @return api response of ZAP * @throws ClientApiException */ public ApiResponse removeHTTPSessionToken(String targetUrl, String sessionTokenIdentifier) throws ClientApiException { + LOG.info("Remove session token: {} for url: {} if it exists.", sessionTokenIdentifier, targetUrl); return clientApi.httpSessions.removeSessionToken(targetUrl, sessionTokenIdentifier); } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java index 1029c555fa..02371b910c 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScanner.java @@ -31,13 +31,9 @@ import com.mercedesbenz.sechub.zapwrapper.config.data.Rule; import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; -import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; -import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLogin; -import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginSessionGrabber; -import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptLoginWebDriverFactory; -import com.mercedesbenz.sechub.zapwrapper.scan.login.ZapWrapperGroovyScriptExecutor; +import com.mercedesbenz.sechub.zapwrapper.scan.login.*; import com.mercedesbenz.sechub.zapwrapper.util.SystemUtil; import com.mercedesbenz.sechub.zapwrapper.util.UrlUtil; @@ -47,33 +43,31 @@ public class ZapScanner implements ZapScan { public static final String X_SECHUB_DAST_HEADER_NAME = "x-sechub-dast"; private static final int CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS = 5000; - private static final int DEFAULT_MAX_DEPTH = 10; + private static final int DEFAULT_MAX_DEPTH_AJAX_SPIDER = 10; + private static final int DEFAULT_MAX_DEPTH_SPIDER = 5; private final ClientApiWrapper clientApiWrapper; private final ZapScanContext scanContext; private final ZapScriptLogin scriptLogin; - private final ScanDurationHelper scanDurationHelper; private final UrlUtil urlUtil; + private final SystemUtil systemUtil; public ZapScanner(ClientApiWrapper clientApiWrapper, ZapScanContext scanContext) { this.clientApiWrapper = clientApiWrapper; this.scanContext = scanContext; - this.scanDurationHelper = new ScanDurationHelper(); this.urlUtil = new UrlUtil(); this.systemUtil = new SystemUtil(); - this.scriptLogin = new ZapScriptLogin(new ZapScriptLoginWebDriverFactory(), new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionGrabber()); + this.scriptLogin = new ZapScriptLogin(); } - ZapScanner(ClientApiWrapper clientApiWrapper, ZapScanContext scanContext, ScanDurationHelper scanDurationHelper, UrlUtil urlUtil, SystemUtil systemUtil, - ZapScriptLogin scriptLogin) { + ZapScanner(ClientApiWrapper clientApiWrapper, ZapScanContext scanContext, UrlUtil urlUtil, SystemUtil systemUtil, ZapScriptLogin scriptLogin) { this.clientApiWrapper = clientApiWrapper; this.scanContext = scanContext; - this.scanDurationHelper = scanDurationHelper; this.urlUtil = urlUtil; this.systemUtil = systemUtil; @@ -87,7 +81,7 @@ public void scan() throws ZapWrapperRuntimeException { setupStandardConfiguration(); deactivateRules(scanContext.getFullRuleset(), scanContext.getDeactivatedRuleReferences()); setupAdditonalProxyConfiguration(scanContext.getProxyInformation()); - String zapContextId = createContext(); + int zapContextId = createContext(); addXSecHubDASTHeader(); addReplacerRulesForHeaders(); @@ -113,30 +107,13 @@ public void scan() throws ZapWrapperRuntimeException { } void setupStandardConfiguration() throws ClientApiException { - LOG.info("Creating new session inside the Zap"); - // to ensure parts from previous scan are deleted - clientApiWrapper.createNewSession(scanContext.getContextName(), "true"); - - LOG.info("Setting default maximum number of alerts for each rule."); - // setting this value to zero means unlimited - clientApiWrapper.configureMaximumAlertsForEachRule("0"); - - LOG.info("Enable all passive scan rules before configuration begins."); - // enable all passive scanner rules by default + clientApiWrapper.createNewSession(scanContext.getContextName(), true); + clientApiWrapper.setMaximumAlertsForEachRuleToUnlimited(); clientApiWrapper.enableAllPassiveScannerRules(); - - LOG.info("Enable all active scan rules before configuration begins."); - // enable all passive scanner rules by default - // null specifies the default scan policy - clientApiWrapper.enableAllActiveScannerRulesForPolicy(null); - - LOG.info("Set browser for ajaxSpider."); - // use firefox in headless mode by default + clientApiWrapper.enableAllActiveScannerRulesForDefaultPolicy(); clientApiWrapper.setAjaxSpiderBrowserId(scanContext.getAjaxSpiderBrowserId()); - - LOG.info("Set max directory depth of spider and ajaxSpider to: {}", DEFAULT_MAX_DEPTH); - clientApiWrapper.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); - clientApiWrapper.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH); + clientApiWrapper.setSpiderMaxDepth(DEFAULT_MAX_DEPTH_SPIDER); + clientApiWrapper.setAjaxSpiderMaxDepth(DEFAULT_MAX_DEPTH_AJAX_SPIDER); } void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deactivatedRuleReferences) throws ClientApiException { @@ -151,12 +128,9 @@ void deactivateRules(ZapFullRuleset fullRuleset, DeactivatedRuleReferences deact for (RuleReference ruleRef : rulesReferences) { Rule ruleToDeactivate = fullRuleset.findRuleByReference(ruleRef.getReference()); if (isPassiveRule(ruleToDeactivate.getType())) { - LOG.info("Deactivate passive scanner rule: {} ", ruleRef.getReference()); clientApiWrapper.disablePassiveScannerRule(ruleToDeactivate.getId()); } else if (isActiveRule(ruleToDeactivate.getType())) { - LOG.info("Deactivate active scanner rule: {} ", ruleRef.getReference()); - // null specifies the default scan policy - clientApiWrapper.disableActiveScannerRuleForPolicy(ruleToDeactivate.getId(), null); + clientApiWrapper.disableActiveScannerRuleForDefaultPolicy(ruleToDeactivate.getId()); } } } @@ -166,12 +140,12 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws String proxyHost = proxyInformation.getHost(); int proxyPort = proxyInformation.getPort(); LOG.info("Using proxy {}:{} to reach target.", proxyHost, proxyPort); - clientApiWrapper.configureHttpProxy(proxyHost, "" + proxyPort, null, null, null); - clientApiWrapper.setHttpProxyEnabled("true"); - clientApiWrapper.setHttpProxyAuthEnabled("false"); + clientApiWrapper.configureHttpProxy(proxyInformation); + clientApiWrapper.setHttpProxyEnabled(true); + clientApiWrapper.setHttpProxyAuthEnabled(false); } else { LOG.info("No proxy was set, continuing without proxy."); - clientApiWrapper.setHttpProxyEnabled("false"); + clientApiWrapper.setHttpProxyEnabled(false); } } @@ -181,7 +155,7 @@ void setupAdditonalProxyConfiguration(ProxyInformation proxyInformation) throws * @return the context id returned by the ZAP API * @throws ClientApiException */ - String createContext() throws ClientApiException { + int createContext() throws ClientApiException { LOG.info("Creating context: {}", scanContext.getContextName()); return clientApiWrapper.createNewContext(scanContext.getContextName()); } @@ -195,11 +169,11 @@ void addReplacerRulesForHeaders() throws ClientApiException { // description specifies the rule name, which will be set later in this method String description = null; - String enabled = "true"; + boolean enabled = true; // "REQ_HEADER" means the header entry will be added to the requests if not // existing or replaced if already existing String matchtype = "REQ_HEADER"; - String matchregex = "false"; + boolean matchregex = false; // matchstring and replacement will be set to the header name and header value String matchstring = null; @@ -243,7 +217,7 @@ void addReplacerRulesForHeaders() throws ClientApiException { */ void addIncludedAndExcludedUrlsToContext() throws ClientApiException { LOG.info("For scan {}: Adding include parts.", scanContext.getContextName()); - String followRedirects = "false"; + boolean followRedirects = false; for (String url : scanContext.getZapURLsIncludeSet()) { clientApiWrapper.addIncludeUrlPatternToContext(scanContext.getContextName(), url); // Cannot not perform initial connection check to included URL with wildcards @@ -261,7 +235,7 @@ void addIncludedAndExcludedUrlsToContext() throws ClientApiException { } } - void loadApiDefinitions(String zapContextId) throws ClientApiException { + void loadApiDefinitions(int zapContextId) throws ClientApiException { Optional apiConfig = scanContext.getSecHubWebScanConfiguration().getApi(); if (!apiConfig.isPresent()) { LOG.info("For scan {}: No API definition was found!", scanContext.getContextName()); @@ -269,16 +243,13 @@ void loadApiDefinitions(String zapContextId) throws ClientApiException { } SecHubWebScanApiConfiguration secHubWebScanApiConfiguration = apiConfig.get(); - switch (secHubWebScanApiConfiguration.getType()) { case OPEN_API: URL apiDefinitionUrl = secHubWebScanApiConfiguration.getApiDefinitionUrl(); if (apiDefinitionUrl != null) { - LOG.info("For scan {}: Loading openAPI definition from : {}", scanContext.getContextName(), apiDefinitionUrl.toString()); clientApiWrapper.importOpenApiDefintionFromUrl(apiDefinitionUrl, scanContext.getTargetUrlAsString(), zapContextId); } for (File apiFile : scanContext.getApiDefinitionFiles()) { - LOG.info("For scan {}: Loading openAPI file: {}", scanContext.getContextName(), apiFile.toString()); clientApiWrapper.importOpenApiFile(apiFile.toString(), scanContext.getTargetUrlAsString(), zapContextId); } break; @@ -315,31 +286,29 @@ void importClientCertificate() throws ClientApiException { if (clientCertificateConfig.getPassword() != null) { password = new String(clientCertificateConfig.getPassword()); } - LOG.info("For scan {}: Loading client certificate file: {}", scanContext.getContextName(), clientCertificateFile.getAbsolutePath()); clientApiWrapper.importPkcs12ClientCertificate(clientCertificateFile.getAbsolutePath(), password); clientApiWrapper.enableClientCertificate(); } - void executeScan(String zapContextId) throws ClientApiException { + void executeScan(int zapContextId) throws ClientApiException { UserInformation userInfo = setupLoginInsideZapContext(zapContextId); - long remainingScanDurationInMillis = scanContext.getMaxScanDurationInMilliSeconds(); if (userInfo != null) { - remainingScanDurationInMillis = runSpiderAsUser(zapContextId, userInfo.zapuserId, remainingScanDurationInMillis); - remainingScanDurationInMillis = passiveScan(remainingScanDurationInMillis); + runAndWaitForSpiderAsUser(zapContextId, userInfo.zapuserId); + runAndWaitForPassiveScan(); if (scanContext.isAjaxSpiderEnabled()) { - remainingScanDurationInMillis = runAjaxSpiderAsUser(userInfo.userName, remainingScanDurationInMillis); + runAndWaitForAjaxSpiderAsUser(userInfo.userName); } if (scanContext.isActiveScanEnabled()) { - runActiveScanAsUser(zapContextId, userInfo.zapuserId, remainingScanDurationInMillis); + runActiveScanAsUser(zapContextId, userInfo.zapuserId); } } else { - remainingScanDurationInMillis = runSpider(remainingScanDurationInMillis); - remainingScanDurationInMillis = passiveScan(remainingScanDurationInMillis); + runAndWaitForSpider(); + runAndWaitForPassiveScan(); if (scanContext.isAjaxSpiderEnabled()) { - remainingScanDurationInMillis = runAjaxSpider(remainingScanDurationInMillis); + runAndWaitAjaxSpider(); } if (scanContext.isActiveScanEnabled()) { - runActiveScan(remainingScanDurationInMillis); + runAndWaitActiveScan(zapContextId); } } } @@ -352,7 +321,7 @@ void executeScan(String zapContextId) throws ClientApiException { * null if nothing could be configured. * @throws ClientApiException */ - UserInformation setupLoginInsideZapContext(String zapContextId) throws ClientApiException { + UserInformation setupLoginInsideZapContext(int zapContextId) throws ClientApiException { if (scanContext.getSecHubWebScanConfiguration().getLogin().isEmpty()) { LOG.info("For scan {}: No login section detected.", scanContext.getContextName()); return null; @@ -364,14 +333,15 @@ UserInformation setupLoginInsideZapContext(String zapContextId) throws ClientApi return initBasicAuthentication(zapContextId, webLoginConfiguration.getBasic().get()); } - if (isScriptLoginWanted()) { + if (scriptLoginWanted()) { LOG.info("For scan {}: Setting up authentcation and session management method for script authentication.", scanContext.getContextName()); setupAuthenticationAndSessionManagementMethodForScriptLogin(zapContextId); LOG.info("For scan {}: Performing script authentication.", scanContext.getContextName()); String zapAuthSessionName = scriptLogin.login(scanContext, clientApiWrapper); - // TODO read the username from templateData as soon as it is implemented + // TODO 2024-11-21 jan: read the username from templateData as soon as it is + // implemented String username = "DUMMY"; /* @formatter:off */ LOG.info("For scan {}: Setup scan user in ZAP to use authenticated session.", scanContext.getContextName()); @@ -392,7 +362,6 @@ UserInformation setupLoginInsideZapContext(String zapContextId) throws ClientApi * @throws ClientApiException */ void generateZapReport() throws ClientApiException { - LOG.info("For scan {}: Writing results to report...", scanContext.getContextName()); Path reportFile = scanContext.getReportFile(); String title = scanContext.getContextName(); @@ -436,26 +405,16 @@ void generateZapReport() throws ClientApiException { void cleanUp() { // to ensure parts from previous scan are deleted + LOG.info("Starting cleanup."); try { - LOG.info("Cleaning up by starting new and empty session...", scanContext.getContextName()); - clientApiWrapper.createNewSession("Cleaned after scan", "true"); - LOG.info("New and empty session inside Zap created."); + clientApiWrapper.createNewSession("Cleaned after scan", true); - // Replacer rules are persistent even after restarting ZAP - // This means we need to cleanUp after every scan. - LOG.info("Start cleaning up replacer rules."); cleanUpReplacerRules(); - // Remove x-sechub-dast header replacer rule - LOG.info("Remove '{}' replacer rule.", X_SECHUB_DAST_HEADER_NAME); clientApiWrapper.removeReplacerRule(X_SECHUB_DAST_HEADER_NAME); - // disable client certificate here, the imported client certificate will be - // removed on ZAP shutdown automatically anyway - LOG.info("Disable client certificate if one was used for the scan."); clientApiWrapper.disableClientCertificate(); - LOG.info("Cleaning up script login data."); scriptLogin.cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); LOG.info("Cleanup successful."); @@ -464,15 +423,15 @@ void cleanUp() { } } - long runSpider(long remainingScanDurationInMillis) throws ClientApiException { + void runAndWaitForSpider() throws ClientApiException { String contextName = scanContext.getContextName(); - String subTreeOnly = "true"; - String recurse = "true"; + boolean subTreeOnly = true; + boolean recurse = true; String maxChildren = null; String targetUrlAsString = scanContext.getTargetUrlAsString(); LOG.info("For scan {}: Starting Spider.", contextName); /* @formatter:off */ - String scanId = + int scanId = clientApiWrapper.startSpiderScan( targetUrlAsString, maxChildren, @@ -480,12 +439,12 @@ long runSpider(long remainingScanDurationInMillis) throws ClientApiException { contextName, subTreeOnly); /* @formatter:on */ - return waitForSpiderResults(scanId, remainingScanDurationInMillis); + waitForSpiderResults(scanId); } - long runAjaxSpider(long remainingScanDurationInMillis) throws ClientApiException { - String inScope = "true"; - String subTreeOnly = "true"; + void runAndWaitAjaxSpider() throws ClientApiException { + boolean inScope = true; + boolean subTreeOnly = true; String contextName = scanContext.getContextName(); String targetUrlAsString = scanContext.getTargetUrlAsString(); LOG.info("For scan {}: Starting AjaxSpider.", scanContext.getContextName()); @@ -496,10 +455,16 @@ long runAjaxSpider(long remainingScanDurationInMillis) throws ClientApiException contextName, subTreeOnly); /* @formatter:on */ - return waitForAjaxSpiderResults(remainingScanDurationInMillis); + waitForAjaxSpiderResults(); } - void runActiveScan(long remainingScanDurationInMillis) throws ClientApiException { + /** + * Runs the active scanner with the given user for the given context and waits + * for the scan to be completed or cancelled. + * + * @throws ClientApiException + */ + void runAndWaitActiveScan(int contextId) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before if (!clientApiWrapper.atLeastOneURLDetected()) { @@ -510,33 +475,42 @@ void runActiveScan(long remainingScanDurationInMillis) throws ClientApiException return; } String targetUrlAsString = scanContext.getTargetUrlAsString(); - String inScopeOnly = "true"; - String recurse = "true"; + boolean inScopeOnly = true; + boolean recurse = true; String scanPolicyName = null; String method = null; String postData = null; LOG.info("For scan {}: Starting ActiveScan.", scanContext.getContextName()); /* @formatter:off */ - String scanId = + int scanId = clientApiWrapper.startActiveScan( targetUrlAsString, recurse, inScopeOnly, scanPolicyName, method, - postData); + postData, + contextId); /* @formatter:on */ - waitForActiveScanResults(scanId, remainingScanDurationInMillis); + waitForActiveScanResults(scanId); } - long runSpiderAsUser(String contextId, String userId, long remainingScanDurationInMillis) throws ClientApiException { + /** + * Runs the spider with the given user for the given context and waits for the + * scan to be completed or cancelled. + * + * @param contextId + * @param userId + * @throws ClientApiException + */ + void runAndWaitForSpiderAsUser(int contextId, int userId) throws ClientApiException { String url = scanContext.getTargetUrlAsString(); String maxchildren = null; - String recurse = "true"; - String subtreeonly = "true"; + boolean recurse = true; + boolean subtreeonly = true; LOG.info("For scan {}: Starting authenticated Spider.", scanContext.getContextName()); /* @formatter:off */ - String scanId = + int scanId = clientApiWrapper.startSpiderScanAsUser( contextId, userId, @@ -545,14 +519,21 @@ long runSpiderAsUser(String contextId, String userId, long remainingScanDuration recurse, subtreeonly); /* @formatter:on */ - return waitForSpiderResults(scanId, remainingScanDurationInMillis); + waitForSpiderResults(scanId); } - long runAjaxSpiderAsUser(String username, long remainingScanDurationInMillis) throws ClientApiException { + /** + * Runs the ajax spider with the given user for the given context and waits for + * the scan to be completed or cancelled. + * + * @param username + * @throws ClientApiException + */ + void runAndWaitForAjaxSpiderAsUser(String username) throws ClientApiException { String contextname = scanContext.getContextName(); String url = scanContext.getTargetUrlAsString(); - String subtreeonly = "true"; - LOG.info("For scan {}: Starting authenticated Ajax Spider.", scanContext.getContextName()); + boolean subtreeonly = true; + LOG.info("For scan {}: Starting authenticated Ajax Spider.", contextname); /* @formatter:off */ clientApiWrapper.startAjaxSpiderScanAsUser( contextname, @@ -560,10 +541,18 @@ long runAjaxSpiderAsUser(String username, long remainingScanDurationInMillis) th url, subtreeonly); /* @formatter:on */ - return waitForAjaxSpiderResults(remainingScanDurationInMillis); + waitForAjaxSpiderResults(); } - void runActiveScanAsUser(String contextId, String userId, long remainingScanDurationInMillis) throws ClientApiException { + /** + * Runs the active scanner with the given user for the given context and waits + * for the scan to be completed or cancelled. + * + * @param contextId + * @param userId + * @throws ClientApiException + */ + void runActiveScanAsUser(int contextId, int userId) throws ClientApiException { // Necessary otherwise the active scanner exits with an exception, // if no URLs to scan where detected by the spider/ajaxSpider before if (!clientApiWrapper.atLeastOneURLDetected()) { @@ -574,13 +563,13 @@ void runActiveScanAsUser(String contextId, String userId, long remainingScanDura return; } String url = scanContext.getTargetUrlAsString(); - String recurse = "true"; + boolean recurse = true; String scanpolicyname = null; String method = null; String postdata = null; LOG.info("For scan {}: Starting authenticated ActiveScan.", scanContext.getContextName()); /* @formatter:off */ - String scanId = + int scanId = clientApiWrapper.startActiveScanAsUser( url, contextId, @@ -590,28 +579,20 @@ void runActiveScanAsUser(String contextId, String userId, long remainingScanDura method, postdata); /* @formatter:on */ - waitForActiveScanResults(scanId, remainingScanDurationInMillis); + waitForActiveScanResults(scanId); } /** * Wait for the results of the ajax spider. Periodically checks the progress of * the ajax spider. * - * @param remainingScanDurationInMillis - * @return * @throws ClientApiException */ - long waitForAjaxSpiderResults(long remainingScanDurationInMillis) throws ClientApiException { - String ajaxSpiderStatus = null; - - long startTime = systemUtil.getCurrentTimeInMilliseconds(); - long maxDuration = scanDurationHelper.computeAjaxSpiderMaxScanDuration(scanContext.isActiveScanEnabled(), remainingScanDurationInMillis); - - boolean timeOut = false; - + void waitForAjaxSpiderResults() throws ClientApiException { ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); - while (!isAjaxSpiderStopped(ajaxSpiderStatus) && !timeOut) { + String ajaxSpiderStatus = "Running"; + while (!isAjaxSpiderStopped(ajaxSpiderStatus)) { if (zapPDSEventHandler.isScanCancelled()) { clientApiWrapper.stopAjaxSpider(); zapPDSEventHandler.cancelScan(scanContext.getContextName()); @@ -619,12 +600,10 @@ long waitForAjaxSpiderResults(long remainingScanDurationInMillis) throws ClientA systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); ajaxSpiderStatus = clientApiWrapper.getAjaxSpiderStatus(); LOG.info("For scan {}: AjaxSpider status {}", scanContext.getContextName(), ajaxSpiderStatus); - timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > maxDuration; } /* stop spider - otherwise running in background */ clientApiWrapper.stopAjaxSpider(); LOG.info("For scan {}: AjaxSpider completed.", scanContext.getContextName()); - return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** @@ -632,21 +611,13 @@ long waitForAjaxSpiderResults(long remainingScanDurationInMillis) throws ClientA * spider. * * @param scanId - * @param remainingScanDurationInMillis - * @return * @throws ClientApiException */ - long waitForSpiderResults(String scanId, long remainingScanDurationInMillis) throws ClientApiException { - int progressSpider = 0; - - long startTime = systemUtil.getCurrentTimeInMilliseconds(); - long maxDuration = scanDurationHelper.computeSpiderMaxScanDuration(scanContext.isActiveScanEnabled(), scanContext.isAjaxSpiderEnabled(), - remainingScanDurationInMillis); - - boolean timeOut = false; + void waitForSpiderResults(int scanId) throws ClientApiException { ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); - while (progressSpider < 100 && !timeOut) { + int progressSpider = 0; + while (progressSpider < 100) { if (zapPDSEventHandler.isScanCancelled()) { clientApiWrapper.stopSpiderScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); @@ -654,7 +625,6 @@ long waitForSpiderResults(String scanId, long remainingScanDurationInMillis) thr systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); progressSpider = clientApiWrapper.getSpiderStatusForScan(scanId); LOG.info("For scan {}: Spider progress {}%", scanContext.getContextName(), progressSpider); - timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } /* stop spider - otherwise running in background */ clientApiWrapper.stopSpiderScan(scanId); @@ -663,38 +633,28 @@ long waitForSpiderResults(String scanId, long remainingScanDurationInMillis) thr scanContext.getZapProductMessageHelper() .writeSingleProductMessage(new SecHubMessage(SecHubMessageType.INFO, "Scanned %s URLs during the scan.".formatted(numberOfSpiderResults))); LOG.info("For scan {}: Spider completed.", scanContext.getContextName()); - return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** * Wait for the results of the passive scan. Periodically checks the progress of * the passive scan. * - * @param remainingScanDurationInMillis - * @return * @throws ClientApiException */ - long passiveScan(long remainingScanDurationInMillis) throws ClientApiException { + void runAndWaitForPassiveScan() throws ClientApiException { LOG.info("For scan {}: Starting passive scan.", scanContext.getContextName()); - long startTime = systemUtil.getCurrentTimeInMilliseconds(); - long maxDuration = scanDurationHelper.computePassiveScanMaxScanDuration(scanContext.isActiveScanEnabled(), scanContext.isAjaxSpiderEnabled(), - remainingScanDurationInMillis); - - int numberOfRecords = clientApiWrapper.getNumberOfPassiveScannerRecordsToScan(); - boolean timeOut = false; ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); - while (numberOfRecords > 0 && !timeOut) { + int numberOfRecords = clientApiWrapper.getNumberOfPassiveScannerRecordsToScan(); + while (numberOfRecords > 0) { if (zapPDSEventHandler.isScanCancelled()) { zapPDSEventHandler.cancelScan(scanContext.getContextName()); } systemUtil.waitForMilliseconds(CHECK_SCAN_STATUS_TIME_IN_MILLISECONDS); numberOfRecords = clientApiWrapper.getNumberOfPassiveScannerRecordsToScan(); LOG.info("For scan {}: Passive scan number of records left for scanning: {}", scanContext.getContextName(), numberOfRecords); - timeOut = systemUtil.getCurrentTimeInMilliseconds() - startTime > maxDuration; } LOG.info("For scan {}: Passive scan completed.", scanContext.getContextName()); - return remainingScanDurationInMillis - (systemUtil.getCurrentTimeInMilliseconds() - startTime); } /** @@ -702,18 +662,13 @@ long passiveScan(long remainingScanDurationInMillis) throws ClientApiException { * the active scan. * * @param scanId - * @param remainingScanDurationInMillis * @throws ClientApiException */ - void waitForActiveScanResults(String scanId, long remainingScanDurationInMillis) throws ClientApiException { - int progressActive = 0; - - long startTime = systemUtil.getCurrentTimeInMilliseconds(); - boolean timeOut = false; - + void waitForActiveScanResults(int scanId) throws ClientApiException { ZapPDSEventHandler zapPDSEventHandler = scanContext.getZapPDSEventHandler(); - while (progressActive < 100 && !timeOut) { + int progressActive = 0; + while (progressActive < 100) { if (zapPDSEventHandler.isScanCancelled()) { clientApiWrapper.stopActiveScan(scanId); zapPDSEventHandler.cancelScan(scanContext.getContextName()); @@ -722,7 +677,6 @@ void waitForActiveScanResults(String scanId, long remainingScanDurationInMillis) progressActive = clientApiWrapper.getActiveScannerStatusForScan(scanId); LOG.info("For scan {}: Active scan progress {}%", scanContext.getContextName(), progressActive); - timeOut = (systemUtil.getCurrentTimeInMilliseconds() - startTime) > remainingScanDurationInMillis; } clientApiWrapper.stopActiveScan(scanId); LOG.info("For scan {}: Active scan completed.", scanContext.getContextName()); @@ -736,12 +690,12 @@ private boolean isActiveRule(String type) { return "active".equals(type.toLowerCase()); } - private UserInformation initBasicAuthentication(String zapContextId, BasicLoginConfiguration basicLoginConfiguration) throws ClientApiException { + private UserInformation initBasicAuthentication(int zapContextId, BasicLoginConfiguration basicLoginConfiguration) throws ClientApiException { String realm = ""; if (basicLoginConfiguration.getRealm().isPresent()) { realm = basicLoginConfiguration.getRealm().get(); } - String port = "" + scanContext.getTargetUrl().getPort(); + String port = Integer.toString(scanContext.getTargetUrl().getPort()); /* @formatter:off */ StringBuilder authMethodConfigParams = new StringBuilder(); authMethodConfigParams.append("hostname=").append(urlEncodeUTF8(scanContext.getTargetUrl().getHost())) @@ -750,7 +704,7 @@ private UserInformation initBasicAuthentication(String zapContextId, BasicLoginC /* @formatter:on */ LOG.info("For scan {}: Setting basic authentication.", scanContext.getContextName()); String authMethodName = ZapAuthenticationType.HTTP_BASIC_AUTHENTICATION.getZapAuthenticationMethod(); - clientApiWrapper.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); + clientApiWrapper.setAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams.toString()); String methodName = ZapSessionManagementType.HTTP_AUTH_SESSION_MANAGEMENT.getZapSessionManagementMethod(); @@ -770,12 +724,12 @@ private UserInformation initBasicAuthentication(String zapContextId, BasicLoginC return setupScanUserForZapContext(zapContextId, username, authCredentialsConfigParams.toString()); } - private UserInformation setupScanUserForZapContext(String zapContextId, String username, String authCredentialsConfigParams) throws ClientApiException { - String userId = clientApiWrapper.createNewUser(zapContextId, username); + private UserInformation setupScanUserForZapContext(int zapContextId, String username, String authCredentialsConfigParams) throws ClientApiException { + int userId = clientApiWrapper.createNewUser(zapContextId, username); LOG.info("For scan {}: Setting up user.", scanContext.getContextName()); clientApiWrapper.configureAuthenticationCredentials(zapContextId, userId, authCredentialsConfigParams.toString()); - String enabled = "true"; + boolean enabled = true; clientApiWrapper.setUserEnabled(zapContextId, userId, enabled); clientApiWrapper.setForcedUser(zapContextId, userId); @@ -785,20 +739,9 @@ private UserInformation setupScanUserForZapContext(String zapContextId, String u return userInfo; } - private void setupAuthenticationAndSessionManagementMethodForScriptLogin(String zapContextId) throws ClientApiException { - // authenticationMethodConfigparams in case of manual authentication is null, - // because it is - // configured automatically - String authMethodConfigParams = null; - String authMethodName = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); - clientApiWrapper.configureAuthenticationMethod(zapContextId, authMethodName, authMethodConfigParams); - - // sessionMethodConfigparams in case of cookie based session management is null, - // because it is - // configured automatically - String sessionMethodconfigparams = null; - String sessionMethodName = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); - clientApiWrapper.setSessionManagementMethod(zapContextId, sessionMethodName, sessionMethodconfigparams); + private void setupAuthenticationAndSessionManagementMethodForScriptLogin(int zapContextId) throws ClientApiException { + clientApiWrapper.setManualAuthenticationMethod(zapContextId); + clientApiWrapper.setCookieBasedSessionManagementMethod(zapContextId); } private boolean isAjaxSpiderStopped(String status) { @@ -850,6 +793,9 @@ private void cleanUpReplacerRules() throws ClientApiException { return; } + // Replacer rules are persistent even after restarting ZAP + // This means we need to cleanUp after every scan. + LOG.info("Start cleaning up replacer rules."); List httpHeaders = scanContext.getSecHubWebScanConfiguration().getHeaders().get(); for (HTTPHeaderConfiguration httpHeader : httpHeaders) { if (httpHeader.getOnlyForUrls().isEmpty()) { @@ -891,11 +837,11 @@ private void addXSecHubDASTHeader() throws ClientApiException { // description specifies the rule name, which will be set later in this method String description = X_SECHUB_DAST_HEADER_NAME; - String enabled = "true"; + boolean enabled = true; // "REQ_HEADER" means the header entry will be added to the requests if not // existing or replaced if already existing String matchtype = "REQ_HEADER"; - String matchregex = "false"; + boolean matchregex = false; // matchstring and replacement will be set to the header name and header value String matchstring = X_SECHUB_DAST_HEADER_NAME; @@ -912,17 +858,11 @@ private void addXSecHubDASTHeader() throws ClientApiException { clientApiWrapper.addReplacerRule(description, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); } - private boolean isScriptLoginWanted() { - if (scanContext.getGroovyScriptLoginFile() == null) { - return false; - } - if (!scanContext.getGroovyScriptLoginFile().isFile()) { - return false; - } - // TODO check if templateData are configured inside SecHub config - return true; + private boolean scriptLoginWanted() { + return scanContext.getGroovyScriptLoginFile() != null; } - record UserInformation(String userName, String zapuserId) { + record UserInformation(String userName, int zapuserId) { } + } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java new file mode 100644 index 0000000000..a7f1da3b3c --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java @@ -0,0 +1,26 @@ +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import java.util.regex.Pattern; + +public class JWTSupport { + + private static final Pattern JWT_PATTERN = Pattern.compile("^[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_.+/=]*$"); + + /** + * Performs some tests to see if the given value is a JWT. + * + * @param value + * @return true if all tests pass and the value is a JWT, + * false otherwise. + */ + public boolean isJWT(String value) { + if (value == null) { + return false; + } + if (!JWT_PATTERN.matcher(value).matches()) { + return false; + } + String[] split = value.split("\\."); + return split[0].startsWith("eyJ") && split[1].startsWith("eyJ"); + } +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java index ce139751a5..092b1960f3 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java @@ -23,7 +23,11 @@ public class ZapScriptLogin { private ZapWrapperGroovyScriptExecutor groovyScriptExecutor; private ZapScriptLoginSessionGrabber sessionGrabber; - public ZapScriptLogin(ZapScriptLoginWebDriverFactory webDriverFactory, ZapWrapperGroovyScriptExecutor groovyScriptExecutor, + public ZapScriptLogin() { + this(new ZapScriptLoginWebDriverFactory(), new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionGrabber()); + } + + ZapScriptLogin(ZapScriptLoginWebDriverFactory webDriverFactory, ZapWrapperGroovyScriptExecutor groovyScriptExecutor, ZapScriptLoginSessionGrabber sessionGrabber) { this.webDriverFactory = webDriverFactory; this.groovyScriptExecutor = groovyScriptExecutor; @@ -54,20 +58,17 @@ public String login(ZapScanContext scanContext, ClientApiWrapper clientApiWrappe LOG.info("Calling session grabber to read the HTTP session data and pass them to ZAP."); return sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - } catch (IOException e) { - throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.IO_ERROR); - } catch (ScriptException e) { - throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); + } catch (IOException | ScriptException e) { + throw new ZapWrapperRuntimeException("An error happened while executing the script file.", e, ZapWrapperExitCode.IO_ERROR); } catch (ClientApiException e) { - throw new ZapWrapperRuntimeException(e.getMessage(), e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); + throw new ZapWrapperRuntimeException("An error happened while grabbing the session data.", e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); } finally { firefox.quit(); } } - public void cleanUpScriptLoginData(String targetUrl, ClientApiWrapper clientApiWrapper) { + public void cleanUpScriptLoginData(String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { sessionGrabber.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); - } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java index 68b7f8f8d1..45af4fe7aa 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java @@ -2,7 +2,6 @@ package com.mercedesbenz.sechub.zapwrapper.scan.login; import java.util.Map; -import java.util.regex.Pattern; import org.openqa.selenium.Cookie; import org.openqa.selenium.JavascriptExecutor; @@ -23,7 +22,15 @@ public class ZapScriptLoginSessionGrabber { private static final String LOCAL_STORAGE = "localStorage"; private static final String SESSION_STORAGE = "sessionStorage"; - private static final Pattern JWT_PATTERN = Pattern.compile("^[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_.+/=]*$"); + private JWTSupport jwtSupport; + + public ZapScriptLoginSessionGrabber() { + this(new JWTSupport()); + } + + ZapScriptLoginSessionGrabber(JWTSupport jwtSupport) { + this.jwtSupport = jwtSupport; + } /** * The sessionGrabber will add all necessary session data to ZAP. @@ -35,25 +42,21 @@ public class ZapScriptLoginSessionGrabber { * @throws ClientApiException */ public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { - LOG.info("Removing old session data inside ZAP if necessary."); cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); - LOG.info("Add new HTTP session token: {} to ZAP.", SESSION_TOKEN_IDENTIFIER); clientApiWrapper.addHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); - LOG.info("Create new empty HTTP session: {} in ZAP.", SESSION_IDENTIFIER); clientApiWrapper.createEmptyHTTPSession(targetUrl, SESSION_IDENTIFIER); - LOG.info("Adding all cookies to ZAP HTTP session: {}", SESSION_IDENTIFIER); for (Cookie cookie : firefox.manage().getCookies()) { clientApiWrapper.setHTTPSessionTokenValue(targetUrl, SESSION_IDENTIFIER, cookie.getName(), cookie.getValue()); } - LOG.info("Set ZAP HTTP session: {} as active session to use.", SESSION_IDENTIFIER); clientApiWrapper.setActiveHTTPSession(targetUrl, SESSION_IDENTIFIER); - addJwtAsReplacerRuleToZap(firefox, clientApiWrapper); + if (!addJwtAsReplacerRuleToZap(firefox, clientApiWrapper, LOCAL_STORAGE)) { + addJwtAsReplacerRuleToZap(firefox, clientApiWrapper, SESSION_STORAGE); + } - String followRedirects = "true"; - LOG.info("Accessing target URL: {} via ZAP to make sure it is added to the sites tree.", targetUrl); + boolean followRedirects = true; clientApiWrapper.accessUrlViaZap(targetUrl, followRedirects); return SESSION_IDENTIFIER; @@ -66,30 +69,36 @@ public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl * @param targetUrl * @param clientApiWrapper */ - public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiWrapper clientApiWrapper) { + public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { try { clientApiWrapper.removeHTTPSession(targetUrl, SESSION_IDENTIFIER); } catch (ClientApiException e) { - LOG.info("Could not find old HTTP session, nothing needs to be removed."); + if (e.getMessage().equalsIgnoreCase("Connection refused")) { + throw e; + } } try { clientApiWrapper.removeHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); } catch (ClientApiException e) { - LOG.info("Could not find old HTTP session token, nothing needs to be removed."); + if (e.getMessage().equalsIgnoreCase("Connection refused")) { + throw e; + } } try { clientApiWrapper.removeReplacerRule(JWT_REPLACER_DESCRIPTION); } catch (ClientApiException e) { - LOG.info("Could not find old JWT repalcer rule, nothing needs to be removed."); + if (e.getMessage().equalsIgnoreCase("Connection refused")) { + throw e; + } } } - private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrapper clientApiWrapper) throws ClientApiException { - String enabled = "true"; + private boolean addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrapper clientApiWrapper, String storageType) throws ClientApiException { + boolean enabled = true; // "REQ_HEADER" means the header entry will be added to the requests if not // existing or replaced if already existing String matchtype = "REQ_HEADER"; - String matchregex = "false"; + boolean matchregex = false; // matchstring and replacement will be set to the header name and header value String matchstring = "Authorization"; @@ -102,27 +111,18 @@ private void addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrapper c // any URL String url = null; - LOG.info("Searching: {} for JWT and add JWT as replacer rule.", LOCAL_STORAGE); - Map localStorage = retrieveStorage(firefox, LOCAL_STORAGE); + LOG.info("Searching: {} for JWT and add JWT as replacer rule.", storageType); + Map localStorage = retrieveStorage(firefox, storageType); for (String key : localStorage.keySet()) { String value = localStorage.get(key); - if (isJWT(value)) { + if (jwtSupport.isJWT(value)) { replacement = "Bearer %s".formatted(value); clientApiWrapper.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); - return; - } - } - LOG.info("Searching: {} for JWT and add JWT as replacer rule.", SESSION_STORAGE); - Map sessionStorage = retrieveStorage(firefox, SESSION_STORAGE); - for (String key : sessionStorage.keySet()) { - String value = sessionStorage.get(key); - if (isJWT(value)) { - replacement = "Bearer %s".formatted(value); - clientApiWrapper.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); - return; + return true; } } + return false; } private Map retrieveStorage(JavascriptExecutor jsExecutor, String storageType) { @@ -139,16 +139,4 @@ private Map retrieveStorage(JavascriptExecutor jsExecutor, Strin Map storage = (Map) jsExecutor.executeScript(script); return storage; } - - private boolean isJWT(String value) { - if (value == null) { - return false; - } - if (!JWT_PATTERN.matcher(value).matches()) { - return false; - } - String[] split = value.split("\\."); - return split[0].startsWith("eyJ") && split[1].startsWith("eyJ"); - } - } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java index e57fcd1728..b4c6cbca8e 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java @@ -25,7 +25,17 @@ public FirefoxDriver createFirefoxWebdriver(ProxyInformation proxyInformation, b if (proxyInformation != null) { LOG.info("Adding proxy to firefox browser options."); - String proxyString = "%s:%s".formatted(proxyInformation.getHost(), proxyInformation.getPort()); + String username = proxyInformation.getUsername(); + String password = proxyInformation.getPassword(); + String host = proxyInformation.getHost(); + int port = proxyInformation.getPort(); + // Realm seems to be not supported by default + String proxyString = null; + if (username != null && password != null) { + proxyString = "%s:%s@%s:%s".formatted(username, password, host, port); + } else { + proxyString = "%s:%s".formatted(host, port); + } Proxy proxy = new Proxy(); proxy.setHttpProxy(proxyString); proxy.setSslProxy(proxyString); diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java index c2d8bd7ab9..3db3471467 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java @@ -23,8 +23,8 @@ import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; import com.mercedesbenz.sechub.commons.model.login.WebLoginTOTPConfiguration; import com.mercedesbenz.sechub.zapwrapper.config.ZapScanContext; -import com.mercedesbenz.sechub.zapwrapper.util.StringDecoder; import com.mercedesbenz.sechub.zapwrapper.util.TOTPGenerator; +import com.mercedesbenz.sechub.zapwrapper.util.ZapWrapperStringDecoder; public class ZapWrapperGroovyScriptExecutor { private static final Logger LOG = LoggerFactory.getLogger(ZapWrapperGroovyScriptExecutor.class); @@ -44,7 +44,7 @@ public void executeScript(File scriptFile, FirefoxDriver firefox, ZapScanContext } private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptEngine, FirefoxDriver firefox) { - // TODO use templates structure from sechub webscan config + // TODO 2024-11-21 jan: use templates structure from sechub webscan config SecHubWebScanConfiguration secHubWebScanConfiguration = scanContext.getSecHubWebScanConfiguration(); WebLoginConfiguration webLoginConfiguration = secHubWebScanConfiguration.getLogin().get(); @@ -52,15 +52,16 @@ private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptE TOTPGenerator totpGenerator = null; if (totp != null) { LOG.info("Trying to decode TOTP seed if necessary."); - StringDecoder stringDecoder = new StringDecoder(); - byte[] decodedSeedBytes = stringDecoder.decodeIfNecessary(totp.getSeed(), totp.getEncodingType()); + ZapWrapperStringDecoder zapWrapperStringDecoder = new ZapWrapperStringDecoder(); + byte[] decodedSeedBytes = zapWrapperStringDecoder.decodeIfNecessary(totp.getSeed(), totp.getEncodingType()); String decodedSeed = new String(decodedSeedBytes, StandardCharsets.UTF_8); LOG.info("Setting up TOTP generator for login."); totpGenerator = new TOTPGenerator(decodedSeed, totp.getTokenLength(), totp.getHashAlgorithm(), totp.getValidityInSeconds()); } - // TODO read the username and password from templateData as soon as it is + // TODO 2024-11-21 jan: read the username and password from templateData as soon + // as it is // implemented String user = "DUMMY"; String password = "DUMMY"; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java index 71405bca16..63a84f53aa 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/EnvironmentVariableConstants.java @@ -4,21 +4,19 @@ public class EnvironmentVariableConstants { public static final String ZAP_HOST_ENV_VARIABLE_NAME = "ZAP_HOST"; - public static final String ZAP_PORT_ENV_VARIABLE_NAME = "ZAP_PORT"; - public static final String ZAP_API_KEY_ENV_VARIABLE_NAME = "ZAP_API_KEY"; public static final String PROXY_HOST_ENV_VARIABLE_NAME = "PROXY_HOST"; - public static final String PROXY_PORT_ENV_VARIABLE_NAME = "PROXY_PORT"; + public static final String PROXY_REALM_ENV_VARIABLE_NAME = "PROXY_REALM"; + public static final String PROXY_USERNAME_ENV_VARIABLE_NAME = "PROXY_USERNAME"; + public static final String PROXY_PASSWORD_ENV_VARIABLE_NAME = "PROXY_PASSWORD"; public static final String ZAP_DEACTIVATED_RULE_REFERENCES = "ZAP_DEACTIVATED_RULE_REFERENCES"; public static final String PDS_JOB_EXTRACTED_SOURCES_FOLDER = "PDS_JOB_EXTRACTED_SOURCES_FOLDER"; - public static final String PDS_JOB_USER_MESSAGES_FOLDER = "PDS_JOB_USER_MESSAGES_FOLDER"; - public static final String PDS_JOB_EVENTS_FOLDER = "PDS_JOB_EVENTS_FOLDER"; public static final String ZAP_GROOVY_LOGIN_SCRIPT_FILE = "ZAP_GROOVY_LOGIN_SCRIPT_FILE"; diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java index 7df87fcaba..d5b6a89917 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java @@ -21,19 +21,12 @@ public class TOTPGenerator { private static final int ONE_SECOND_IN_MILLISECONDS = 1000; - private static final int DEFAULT_TOTP_LENGTH = 6; - private static final int DEFAULT_TOKEN_VALIDITY_TIME_IN_SECONDS = 30; - private SealedObject seed; private String hashAlgorithmName; private int totpLength; private int tokenValidityTimeInSeconds; private long digitsTruncate; - public TOTPGenerator(String seed) { - this(seed, DEFAULT_TOTP_LENGTH, TOTPHashAlgorithm.HMAC_SHA1, DEFAULT_TOKEN_VALIDITY_TIME_IN_SECONDS); - } - public TOTPGenerator(String seed, int totpLength, TOTPHashAlgorithm hashAlgorithm, int tokenValidityTimeInSeconds) { if (seed == null) { throw new IllegalArgumentException("The specified TOTP seed must not be null!"); diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoder.java similarity index 89% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoder.java index 1a1fecbede..38d1163e13 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoder.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoder.java @@ -10,7 +10,7 @@ import com.mercedesbenz.sechub.commons.model.login.EncodingType; -public class StringDecoder { +public class ZapWrapperStringDecoder { private static final String HEX_REGEX = "^(0x|#)?[\\p{XDigit}]+$"; private static final Pattern HEX_PATTERN = Pattern.compile(HEX_REGEX); @@ -21,6 +21,15 @@ public class StringDecoder { private static final String BASE64_REGEX = "^[-A-Za-z0-9+/]+=*$"; private static final Pattern BASE64_PATTERN = Pattern.compile(BASE64_REGEX); + /** + * Decode the given string seed, by using the given encoding type. + * + * @param seed + * @param encodingType + * @return decoded seed + * + * @throws IllegalArgumentException if the seed is null + */ public byte[] decodeIfNecessary(String seed, EncodingType encodingType) { if (seed == null) { throw new IllegalArgumentException("The secret key must not be null!"); @@ -60,7 +69,7 @@ public byte[] decodeIfNecessary(String seed, EncodingType encodingType) { * 'example1', which technically would match the condition for BASE64 below. * * @param string - * @return + * @return encoding type, never null */ private EncodingType detectEncoding(String string) { if (HEX_PATTERN.matcher(string).matches()) { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index 158698c337..a5f4ef3f30 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -108,6 +108,9 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ when(settings.getZapApiKey()).thenReturn(apiKey); when(settings.getProxyHost()).thenReturn(proxy); when(settings.getProxyPort()).thenReturn(proxyPort); + when(settings.getProxyRealm()).thenReturn("realm"); + when(settings.getProxyUsername()).thenReturn("user"); + when(settings.getProxyPassword()).thenReturn("password"); when(ruleProvider.fetchDeactivatedRuleReferences(any())).thenReturn(new DeactivatedRuleReferences()); /* execute */ @@ -124,11 +127,14 @@ void result_contains_server_config_with_arguments_from_command_line_settings_no_ assertEquals(proxyPort, result.getProxyInformation().getPort()); verify(envVariableReader, never()).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); - verify(envVariableReader, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); - verify(envVariableReader, never()).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); verify(envVariableReader, never()).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(PROXY_REALM_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(PROXY_USERNAME_ENV_VARIABLE_NAME); + verify(envVariableReader, never()).readAsString(PROXY_PASSWORD_ENV_VARIABLE_NAME); } @ParameterizedTest @@ -145,11 +151,24 @@ void result_contains_server_config_with_arguments_from_environment_when_command_ when(envVariableReader.readAsString(PROXY_HOST_ENV_VARIABLE_NAME)).thenReturn(proxy); when(envVariableReader.readAsInt(PROXY_PORT_ENV_VARIABLE_NAME)).thenReturn(proxyPort); + when(envVariableReader.readAsString(PROXY_REALM_ENV_VARIABLE_NAME)).thenReturn("realm"); + when(envVariableReader.readAsString(PROXY_USERNAME_ENV_VARIABLE_NAME)).thenReturn("username"); + when(envVariableReader.readAsString(PROXY_PASSWORD_ENV_VARIABLE_NAME)).thenReturn("password"); /* execute */ ZapScanContext result = factoryToTest.create(settings); /* test */ + verify(envVariableReader, times(1)).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + + verify(envVariableReader, times(1)).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsString(PROXY_REALM_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsString(PROXY_USERNAME_ENV_VARIABLE_NAME); + verify(envVariableReader, times(1)).readAsString(PROXY_PASSWORD_ENV_VARIABLE_NAME); + ZapServerConfiguration serverConfig = result.getServerConfig(); assertNotNull(serverConfig); assertEquals(host, serverConfig.getZaproxyHost()); @@ -157,6 +176,9 @@ void result_contains_server_config_with_arguments_from_environment_when_command_ assertEquals(apiKey, serverConfig.getZaproxyApiKey()); assertEquals(proxy, result.getProxyInformation().getHost()); assertEquals(proxyPort, result.getProxyInformation().getPort()); + assertEquals("realm", result.getProxyInformation().getRealm()); + assertEquals("username", result.getProxyInformation().getUsername()); + assertEquals("password", result.getProxyInformation().getPassword()); } @Test diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelperTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelperTest.java deleted file mode 100644 index d00297004f..0000000000 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ScanDurationHelperTest.java +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.zapwrapper.helper; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class ScanDurationHelperTest { - - private ScanDurationHelper scanDurationHelperToTest; - - @BeforeEach - void beforeEach() { - scanDurationHelperToTest = new ScanDurationHelper(); - } - - @Test - void compute_max_durations_activeScan_disabled_ajaxSpider_disabled() { - /* prepare */ - boolean activeScanEnabled = false; - boolean ajaxSpiderEnabled = false; - long maxScanDuration = 10000; - - /* execute */ - long spiderDuration = scanDurationHelperToTest.computeSpiderMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, maxScanDuration); - long remainingMaxDuration = maxScanDuration - spiderDuration; - long passiveScanDuration = scanDurationHelperToTest.computePassiveScanMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - - /* test */ - assertEquals(5000, spiderDuration); - assertEquals(5000, passiveScanDuration); - } - - @Test - void compute_max_durations_activeScan_disabled_ajaxSpider_enabled() { - /* prepare */ - boolean activeScanEnabled = false; - boolean ajaxSpiderEnabled = true; - long maxScanDuration = 10000; - - /* execute */ - long ajaxSpiderDuration = scanDurationHelperToTest.computeAjaxSpiderMaxScanDuration(activeScanEnabled, maxScanDuration); - long remainingMaxDuration = maxScanDuration - ajaxSpiderDuration; - long spiderDuration = scanDurationHelperToTest.computeSpiderMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - remainingMaxDuration = remainingMaxDuration - spiderDuration; - long passiveScanDuration = scanDurationHelperToTest.computePassiveScanMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - - /* test */ - assertEquals(7000, ajaxSpiderDuration); - assertEquals(900, spiderDuration); - assertEquals(2100, passiveScanDuration); - } - - @Test - void compute_max_durations_activeScan_enabled_ajaxSpider_disabled() { - /* prepare */ - boolean activeScanEnabled = true; - boolean ajaxSpiderEnabled = false; - long maxScanDuration = 10000; - - /* execute */ - long spiderDuration = scanDurationHelperToTest.computeSpiderMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, maxScanDuration); - long remainingMaxDuration = maxScanDuration - spiderDuration; - long passiveScanDuration = scanDurationHelperToTest.computePassiveScanMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - long activeScanDuration = remainingMaxDuration - passiveScanDuration; - - /* test */ - assertEquals(3000, spiderDuration); - assertEquals(2100, passiveScanDuration); - assertEquals(4900, activeScanDuration); - } - - @Test - void compute_max_durations_activeScan_enabled_ajaxSpider_enabled() { - /* prepare */ - boolean activeScanEnabled = true; - boolean ajaxSpiderEnabled = true; - long maxScanDuration = 10000; - - /* execute */ - long ajaxSpiderDuration = scanDurationHelperToTest.computeAjaxSpiderMaxScanDuration(activeScanEnabled, maxScanDuration); - long remainingMaxDuration = maxScanDuration - ajaxSpiderDuration; - long spiderDuration = scanDurationHelperToTest.computeSpiderMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - remainingMaxDuration = remainingMaxDuration - spiderDuration; - long passiveScanDuration = scanDurationHelperToTest.computePassiveScanMaxScanDuration(activeScanEnabled, ajaxSpiderEnabled, remainingMaxDuration); - long activeScanDuration = remainingMaxDuration - passiveScanDuration; - - /* test */ - assertEquals(4000, ajaxSpiderDuration); - assertEquals(600, spiderDuration); - assertEquals(540, passiveScanDuration); - assertEquals(4860, activeScanDuration); - } - -} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java index 1b358e1212..11f288c0ac 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/helper/ZapPDSEventHandlerTest.java @@ -10,16 +10,23 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; import com.mercedesbenz.sechub.zapwrapper.cli.ZapWrapperRuntimeException; class ZapPDSEventHandlerTest { - @Test - void file_does_not_exist_and_so_no_scan_is_cancelled() throws IOException { + @ParameterizedTest + @NullSource + @EmptySource + @ValueSource(strings = { " ", "not-existing" }) + void invalid_parent_directories_result_in_no_scan_is_cancelled(String value) throws IOException { /* prepare */ String scanContextName = UUID.randomUUID().toString(); - ZapPDSEventHandler zapPDSEventHandler = new ZapPDSEventHandler(""); + ZapPDSEventHandler zapPDSEventHandler = new ZapPDSEventHandler(value); /* execute + test */ assertFalse(zapPDSEventHandler.isScanCancelled()); diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java index b96cd0ed04..e4260a0486 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java @@ -40,7 +40,6 @@ import com.mercedesbenz.sechub.zapwrapper.config.data.RuleReference; import com.mercedesbenz.sechub.zapwrapper.config.data.ZapFullRuleset; import com.mercedesbenz.sechub.zapwrapper.helper.IncludeExcludeToZapURLHelper; -import com.mercedesbenz.sechub.zapwrapper.helper.ScanDurationHelper; import com.mercedesbenz.sechub.zapwrapper.helper.ZapPDSEventHandler; import com.mercedesbenz.sechub.zapwrapper.helper.ZapProductMessageHelper; import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; @@ -66,7 +65,7 @@ class ZapScannerTest { private static final String CONTEXT_NAME = "context-name"; @BeforeEach - void beforeEach() { + void beforeEach() throws ClientApiException { clientApiWrapper = mock(); scanContext = mock(); zapPDSEventHandler = mock(); @@ -80,7 +79,6 @@ void beforeEach() { /* @formatter:off */ scannerToTest = new ZapScanner(clientApiWrapper, scanContext, - new ScanDurationHelper(), new UrlUtil(), systemUtil, scriptLogin); @@ -108,10 +106,10 @@ void beforeEach() { @Test void setup_standard_configuration_results_in_expected_calls() throws ClientApiException { /* prepare */ - when(clientApiWrapper.createNewSession(scanContext.getContextName(), "true")).thenReturn(null); - when(clientApiWrapper.configureMaximumAlertsForEachRule("0")).thenReturn(null); + when(clientApiWrapper.createNewSession(scanContext.getContextName(), true)).thenReturn(null); + when(clientApiWrapper.setMaximumAlertsForEachRuleToUnlimited()).thenReturn(null); when(clientApiWrapper.enableAllPassiveScannerRules()).thenReturn(null); - when(clientApiWrapper.enableAllActiveScannerRulesForPolicy(null)).thenReturn(null); + when(clientApiWrapper.enableAllActiveScannerRulesForDefaultPolicy()).thenReturn(null); when(clientApiWrapper.setAjaxSpiderBrowserId(BROWSER_ID)) .thenReturn(null); @@ -119,10 +117,10 @@ void setup_standard_configuration_results_in_expected_calls() throws ClientApiEx scannerToTest.setupStandardConfiguration(); /* test */ - verify(clientApiWrapper, times(1)).createNewSession(scanContext.getContextName(), "true"); - verify(clientApiWrapper, times(1)).configureMaximumAlertsForEachRule("0"); + verify(clientApiWrapper, times(1)).createNewSession(scanContext.getContextName(), true); + verify(clientApiWrapper, times(1)).setMaximumAlertsForEachRuleToUnlimited(); verify(clientApiWrapper, times(1)).enableAllPassiveScannerRules(); - verify(clientApiWrapper, times(1)).enableAllActiveScannerRulesForPolicy(null); + verify(clientApiWrapper, times(1)).enableAllActiveScannerRulesForDefaultPolicy(); verify(clientApiWrapper, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); } @@ -140,7 +138,7 @@ void deactivate_rules_ruleset_or_rules_to_deactivate_null_results_in_nothing_is_ /* test */ verify(clientApiWrapper, never()).disablePassiveScannerRule(any()); - verify(clientApiWrapper, never()).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiWrapper, never()).disableActiveScannerRuleForDefaultPolicy(any()); } @Test @@ -157,27 +155,27 @@ void deactivate_rules_results_in_rules_are_deactivated() throws ClientApiExcepti ZapFullRuleset ruleSet = new ZapFullRuleset().fromJSON(json); when(clientApiWrapper.disablePassiveScannerRule(any())).thenReturn(null); - when(clientApiWrapper.disableActiveScannerRuleForPolicy(any(), any())).thenReturn(null); + when(clientApiWrapper.disableActiveScannerRuleForDefaultPolicy(any())).thenReturn(null); /* execute */ scannerToTest.deactivateRules(ruleSet, deactivatedReferences); /* test */ verify(clientApiWrapper, times(1)).disablePassiveScannerRule(any()); - verify(clientApiWrapper, times(2)).disableActiveScannerRuleForPolicy(any(), any()); + verify(clientApiWrapper, times(2)).disableActiveScannerRuleForDefaultPolicy(any()); } @Test void setup_addtional_proxy_information_with_proxy_information_null_results_in_proxy_disabled() throws ClientApiException { /* prepare */ - when(clientApiWrapper.setHttpProxyEnabled("false")).thenReturn(null); + when(clientApiWrapper.setHttpProxyEnabled(false)).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(null); /* test */ - verify(clientApiWrapper, times(1)).setHttpProxyEnabled("false"); + verify(clientApiWrapper, times(1)).setHttpProxyEnabled(false); } @Test @@ -185,30 +183,29 @@ void setup_addtional_proxy_information_results_in_proxy_enabled() throws ClientA /* prepare */ String host = "127.0.0.1"; int port = 8000; - var portAsString = String.valueOf(port); - ProxyInformation proxyInformation = new ProxyInformation(host, port); + ProxyInformation proxyInformation = ProxyInformation.builder().setHost(host).setPort(port).build(); - when(clientApiWrapper.configureHttpProxy(host, portAsString, null, null, null)).thenReturn(null); - when(clientApiWrapper.setHttpProxyEnabled("true")).thenReturn(null); - when(clientApiWrapper.setHttpProxyAuthEnabled("false")).thenReturn(null); + when(clientApiWrapper.configureHttpProxy(proxyInformation)).thenReturn(null); + when(clientApiWrapper.setHttpProxyEnabled(true)).thenReturn(null); + when(clientApiWrapper.setHttpProxyAuthEnabled(false)).thenReturn(null); /* execute */ scannerToTest.setupAdditonalProxyConfiguration(proxyInformation); /* test */ - verify(clientApiWrapper, times(1)).configureHttpProxy(host, portAsString, null, null, null); - verify(clientApiWrapper, times(1)).setHttpProxyEnabled("true"); - verify(clientApiWrapper, times(1)).setHttpProxyAuthEnabled("false"); + verify(clientApiWrapper, times(1)).configureHttpProxy(proxyInformation); + verify(clientApiWrapper, times(1)).setHttpProxyEnabled(true); + verify(clientApiWrapper, times(1)).setHttpProxyAuthEnabled(false); } @Test void create_context_results_in_expected_calls() throws ClientApiException { /* prepare */ - String expectedContextId = "random-id"; + int expectedContextId = 12345; when(clientApiWrapper.createNewContext(CONTEXT_NAME)).thenReturn(expectedContextId); /* execute */ - String contextId = scannerToTest.createContext(); + int contextId = scannerToTest.createContext(); /* test */ assertEquals(expectedContextId, contextId); @@ -222,13 +219,13 @@ void add_replacer_rules_for_headers_with_no_headers_results_add_replacer_rule_is SecHubWebScanConfiguration sechubwebScanConfig = new SecHubWebScanConfiguration(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubwebScanConfig); - when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiWrapper, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, never()).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); } @ParameterizedTest @@ -239,14 +236,14 @@ void add_replacer_rules_for_headers_with_no_onlyForUrls_results_add_replacer_rul SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiWrapper, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(times)).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); } @ParameterizedTest @@ -257,7 +254,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(sechubScanConfigJSON).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); @@ -270,7 +267,7 @@ void add_replacer_rules_for_headers_with_onlyForUrls_results_add_replacer_rule_i times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiWrapper, times(times)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(times)).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); } @Test @@ -315,14 +312,14 @@ void add_replacer_rules_for_headers_with_data_section_results_add_replacer_rule_ headerFiles.put("Other", new File("src/test/resources/header-value-files/token.txt")); when(scanContext.getHeaderValueFiles()).thenReturn(headerFiles); - when(clientApiWrapper.addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any())).thenReturn(apiResponse); /* execute */ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiWrapper, times(1)).addReplacerRule("Key", "true", "REQ_HEADER", "false", "Key", "header-token", null, null); - verify(clientApiWrapper, times(1)).addReplacerRule("Other", "true", "REQ_HEADER", "false", "Other", "token", null, null); + verify(clientApiWrapper, times(1)).addReplacerRule("Key", true, "REQ_HEADER", false, "Key", "header-token", null, null); + verify(clientApiWrapper, times(1)).addReplacerRule("Other", true, "REQ_HEADER", false, "Other", "token", null, null); } @ParameterizedTest @@ -345,7 +342,7 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o when(scanContext.getZapURLsExcludeSet()).thenReturn(excludes); when(clientApiWrapper.addIncludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); - when(clientApiWrapper.accessUrlViaZap(any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.accessUrlViaZap(any(), anyBoolean())).thenReturn(apiResponse); when(clientApiWrapper.addExcludeUrlPatternToContext(any(), any())).thenReturn(apiResponse); /* @formatter:off */ @@ -360,32 +357,31 @@ void set_includes_and_excludes_api_support_is_called_once_for_each_include_and_o /* test */ verify(clientApiWrapper, times(includes.size())).addIncludeUrlPatternToContext(any(), any()); // make sure this method is only called for includes without wildcards - verify(clientApiWrapper, times(includesWithoutWildcards)).accessUrlViaZap(any(), any()); + verify(clientApiWrapper, times(includesWithoutWildcards)).accessUrlViaZap(any(), anyBoolean()); verify(clientApiWrapper, times(excludes.size())).addExcludeUrlPatternToContext(any(), any()); } @Test void import_openapi_file_but_api_file_is_null_api_support_is_never_called() throws ClientApiException { /* prepare */ - String contextId = "context-id"; - + int contextId = 12345; when(scanContext.getSecHubWebScanConfiguration()).thenReturn(new SecHubWebScanConfiguration()); - when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); - when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), anyInt())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), anyInt())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiWrapper, never()).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), anyInt()); + verify(clientApiWrapper, never()).importOpenApiDefintionFromUrl(any(), any(), anyInt()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-file.json" }) void import_openapi_file_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ - String contextId = "context-id"; + int contextId = 12345; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); @@ -395,40 +391,40 @@ void import_openapi_file_api_support_is_called_once(String sechubConfigFile) thr when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), anyInt())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), anyInt()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-from-url.json" }) void import_openapi_defintion_from_url_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ - String contextId = "context-id"; + int contextId = 12345; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); - when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), anyInt())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiDefintionFromUrl(any(), any(), anyInt())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); - verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), anyInt()); + verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), anyInt()); } @ParameterizedTest @ValueSource(strings = { "src/test/resources/sechub-config-examples/no-auth-with-openapi-from-file-and-url.json" }) void import_openapi_from_file_and_from_url_api_support_is_called_once(String sechubConfigFile) throws ClientApiException { /* prepare */ - String contextId = "context-id"; + int contextId = 12345; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); @@ -438,14 +434,14 @@ void import_openapi_from_file_and_from_url_api_support_is_called_once(String sec when(scanContext.getApiDefinitionFiles()).thenReturn(apiFiles); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.importOpenApiFile(any(), any(), any())).thenReturn(apiResponse); + when(clientApiWrapper.importOpenApiFile(any(), any(), anyInt())).thenReturn(apiResponse); /* execute */ scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), any()); - verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), any()); + verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), anyInt()); + verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), anyInt()); } @Test @@ -457,7 +453,7 @@ void import_client_certificate_file_but_client_certificate_file_is_null_api_supp scannerToTest.importClientCertificate(); /* test */ - verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), any()); + verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), anyInt()); } @Test @@ -561,7 +557,7 @@ void import_client_certificate_file_but_without_password_api_support_is_called_o "src/test/resources/sechub-config-examples/form-based-auth.json" }) void configure_login_inside_zap_using_no_auth_and_unsupported_auth_return_null(String sechubConfigFile) throws ClientApiException { /* prepare */ - String contextId = "context-id"; + int contextId = 12345; String json = TestFileReader.readTextFromFile(sechubConfigFile); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); @@ -577,8 +573,8 @@ void configure_login_inside_zap_using_no_auth_and_unsupported_auth_return_null(S @Test void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() throws ClientApiException, MalformedURLException { /* prepare */ - String contextId = "context-id"; - String userId = "user-id"; + int userId = 123; + int contextId = 12345; URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); String json = TestFileReader.readTextFromFile("src/test/resources/sechub-config-examples/basic-auth.json"); SecHubWebScanConfiguration sechubWebScanConfig = SecHubScanConfiguration.createFromJSON(json).getWebScan().get(); @@ -591,7 +587,7 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr when(scanContext.getTargetUrl()).thenReturn(targetUrl); when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); - when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); @@ -607,7 +603,7 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr verify(scanContext, times(2)).getTargetUrl(); - verify(clientApiWrapper, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiWrapper, times(1)).setAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); verify(clientApiWrapper, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); @@ -618,8 +614,8 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr @Test void configure_login_inside_zap_using_script_auth_without_script_file_results_in_script_login_not_being_called() throws Exception { /* prepare */ - String contextId = "context-id"; - String userId = "user-id"; + int userId = 123; + int contextId = 12345; String userName = "user"; URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); SecHubWebScanConfiguration sechubWebScanConfig = new SecHubWebScanConfiguration(); @@ -636,7 +632,7 @@ void configure_login_inside_zap_using_script_auth_without_script_file_results_in when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(scanContext.getGroovyScriptLoginFile()).thenReturn(null); - when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); @@ -655,8 +651,8 @@ void configure_login_inside_zap_using_script_auth_without_script_file_results_in @Test void configure_login_inside_zap_using_script_auth_with_existing_script_file_results_in_script_login_being_called() throws Exception { /* prepare */ - String contextId = "context-id"; - String userId = "user-id"; + int userId = 123; + int contextId = 12345; String userName = "DUMMY"; URL targetUrl = URI.create("https://127.0.0.1:8000").toURL(); SecHubWebScanConfiguration sechubWebScanConfig = new SecHubWebScanConfiguration(); @@ -664,8 +660,6 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu WebLoginConfiguration login = new WebLoginConfiguration(); sechubWebScanConfig.setLogin(Optional.of(login)); - String zapAuthenticationMethod = ZapAuthenticationType.MANUAL_AUTHENTICATION.getZapAuthenticationMethod(); - String zapSessionManagementMethod = ZapSessionManagementType.COOKIE_BASED_SESSION_MANAGEMENT.getZapSessionManagementMethod(); File scriptFile = new File("src/test/resources/login-script-examples/test-script.groovy"); when(scriptLogin.login(scanContext, clientApiWrapper)).thenReturn("zap-auth-session"); @@ -674,8 +668,8 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu when(scanContext.getSecHubWebScanConfiguration()).thenReturn(sechubWebScanConfig); when(scanContext.getGroovyScriptLoginFile()).thenReturn(scriptFile); - when(clientApiWrapper.configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any())).thenReturn(apiResponse); - when(clientApiWrapper.setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any())).thenReturn(apiResponse); + when(clientApiWrapper.setManualAuthenticationMethod(contextId)).thenReturn(apiResponse); + when(clientApiWrapper.setCookieBasedSessionManagementMethod(contextId)).thenReturn(apiResponse); when(clientApiWrapper.createNewUser(contextId, userName)).thenReturn(userId); when(clientApiWrapper.configureAuthenticationCredentials(eq(contextId), eq(userId), any())).thenReturn(apiResponse); when(clientApiWrapper.setForcedUser(contextId, userId)).thenReturn(apiResponse); @@ -689,10 +683,10 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu assertEquals(userId, userInformation.zapuserId()); verify(scriptLogin, times(1)).login(scanContext, clientApiWrapper); - verify(scanContext, times(2)).getGroovyScriptLoginFile(); + verify(scanContext, times(1)).getGroovyScriptLoginFile(); - verify(clientApiWrapper, times(1)).configureAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(clientApiWrapper, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiWrapper, times(1)).setManualAuthenticationMethod(contextId); + verify(clientApiWrapper, times(1)).setCookieBasedSessionManagementMethod(contextId); verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); verify(clientApiWrapper, times(1)).setForcedUser(contextId, userId); @@ -782,20 +776,16 @@ void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_e when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); - long scanDuration = 20000L; - when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForAjaxSpiderResults(scanDuration); + scannerToTest.waitForAjaxSpiderResults(); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).isActiveScanEnabled(); verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @@ -804,72 +794,37 @@ void wait_for_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApi /* prepare */ when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - long scanDuration = 1000L; - when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); - when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("Running").thenReturn("stopped"); /* execute */ - scannerToTest.waitForAjaxSpiderResults(scanDuration); + scannerToTest.waitForAjaxSpiderResults(); /* test */ - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiWrapper, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiWrapper, times(2)).getAjaxSpiderStatus(); verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @Test void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { /* prepare */ - String scanId = "12345"; - + int scanId = 111111; when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); - long scanDuration = 20000L; - when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForSpiderResults(scanId, scanDuration); + scannerToTest.waitForSpiderResults(scanId); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).isActiveScanEnabled(); verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); } - @Test - void wait_for_spider_scan_ended_results_in_expected_calls() throws ClientApiException { - /* prepare */ - String scanId = "12345"; - - when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - long scanDuration = 1000L; - when(scanContext.isActiveScanEnabled()).thenReturn(true); - ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); - when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); - - when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiWrapper.getSpiderStatusForScan(scanId)).thenReturn(42); - when(clientApiWrapper.logFullSpiderResults(scanId)).thenReturn(0L); - - /* execute */ - scannerToTest.waitForSpiderResults(scanId, scanDuration); - - /* test */ - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiWrapper, atLeast(1)).getSpiderStatusForScan(scanId); - verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); - verify(clientApiWrapper, times(1)).logFullSpiderResults(scanId); - } - @Test void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { @@ -877,22 +832,17 @@ void wait_for_passiveScan_scan_is_cancelled_results_in_exception_with_dedicated_ when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); - long scanDuration = 20000L; - when(scanContext.isActiveScanEnabled()).thenReturn(false); - when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); when(clientApiWrapper.getNumberOfPassiveScannerRecordsToScan()).thenReturn(12); /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.passiveScan(scanDuration); + scannerToTest.runAndWaitForPassiveScan(); }); /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).isAjaxSpiderEnabled(); verify(clientApiWrapper, atLeast(1)).getNumberOfPassiveScannerRecordsToScan(); } @@ -901,27 +851,20 @@ void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws Clien /* prepare */ when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - long scanDuration = 20000L; - when(scanContext.isActiveScanEnabled()).thenReturn(false); - when(scanContext.isAjaxSpiderEnabled()).thenReturn(false); when(clientApiWrapper.getNumberOfPassiveScannerRecordsToScan()).thenReturn(0); /* execute */ - scannerToTest.passiveScan(scanDuration); + scannerToTest.runAndWaitForPassiveScan(); /* test */ - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(scanContext, times(1)).isAjaxSpiderEnabled(); verify(clientApiWrapper, times(1)).getNumberOfPassiveScannerRecordsToScan(); } @Test void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_exit_code() throws ClientApiException { /* prepare */ - String scanId = "12345"; - long scanDuration = 20000L; - + int scanId = 111111; when(zapPDSEventHandler.isScanCancelled()).thenReturn(true); doCallRealMethod().when(zapPDSEventHandler).cancelScan(CONTEXT_NAME); @@ -930,7 +873,7 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e /* execute */ ZapWrapperRuntimeException exception = assertThrows(ZapWrapperRuntimeException.class, () -> { - scannerToTest.waitForActiveScanResults(scanId, scanDuration); + scannerToTest.waitForActiveScanResults(scanId); }); /* test */ @@ -943,16 +886,14 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e @Test void wait_for_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - String scanId = "12345"; - long scanDuration = 20000L; - + int scanId = 111111; when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); when(clientApiWrapper.getActiveScannerStatusForScan(scanId)).thenReturn(100); when(clientApiWrapper.stopActiveScan(scanId)).thenReturn(null); /* execute */ - scannerToTest.waitForActiveScanResults(scanId, scanDuration); + scannerToTest.waitForActiveScanResults(scanId); /* test */ verify(clientApiWrapper, atLeast(1)).getActiveScannerStatusForScan(scanId); @@ -964,71 +905,60 @@ void run_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiExcep /* prepare */ when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - long scanDuration = 1000L; - when(scanContext.isActiveScanEnabled()).thenReturn(true); - when(clientApiWrapper.stopAjaxSpider()).thenReturn(null); - when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("stopped"); + when(clientApiWrapper.getAjaxSpiderStatus()).thenReturn("Running").thenReturn("stopped"); /* execute */ - scannerToTest.runAjaxSpider(scanDuration); + scannerToTest.runAndWaitAjaxSpider(); /* test */ - verify(scanContext, times(1)).isActiveScanEnabled(); - verify(clientApiWrapper, atLeast(1)).getAjaxSpiderStatus(); + verify(clientApiWrapper, times(2)).getAjaxSpiderStatus(); verify(clientApiWrapper, times(1)).stopAjaxSpider(); } @Test void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - String scanId = "12345"; - long scanDuration = 1000L; - + int scanId = 111111; when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); - when(scanContext.isActiveScanEnabled()).thenReturn(true); ZapProductMessageHelper messageHelper = mock(ZapProductMessageHelper.class); when(scanContext.getZapProductMessageHelper()).thenReturn(messageHelper); when(clientApiWrapper.stopSpiderScan(scanId)).thenReturn(null); - when(clientApiWrapper.getSpiderStatusForScan(scanId)).thenReturn(42); + when(clientApiWrapper.getSpiderStatusForScan(scanId)).thenReturn(42).thenReturn(100); when(clientApiWrapper.logFullSpiderResults(scanId)).thenReturn(0L); - when(clientApiWrapper.startSpiderScan(any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiWrapper.startSpiderScan(any(), any(), anyBoolean(), any(), anyBoolean())).thenReturn(scanId); /* execute */ - scannerToTest.runSpider(scanDuration); + scannerToTest.runAndWaitForSpider(); /* test */ - verify(scanContext, times(1)).isActiveScanEnabled(); verify(scanContext, times(1)).getZapProductMessageHelper(); - verify(clientApiWrapper, atLeast(1)).getSpiderStatusForScan(scanId); + verify(clientApiWrapper, times(2)).getSpiderStatusForScan(scanId); verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); verify(clientApiWrapper, times(1)).logFullSpiderResults(scanId); - verify(clientApiWrapper, times(1)).startSpiderScan(any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(1)).startSpiderScan(any(), any(), anyBoolean(), any(), anyBoolean()); } @Test void run_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiException { /* prepare */ - String scanId = "12345"; - - long scanDuration = 20000L; - + int scanId = 111111; when(zapPDSEventHandler.isScanCancelled()).thenReturn(false); when(clientApiWrapper.getActiveScannerStatusForScan(scanId)).thenReturn(100); when(clientApiWrapper.stopActiveScan(scanId)).thenReturn(null); - when(clientApiWrapper.startActiveScan(any(), any(), any(), any(), any(), any())).thenReturn(scanId); + when(clientApiWrapper.startActiveScan(any(), anyBoolean(), anyBoolean(), any(), any(), any(), anyInt())).thenReturn(scanId); when(clientApiWrapper.atLeastOneURLDetected()).thenReturn(true); /* execute */ - scannerToTest.runActiveScan(scanDuration); + scannerToTest.runAndWaitActiveScan(scanId); /* test */ - verify(clientApiWrapper, atLeast(1)).getActiveScannerStatusForScan(scanId); + verify(clientApiWrapper, times(1)).getActiveScannerStatusForScan(scanId); verify(clientApiWrapper, times(1)).stopActiveScan(scanId); - verify(clientApiWrapper, times(1)).startActiveScan(any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(1)).startActiveScan(any(), anyBoolean(), anyBoolean(), any(), any(), any(), anyInt()); } static Stream headerPartWithoutOnlyForUrlsTestNamedArguments() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java new file mode 100644 index 0000000000..7a35e3a890 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java @@ -0,0 +1,33 @@ +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +class JWTSupportTest { + + private JWTSupport supportToTest = new JWTSupport(); + + @ParameterizedTest + @NullSource + @EmptySource + @ValueSource(strings = { " ", "12345", "1234.5678.91011", "gazde5237d.hw78287d32.di7g82dgiwegiafafea" }) + void invalid_values_isjwt_returns_false(String value) { + /* execute + test */ + assertFalse(supportToTest.isJWT(value)); + } + + @ParameterizedTest + @ValueSource(strings = { + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", + "eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.VUPWQZuClnkFbaEKCsPy7CZVMh5wxbCSpaAWFLpnTe9J0--PzHNeTFNXCrVHysAa3eFbuzD8_bLSsgTKC8SzHxRVSj5eN86vBPo_1fNfE7SHTYhWowjY4E_wuiC13yoj", + "eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.J5W09-rNx0pt5_HBiydR-vOluS6oD-RpYNa8PVWwMcBDQSXiw6-EPW8iSsalXPspGj3ouQjAnOP_4-zrlUUlvUIt2T79XyNeiKuooyIFvka3Y5NnGiOUBHWvWcWp4RcQFMBrZkHtJM23sB5D7Wxjx0-HFeNk-Y3UJgeJVhg5NaWXypLkC4y0ADrUBfGAxhvGdRdULZivfvzuVtv6AzW6NRuEE6DM9xpoWX_4here-yvLS2YPiBTZ8xbB3axdM99LhES-n52lVkiX5AWg2JJkEROZzLMpaacA_xlbUz_zbIaOaoqk8gB5oO7kI6sZej3QAdGigQy-hXiRnW_L98d4GQ" }) + void valid_values_isjwt_returns_true(String value) { + /* execute + test */ + assertTrue(supportToTest.isJWT(value)); + } + +} diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java index 7ada85c687..772a8961ea 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java @@ -28,17 +28,19 @@ class ZapScriptLoginSessionGrabberTest { private ClientApiWrapper clientApiWrapper; private FirefoxDriver firefox; private Options webDriverOptions; + private JWTSupport jwtSupport; private ApiResponse zapApiResponse; private static final String TARGET_URL = "http://example.com"; - private static final String FOLLOW_REDIRECTS = "true"; + private static final boolean FOLLOW_REDIRECTS = true; @BeforeEach void beforeEach() { zapApiResponse = mock(); firefox = mock(); webDriverOptions = mock(); + jwtSupport = mock(); clientApiWrapper = mock(ClientApiWrapper.class, new Answer() { @Override @@ -48,7 +50,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { } }); - sessionGrabberToTest = new ZapScriptLoginSessionGrabber(); + sessionGrabberToTest = new ZapScriptLoginSessionGrabber(jwtSupport); } @Test @@ -58,14 +60,13 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE Set cookies = Set.of(cookie); Map storage = new HashMap<>(); - // example from https://jwt.io/ - storage.put("jwt", - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"); + storage.put("jwt", "1234"); when(firefox.manage()).thenReturn(webDriverOptions); when(webDriverOptions.getCookies()).thenReturn(cookies); when(firefox.executeScript(anyString())).thenReturn(storage); + when(jwtSupport.isJWT(storage.get("jwt"))).thenReturn(true); /* execute */ sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); @@ -82,7 +83,7 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE verify(clientApiWrapper, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); verify(clientApiWrapper, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); verify(clientApiWrapper, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, times(1)).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } @@ -94,6 +95,7 @@ void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() thr when(webDriverOptions.getCookies()).thenReturn(Collections.emptySet()); when(firefox.executeScript(anyString())).thenReturn(Collections.emptyMap()); + when(jwtSupport.isJWT(anyString())).thenReturn(false); /* execute */ sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); @@ -102,7 +104,7 @@ void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() thr // both browser storages are checked now without JWT verify(firefox, times(2)).executeScript(anyString()); // no JWT can be added - verify(clientApiWrapper, never()).addReplacerRule(any(), any(), any(), any(), any(), any(), any(), any()); + verify(clientApiWrapper, never()).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); // no cookie can be added verify(clientApiWrapper, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java index 1d0a0c1fc4..3c67e4dead 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGeneratorTest.java @@ -24,7 +24,7 @@ class TOTPGeneratorTest { @Test void secret_key_being_null_throws_exception() { /* execute + test */ - assertThrows(IllegalArgumentException.class, () -> new TOTPGenerator(null)); + assertThrows(IllegalArgumentException.class, () -> new TOTPGenerator(null, 6, TOTPHashAlgorithm.HMAC_SHA1, 30)); } @Test @@ -36,7 +36,7 @@ void generate_the_excpected_otp_with_default_config() throws DecoderException { String expectedToken = "950308"; String seedDecoded = new String(seedBytes, StandardCharsets.UTF_8); - TOTPGenerator totpGenerator = new TOTPGenerator(seedDecoded); + TOTPGenerator totpGenerator = new TOTPGenerator(seedDecoded, 6, TOTPHashAlgorithm.HMAC_SHA1, 30); /* execute */ String generatedToken = totpGenerator.generateTOTP(timeMillis); diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoderTest.java similarity index 80% rename from sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java rename to sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoderTest.java index 7e5daa73c2..951fbaa6da 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/StringDecoderTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/util/ZapWrapperStringDecoderTest.java @@ -13,9 +13,9 @@ import com.mercedesbenz.sechub.commons.model.login.EncodingType; -class StringDecoderTest { +class ZapWrapperStringDecoderTest { - private StringDecoder decoderToTest = new StringDecoder(); + private ZapWrapperStringDecoder decoderToTest = new ZapWrapperStringDecoder(); @Test void when_seed_is_null_an_exception_is_thrown() { @@ -61,7 +61,7 @@ void encoded_values_are_decoded_correctly_ignoring_spaces_or_tabs(String value) } @ParameterizedTest - @ValueSource(strings = { "���", "NotEncoded!", "@:_DASF2daagjtz", "HelloWorld" }) + @ValueSource(strings = { "���", "NotEncoded!", "@:_DASF2daagjtz", "HelloWorld", }) void not_encoded_values_are_correctly_treated_ignoring_spaces_or_tabs(String value) throws DecoderException { /* execute */ byte[] decoded = decoderToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); @@ -70,4 +70,17 @@ void not_encoded_values_are_correctly_treated_ignoring_spaces_or_tabs(String val assertEquals(value, new String(decoded)); } + @ParameterizedTest + @ValueSource(strings = { "", " ", "\n\t\r" }) + void empty_values_are_correctly_treated_ignoring_spaces_or_tabs(String value) throws DecoderException { + /* prepare */ + String emptyString = ""; + + /* execute */ + byte[] decoded = decoderToTest.decodeIfNecessary(value, EncodingType.AUTODETECT); + + /* test */ + assertEquals(emptyString, new String(decoded)); + } + } From 1232db839be68dfab1ca960384711e875914f070 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Fri, 22 Nov 2024 15:24:24 +0100 Subject: [PATCH 09/13] Apply headers + update README.adoc #3622 --- sechub-wrapper-owasp-zap/README.adoc | 9 +++++++++ .../sechub/zapwrapper/scan/login/JWTSupport.java | 1 + .../sechub/zapwrapper/scan/login/JWTSupportTest.java | 1 + .../login-script-examples/invalid-script.groovy | 1 + .../resources/login-script-examples/test-script.groovy | 1 + 5 files changed, 13 insertions(+) diff --git a/sechub-wrapper-owasp-zap/README.adoc b/sechub-wrapper-owasp-zap/README.adoc index 6e0ad59d67..15dbaf0ce2 100644 --- a/sechub-wrapper-owasp-zap/README.adoc +++ b/sechub-wrapper-owasp-zap/README.adoc @@ -72,10 +72,19 @@ Usage: ZapWrapper [options] --proxyHost Specify a proxy host. You can also set the environment variable PROXY_HOST, instead of using this parameter. + --proxyPassword + Specify a proxy password. You can also set the environment variable + PROXY_PASSWORD, instead of using this parameter. --proxyPort Specify a proxy port. You can also set the environment variable PROXY_PORT, instead of using this parameter. Default: 0 + --proxyRealm + Specify a proxy realm. You can also set the environment variable + PROXY_REALM, instead of using this parameter. + --proxyUsername + Specify a proxy username. You can also set the environment variable + PROXY_USERNAME, instead of using this parameter. * --report The output file, where the report will be written to. --retryWaittimeInMilliseconds diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java index a7f1da3b3c..a35d298f4a 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.scan.login; import java.util.regex.Pattern; diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java index 7a35e3a890..6762c4d5d4 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupportTest.java @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.scan.login; import static org.junit.jupiter.api.Assertions.*; diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy index e4cb516a73..235b1f05a6 100644 --- a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/invalid-script.groovy @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.* diff --git a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy index b6db9d6909..c5cf4df533 100644 --- a/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy +++ b/sechub-wrapper-owasp-zap/src/test/resources/login-script-examples/test-script.groovy @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: MIT import static com.mercedesbenz.sechub.zapwrapper.scan.login.ZapScriptBindingKeys.* From e4a4459f089fb3d830273ec58924b611c01c3ecc Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Mon, 25 Nov 2024 07:35:17 +0100 Subject: [PATCH 10/13] Change webdriver proxy settings and add todo #3622 --- .../scan/login/ZapScriptLoginWebDriverFactory.java | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java index b4c6cbca8e..2c7c17ba10 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java @@ -25,17 +25,8 @@ public FirefoxDriver createFirefoxWebdriver(ProxyInformation proxyInformation, b if (proxyInformation != null) { LOG.info("Adding proxy to firefox browser options."); - String username = proxyInformation.getUsername(); - String password = proxyInformation.getPassword(); - String host = proxyInformation.getHost(); - int port = proxyInformation.getPort(); - // Realm seems to be not supported by default - String proxyString = null; - if (username != null && password != null) { - proxyString = "%s:%s@%s:%s".formatted(username, password, host, port); - } else { - proxyString = "%s:%s".formatted(host, port); - } + // TODO 2024-11-25 jan: add additional proxy data like credentials + String proxyString = "%s:%s".formatted(proxyInformation.getHost(), proxyInformation.getPort()); Proxy proxy = new Proxy(); proxy.setHttpProxy(proxyString); proxy.setSslProxy(proxyString); From 9b34ad4b09fd7c9d37de5ac2d00feec0c826bd67 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Tue, 26 Nov 2024 08:26:35 +0100 Subject: [PATCH 11/13] Refactoring to be able to close the browser earlier #3622 - add a ScriptLoginResult which contains all the session data - update the current script login to use the ScriptLoginResult - update and extend testcases --- .../scan/login/ScriptLoginResult.java | 60 ++++++++++++++ .../zapwrapper/scan/login/ZapScriptLogin.java | 33 +++----- ...=> ZapScriptLoginSessionConfigurator.java} | 49 ++++------- .../login/ZapScriptLoginWebDriverFactory.java | 2 + .../login/ZapWrapperGroovyScriptExecutor.java | 71 +++++++++++++--- .../sechub/zapwrapper/util/TOTPGenerator.java | 4 +- ...apScriptLoginSessionConfiguratorTest.java} | 82 ++++++++++++------- .../scan/login/ZapScriptLoginTest.java | 75 +++++++---------- .../ZapWrapperGroovyScriptExecutorTest.java | 55 ++++++++++--- 9 files changed, 279 insertions(+), 152 deletions(-) create mode 100644 sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ScriptLoginResult.java rename sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/{ZapScriptLoginSessionGrabber.java => ZapScriptLoginSessionConfigurator.java} (66%) rename sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/{ZapScriptLoginSessionGrabberTest.java => ZapScriptLoginSessionConfiguratorTest.java} (58%) diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ScriptLoginResult.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ScriptLoginResult.java new file mode 100644 index 0000000000..f436fc0706 --- /dev/null +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ScriptLoginResult.java @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.zapwrapper.scan.login; + +import java.util.*; + +import org.openqa.selenium.Cookie; + +public class ScriptLoginResult { + + private Set sessionCookies; + private Map localStorage; + private Map sessionStorage; + + private boolean loginFailed; + + public ScriptLoginResult() { + this.sessionCookies = new HashSet<>(); + this.localStorage = new HashMap<>(); + this.sessionStorage = new HashMap<>(); + } + + public Set getSessionCookies() { + return Collections.unmodifiableSet(sessionCookies); + } + + public void setSessionCookies(Set sessionCookies) { + if (sessionCookies != null) { + this.sessionCookies = sessionCookies; + } + } + + public Map getLocalStorage() { + return Collections.unmodifiableMap(localStorage); + } + + public void setLocalStorage(Map localStorage) { + if (localStorage != null) { + this.localStorage = localStorage; + } + } + + public Map getSessionStorage() { + return Collections.unmodifiableMap(sessionStorage); + } + + public void setSessionStorage(Map sessionStorage) { + if (sessionStorage != null) { + this.sessionStorage = sessionStorage; + } + } + + public boolean isLoginFailed() { + return loginFailed; + } + + public void setLoginFailed(boolean loginFailed) { + this.loginFailed = loginFailed; + } + +} diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java index 092b1960f3..827ef98799 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLogin.java @@ -2,11 +2,7 @@ package com.mercedesbenz.sechub.zapwrapper.scan.login; import java.io.File; -import java.io.IOException; -import javax.script.ScriptException; - -import org.openqa.selenium.firefox.FirefoxDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zaproxy.clientapi.core.ClientApiException; @@ -19,19 +15,16 @@ public class ZapScriptLogin { private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLogin.class); - private ZapScriptLoginWebDriverFactory webDriverFactory; private ZapWrapperGroovyScriptExecutor groovyScriptExecutor; - private ZapScriptLoginSessionGrabber sessionGrabber; + private ZapScriptLoginSessionConfigurator sessionConfigurator; public ZapScriptLogin() { - this(new ZapScriptLoginWebDriverFactory(), new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionGrabber()); + this(new ZapWrapperGroovyScriptExecutor(), new ZapScriptLoginSessionConfigurator()); } - ZapScriptLogin(ZapScriptLoginWebDriverFactory webDriverFactory, ZapWrapperGroovyScriptExecutor groovyScriptExecutor, - ZapScriptLoginSessionGrabber sessionGrabber) { - this.webDriverFactory = webDriverFactory; + ZapScriptLogin(ZapWrapperGroovyScriptExecutor groovyScriptExecutor, ZapScriptLoginSessionConfigurator sessionConfigurator) { this.groovyScriptExecutor = groovyScriptExecutor; - this.sessionGrabber = sessionGrabber; + this.sessionConfigurator = sessionConfigurator; } /** @@ -49,26 +42,22 @@ public String login(ZapScanContext scanContext, ClientApiWrapper clientApiWrappe "Expected a groovy script file to perform login, but no script was found. Cannot perform script login without the script file.", ZapWrapperExitCode.PDS_CONFIGURATION_ERROR); } - LOG.info("Creating selenium web driver."); - FirefoxDriver firefox = webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true); + LOG.info("Calling groovy script executor to execute login script."); + ScriptLoginResult loginResult = groovyScriptExecutor.executeScript(groovyScriptLoginFile, scanContext); + if (loginResult.isLoginFailed()) { + throw new ZapWrapperRuntimeException("An error happened during script login.", ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); + } try { - LOG.info("Calling groovy script executor to execute login script."); - groovyScriptExecutor.executeScript(groovyScriptLoginFile, firefox, scanContext); - LOG.info("Calling session grabber to read the HTTP session data and pass them to ZAP."); - return sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - } catch (IOException | ScriptException e) { - throw new ZapWrapperRuntimeException("An error happened while executing the script file.", e, ZapWrapperExitCode.IO_ERROR); + return sessionConfigurator.passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } catch (ClientApiException e) { throw new ZapWrapperRuntimeException("An error happened while grabbing the session data.", e, ZapWrapperExitCode.PRODUCT_EXECUTION_ERROR); - } finally { - firefox.quit(); } } public void cleanUpScriptLoginData(String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { - sessionGrabber.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); + sessionConfigurator.cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfigurator.java similarity index 66% rename from sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java rename to sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfigurator.java index 45af4fe7aa..f05f25e9bf 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabber.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfigurator.java @@ -4,56 +4,52 @@ import java.util.Map; import org.openqa.selenium.Cookie; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.firefox.FirefoxDriver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zaproxy.clientapi.core.ClientApiException; import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; -public class ZapScriptLoginSessionGrabber { - private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLoginSessionGrabber.class); +public class ZapScriptLoginSessionConfigurator { + private static final Logger LOG = LoggerFactory.getLogger(ZapScriptLoginSessionConfigurator.class); private static final String JWT_REPLACER_DESCRIPTION = "JWT"; private static final String SESSION_TOKEN_IDENTIFIER = "session-token"; private static final String SESSION_IDENTIFIER = "authenticated-session"; - private static final String LOCAL_STORAGE = "localStorage"; - private static final String SESSION_STORAGE = "sessionStorage"; - private JWTSupport jwtSupport; - public ZapScriptLoginSessionGrabber() { + public ZapScriptLoginSessionConfigurator() { this(new JWTSupport()); } - ZapScriptLoginSessionGrabber(JWTSupport jwtSupport) { + ZapScriptLoginSessionConfigurator(JWTSupport jwtSupport) { this.jwtSupport = jwtSupport; } /** - * The sessionGrabber will add all necessary session data to ZAP. + * This method will add all necessary session data to ZAP. ZAP can use this + * authenticated session for scanning. * - * @param firefox + * @param loginResult * @param targetUrl * @param clientApiWrapper * @return the name/identifier of the authenticated session inside ZAP * @throws ClientApiException */ - public String extractSessionAndPassToZAP(FirefoxDriver firefox, String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { + public String passSessionDataToZAP(ScriptLoginResult loginResult, String targetUrl, ClientApiWrapper clientApiWrapper) throws ClientApiException { cleanUpOldSessionDataIfNecessary(targetUrl, clientApiWrapper); clientApiWrapper.addHTTPSessionToken(targetUrl, SESSION_TOKEN_IDENTIFIER); clientApiWrapper.createEmptyHTTPSession(targetUrl, SESSION_IDENTIFIER); - for (Cookie cookie : firefox.manage().getCookies()) { + for (Cookie cookie : loginResult.getSessionCookies()) { clientApiWrapper.setHTTPSessionTokenValue(targetUrl, SESSION_IDENTIFIER, cookie.getName(), cookie.getValue()); } clientApiWrapper.setActiveHTTPSession(targetUrl, SESSION_IDENTIFIER); - if (!addJwtAsReplacerRuleToZap(firefox, clientApiWrapper, LOCAL_STORAGE)) { - addJwtAsReplacerRuleToZap(firefox, clientApiWrapper, SESSION_STORAGE); + if (!addJwtAsReplacerRuleToZap(loginResult.getSessionStorage(), clientApiWrapper)) { + addJwtAsReplacerRuleToZap(loginResult.getLocalStorage(), clientApiWrapper); } boolean followRedirects = true; @@ -93,7 +89,7 @@ public void cleanUpOldSessionDataIfNecessary(String targetUrl, ClientApiWrapper } } - private boolean addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrapper clientApiWrapper, String storageType) throws ClientApiException { + private boolean addJwtAsReplacerRuleToZap(Map storage, ClientApiWrapper clientApiWrapper) throws ClientApiException { boolean enabled = true; // "REQ_HEADER" means the header entry will be added to the requests if not // existing or replaced if already existing @@ -111,11 +107,10 @@ private boolean addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrappe // any URL String url = null; - LOG.info("Searching: {} for JWT and add JWT as replacer rule.", storageType); - Map localStorage = retrieveStorage(firefox, storageType); + LOG.info("Searching browser storage for JWT and add JWT as replacer rule."); - for (String key : localStorage.keySet()) { - String value = localStorage.get(key); + for (String key : storage.keySet()) { + String value = storage.get(key); if (jwtSupport.isJWT(value)) { replacement = "Bearer %s".formatted(value); clientApiWrapper.addReplacerRule(JWT_REPLACER_DESCRIPTION, enabled, matchtype, matchregex, matchstring, replacement, initiators, url); @@ -125,18 +120,4 @@ private boolean addJwtAsReplacerRuleToZap(FirefoxDriver firefox, ClientApiWrappe return false; } - private Map retrieveStorage(JavascriptExecutor jsExecutor, String storageType) { - String script = """ - let items = {}; - for (let i = 0; i < %s.length; i++) { - let key = %s.key(i); - items[key] = %s.getItem(key); - } - return items; - """.formatted(storageType, storageType, storageType); - - @SuppressWarnings("unchecked") - Map storage = (Map) jsExecutor.executeScript(script); - return storage; - } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java index 2c7c17ba10..f243def4d2 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginWebDriverFactory.java @@ -16,6 +16,7 @@ public class ZapScriptLoginWebDriverFactory { private static final Dimension DEFAULT_WEBDRIVER_RESOLUTION = new Dimension(1920, 1080); public FirefoxDriver createFirefoxWebdriver(ProxyInformation proxyInformation, boolean headless) { + FirefoxOptions options = new FirefoxOptions(); if (headless) { LOG.info("Using firefox in headless mode."); @@ -32,6 +33,7 @@ public FirefoxDriver createFirefoxWebdriver(ProxyInformation proxyInformation, b proxy.setSslProxy(proxyString); options.setProxy(proxy); } + LOG.info("Creating selenium firefox driver."); FirefoxDriver firefox = new FirefoxDriver(options); // Set the window size, some application need a windows size to render correctly // even in headless mode diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java index 3db3471467..909cc6ca18 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java @@ -8,12 +8,14 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.time.Duration; +import java.util.Map; import javax.script.Bindings; import javax.script.ScriptEngine; import javax.script.ScriptException; import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.support.ui.WebDriverWait; import org.slf4j.Logger; @@ -29,21 +31,57 @@ public class ZapWrapperGroovyScriptExecutor { private static final Logger LOG = LoggerFactory.getLogger(ZapWrapperGroovyScriptExecutor.class); - private static final long WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS = 30; + private static final int WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS = 30; - public void executeScript(File scriptFile, FirefoxDriver firefox, ZapScanContext scanContext) throws IOException, ScriptException { + private static final String LOCAL_STORAGE = "localStorage"; + private static final String SESSION_STORAGE = "sessionStorage"; + + private ZapScriptLoginWebDriverFactory webDriverFactory; + + private int webdriverTimeoutInSeconds; + + public ZapWrapperGroovyScriptExecutor() { + this(new ZapScriptLoginWebDriverFactory(), WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS); + } + + ZapWrapperGroovyScriptExecutor(ZapScriptLoginWebDriverFactory webDriverFactory, int webdriverTimeoutInSeconds) { + this.webDriverFactory = webDriverFactory; + this.webdriverTimeoutInSeconds = webdriverTimeoutInSeconds; + } + + public ScriptLoginResult executeScript(File scriptFile, ZapScanContext scanContext) { + + FirefoxDriver firefox = webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true); + WebDriverWait wait = new WebDriverWait(firefox, Duration.ofSeconds(webdriverTimeoutInSeconds)); - String script = Files.readString(scriptFile.toPath()); ScriptEngine scriptEngine = new GroovyScriptEngineFactory().getScriptEngine(); LOG.info("Create bindings for groovy script."); - Bindings bindings = createBindings(scanContext, scriptEngine, firefox); - - LOG.info("Execute groovy login script."); - scriptEngine.eval(script, bindings); + Bindings bindings = createBindings(scanContext, scriptEngine, firefox, wait); + + ScriptLoginResult loginResult = new ScriptLoginResult(); + try { + String script = Files.readString(scriptFile.toPath()); + LOG.info("Execute groovy login script."); + scriptEngine.eval(script, bindings); + + // load target URL to ensure the correct page is loaded in the browser + firefox.get(scanContext.getTargetUrlAsString()); + + LOG.info("Execution successful, perparing login result with session data."); + loginResult.setSessionCookies(firefox.manage().getCookies()); + loginResult.setSessionStorage(retrieveStorage(firefox, SESSION_STORAGE)); + loginResult.setLocalStorage(retrieveStorage(firefox, LOCAL_STORAGE)); + } catch (IOException | ScriptException e) { + LOG.error("An error happened while executing the script file.", e); + loginResult.setLoginFailed(true); + } finally { + firefox.quit(); + } + return loginResult; } - private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptEngine, FirefoxDriver firefox) { + private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptEngine, FirefoxDriver firefox, WebDriverWait wait) { // TODO 2024-11-21 jan: use templates structure from sechub webscan config SecHubWebScanConfiguration secHubWebScanConfiguration = scanContext.getSecHubWebScanConfiguration(); WebLoginConfiguration webLoginConfiguration = secHubWebScanConfiguration.getLogin().get(); @@ -66,8 +104,6 @@ private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptE String user = "DUMMY"; String password = "DUMMY"; - WebDriverWait wait = new WebDriverWait(firefox, Duration.ofSeconds(WEBDRIVER_TIMEOUT_PER_STEP_IN_SECONDS)); - Bindings bindings = scriptEngine.createBindings(); bindings.put(FIREFOX_WEBDRIVER_KEY, firefox); bindings.put(FIREFOX_WEBDRIVER_WAIT_KEY, wait); @@ -82,4 +118,19 @@ private Bindings createBindings(ZapScanContext scanContext, ScriptEngine scriptE return bindings; } + + private Map retrieveStorage(JavascriptExecutor jsExecutor, String storageType) { + String script = """ + let items = {}; + for (let i = 0; i < %s.length; i++) { + let key = %s.key(i); + items[key] = %s.getItem(key); + } + return items; + """.formatted(storageType, storageType, storageType); + + @SuppressWarnings("unchecked") + Map storage = (Map) jsExecutor.executeScript(script); + return storage; + } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java index d5b6a89917..be427514ad 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/util/TOTPGenerator.java @@ -41,7 +41,7 @@ public TOTPGenerator(String seed, int totpLength, TOTPHashAlgorithm hashAlgorith } /** - * This method generates a TOTP for the current times stamp in milliseconds. + * This method generates a TOTP for the current timestamp in milliseconds. * * @return totp currently valid */ @@ -50,7 +50,7 @@ public String now() { } /** - * This method generates a TOTP for a time stamp in milliseconds. + * This method generates a TOTP for a timestamp in milliseconds. * * @param seed * @param currentTimeMillis diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java similarity index 58% rename from sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java rename to sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java index 772a8961ea..39796f414d 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionGrabberTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.zapwrapper.scan.login; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -14,20 +14,16 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.openqa.selenium.Cookie; -import org.openqa.selenium.WebDriver.Options; -import org.openqa.selenium.firefox.FirefoxDriver; import org.zaproxy.clientapi.core.ApiResponse; import org.zaproxy.clientapi.core.ClientApiException; import com.mercedesbenz.sechub.zapwrapper.internal.scan.ClientApiWrapper; -class ZapScriptLoginSessionGrabberTest { +class ZapScriptLoginSessionConfiguratorTest { - private ZapScriptLoginSessionGrabber sessionGrabberToTest; + private ZapScriptLoginSessionConfigurator sessionConfiguratorToTest; private ClientApiWrapper clientApiWrapper; - private FirefoxDriver firefox; - private Options webDriverOptions; private JWTSupport jwtSupport; private ApiResponse zapApiResponse; @@ -38,8 +34,6 @@ class ZapScriptLoginSessionGrabberTest { @BeforeEach void beforeEach() { zapApiResponse = mock(); - firefox = mock(); - webDriverOptions = mock(); jwtSupport = mock(); clientApiWrapper = mock(ClientApiWrapper.class, new Answer() { @@ -50,7 +44,7 @@ public Object answer(InvocationOnMock invocation) throws Throwable { } }); - sessionGrabberToTest = new ZapScriptLoginSessionGrabber(jwtSupport); + sessionConfiguratorToTest = new ZapScriptLoginSessionConfigurator(jwtSupport); } @Test @@ -62,20 +56,16 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE Map storage = new HashMap<>(); storage.put("jwt", "1234"); - when(firefox.manage()).thenReturn(webDriverOptions); + ScriptLoginResult loginResult = new ScriptLoginResult(); + loginResult.setSessionCookies(cookies); + loginResult.setSessionStorage(storage); - when(webDriverOptions.getCookies()).thenReturn(cookies); - when(firefox.executeScript(anyString())).thenReturn(storage); when(jwtSupport.isJWT(storage.get("jwt"))).thenReturn(true); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); + sessionConfiguratorToTest.passSessionDataToZAP(loginResult, TARGET_URL, clientApiWrapper); /* test */ - verify(firefox, times(1)).manage(); - verify(webDriverOptions, times(1)).getCookies(); - verify(firefox, times(1)).executeScript(anyString()); - verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); verify(clientApiWrapper, times(1)).removeReplacerRule(any()); @@ -91,27 +81,22 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE @Test void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() throws ClientApiException { /* prepare */ - when(firefox.manage()).thenReturn(webDriverOptions); + Map storage = new HashMap<>(); + storage.put("jwt", "1234"); + ScriptLoginResult loginResult = new ScriptLoginResult(); + loginResult.setSessionStorage(storage); - when(webDriverOptions.getCookies()).thenReturn(Collections.emptySet()); - when(firefox.executeScript(anyString())).thenReturn(Collections.emptyMap()); when(jwtSupport.isJWT(anyString())).thenReturn(false); /* execute */ - sessionGrabberToTest.extractSessionAndPassToZAP(firefox, TARGET_URL, clientApiWrapper); + sessionConfiguratorToTest.passSessionDataToZAP(loginResult, TARGET_URL, clientApiWrapper); /* test */ - // both browser storages are checked now without JWT - verify(firefox, times(2)).executeScript(anyString()); // no JWT can be added verify(clientApiWrapper, never()).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); // no cookie can be added verify(clientApiWrapper, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); - // the other calls must be the same as on every execution without error - verify(firefox, times(1)).manage(); - verify(webDriverOptions, times(1)).getCookies(); - verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); verify(clientApiWrapper, times(1)).removeReplacerRule(any()); @@ -122,4 +107,45 @@ void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() thr verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } + @Test + void zap_available_clean_up_old_session_data_does_not_throw_an_exception() throws ClientApiException { + /* execute + test */ + assertDoesNotThrow(() -> sessionConfiguratorToTest.cleanUpOldSessionDataIfNecessary(TARGET_URL, clientApiWrapper)); + } + + @Test + void zap_not_available_removing_old_session_does_throw_an_exception() throws ClientApiException { + String errorMessage = "Connection refused"; + + ClientApiException apiException = new ClientApiException(errorMessage); + + when(clientApiWrapper.removeHTTPSession(any(), any())).thenThrow(apiException); + + /* execute + test */ + assertThrows(ClientApiException.class, () -> sessionConfiguratorToTest.cleanUpOldSessionDataIfNecessary(TARGET_URL, clientApiWrapper)); + } + + @Test + void zap_not_available_removing_old_session_token_does_throw_an_exception() throws ClientApiException { + String errorMessage = "Connection refused"; + + ClientApiException apiException = new ClientApiException(errorMessage); + + when(clientApiWrapper.removeHTTPSessionToken(any(), any())).thenThrow(apiException); + + /* execute + test */ + assertThrows(ClientApiException.class, () -> sessionConfiguratorToTest.cleanUpOldSessionDataIfNecessary(TARGET_URL, clientApiWrapper)); + } + + @Test + void zap_not_available_removing_old_jwt_replacer_rule_does_throw_an_exception() throws ClientApiException { + String errorMessage = "Connection refused"; + + ClientApiException apiException = new ClientApiException(errorMessage); + + when(clientApiWrapper.removeReplacerRule(any())).thenThrow(apiException); + + /* execute + test */ + assertThrows(ClientApiException.class, () -> sessionConfiguratorToTest.cleanUpOldSessionDataIfNecessary(TARGET_URL, clientApiWrapper)); + } } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java index bac27a65e4..84934feaba 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java @@ -5,17 +5,13 @@ import static org.mockito.Mockito.*; import java.io.File; -import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.Optional; -import javax.script.ScriptException; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.openqa.selenium.firefox.FirefoxDriver; import org.zaproxy.clientapi.core.ClientApiException; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; @@ -30,99 +26,88 @@ class ZapScriptLoginTest { private ZapScriptLogin scriptLoginToTest; - private ZapScriptLoginWebDriverFactory webDriverFactory = mock(); - private ZapWrapperGroovyScriptExecutor groovyScriptExecutor = mock(); - private ZapScriptLoginSessionGrabber sessionGrabber = mock(); + private ZapWrapperGroovyScriptExecutor groovyScriptExecutor; + private ZapScriptLoginSessionConfigurator sessionConfigurator; - private ClientApiWrapper clientApiWrapper = mock(); - private FirefoxDriver firefox = mock(); + private ClientApiWrapper clientApiWrapper; @BeforeEach void beforeEach() { - webDriverFactory = mock(); groovyScriptExecutor = mock(); - sessionGrabber = mock(); + sessionConfigurator = mock(); clientApiWrapper = mock(); - firefox = mock(); - scriptLoginToTest = new ZapScriptLogin(webDriverFactory, groovyScriptExecutor, sessionGrabber); + scriptLoginToTest = new ZapScriptLogin(groovyScriptExecutor, sessionConfigurator); } @Test void script_login_execution_is_perfomed_as_expected() throws Exception { /* prepare */ - + ScriptLoginResult loginResult = new ScriptLoginResult(); ZapScanContext scanContext = createValidZapScanContext(); - when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); - doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); + when(groovyScriptExecutor.executeScript(scanContext.getGroovyScriptLoginFile(), scanContext)).thenReturn(loginResult); + when(sessionConfigurator.passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ scriptLoginToTest.login(scanContext, clientApiWrapper); /* test */ - verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - verify(firefox, times(1)).quit(); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator, times(1)).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test - void script_can_not_be_read_results_in_firefox_closed_and_session_grabber_never_called() throws Exception { + void script_can_not_be_read_results_in_firefox_closed_and_session_configurator_never_called() throws Exception { /* prepare */ + ScriptLoginResult loginResult = new ScriptLoginResult(); + loginResult.setLoginFailed(true); ZapScanContext scanContext = createValidZapScanContext(); - when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); - doThrow(IOException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); + when(groovyScriptExecutor.executeScript(scanContext.getGroovyScriptLoginFile(), scanContext)).thenReturn(loginResult); + when(sessionConfigurator.passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - verify(firefox, times(1)).quit(); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator, never()).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test - void script_login_execution_fails_results_in_firefox_closed_and_session_grabber_never_called() throws Exception { + void script_login_execution_fails_results_in_firefox_closed_and_session_configurator_never_called() throws Exception { /* prepare */ + ScriptLoginResult loginResult = new ScriptLoginResult(); + loginResult.setLoginFailed(true); ZapScanContext scanContext = createValidZapScanContext(); - when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); - doThrow(ScriptException.class).when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - when(sessionGrabber.extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); + when(groovyScriptExecutor.executeScript(scanContext.getGroovyScriptLoginFile(), scanContext)).thenReturn(loginResult); + when(sessionConfigurator.passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper)).thenReturn(AUTH_SESSION); /* execute */ assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, never()).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - verify(firefox, times(1)).quit(); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator, never()).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test - void session_grabbing_fails_results_in_firefox_closed() throws Exception { + void session_configurator_fails_results_in_excpetion_thrown() throws Exception { /* prepare */ + ScriptLoginResult loginResult = new ScriptLoginResult(); ZapScanContext scanContext = createValidZapScanContext(); - when(webDriverFactory.createFirefoxWebdriver(scanContext.getProxyInformation(), true)).thenReturn(firefox); - doNothing().when(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - doThrow(ClientApiException.class).when(sessionGrabber).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); + when(groovyScriptExecutor.executeScript(scanContext.getGroovyScriptLoginFile(), scanContext)).thenReturn(loginResult); + doThrow(ClientApiException.class).when(sessionConfigurator).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); /* execute */ assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(webDriverFactory, times(1)).createFirefoxWebdriver(scanContext.getProxyInformation(), true); - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), firefox, scanContext); - verify(sessionGrabber, times(1)).extractSessionAndPassToZAP(firefox, scanContext.getTargetUrlAsString(), clientApiWrapper); - verify(firefox, times(1)).quit(); + verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator, times(1)).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } private ZapScanContext createValidZapScanContext() throws MalformedURLException, URISyntaxException { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java index 07f36e36a9..74a119be5c 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutorTest.java @@ -2,17 +2,19 @@ package com.mercedesbenz.sechub.zapwrapper.scan.login; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.io.File; -import java.io.IOException; import java.net.URI; import java.net.URL; +import java.util.Collections; import java.util.Optional; -import javax.script.ScriptException; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.openqa.selenium.WebDriver.Options; +import org.openqa.selenium.firefox.FirefoxDriver; import com.mercedesbenz.sechub.commons.model.SecHubWebScanConfiguration; import com.mercedesbenz.sechub.commons.model.login.WebLoginConfiguration; @@ -22,18 +24,43 @@ class ZapWrapperGroovyScriptExecutorTest { private ZapWrapperGroovyScriptExecutor scriptExecutorToTest; + private ZapScriptLoginWebDriverFactory webDriverFactory; + private FirefoxDriver firefox; + private Options options; + @BeforeEach void beforeEach() { - scriptExecutorToTest = new ZapWrapperGroovyScriptExecutor(); + webDriverFactory = mock(); + firefox = mock(); + options = mock(); + + scriptExecutorToTest = new ZapWrapperGroovyScriptExecutor(webDriverFactory, 0); + + when(webDriverFactory.createFirefoxWebdriver(any(), anyBoolean())).thenReturn(firefox); + when(firefox.manage()).thenReturn(options); + when(options.getCookies()).thenReturn(Collections.emptySet()); } @Test - void throws_io_exception_when_script_cannot_be_read() { + void throws_io_exception_when_script_cannot_be_read() throws Exception { /* prepare */ File scriptFile = new File("not-existing.groovy"); - /* execute + test */ - assertThrows(IOException.class, () -> scriptExecutorToTest.executeScript(scriptFile, null, null)); + SecHubWebScanConfiguration webScanConfig = new SecHubWebScanConfiguration(); + webScanConfig.setUrl(URI.create("http://example.com")); + + WebLoginConfiguration login = new WebLoginConfiguration(); + login.setUrl(new URL("http://example.com/login")); + webScanConfig.setLogin(Optional.of(login)); + + ZapScanContext zapScanContext = ZapScanContext.builder().setSecHubWebScanConfiguration(webScanConfig).setTargetUrl(webScanConfig.getUrl().toURL()) + .build(); + + /* execute */ + ScriptLoginResult loginResult = scriptExecutorToTest.executeScript(scriptFile, zapScanContext); + + /* test */ + assertTrue(loginResult.isLoginFailed()); } @Test @@ -51,8 +78,11 @@ void throws_script_exception_when_script_contains_errors() throws Exception { ZapScanContext zapScanContext = ZapScanContext.builder().setSecHubWebScanConfiguration(webScanConfig).setTargetUrl(webScanConfig.getUrl().toURL()) .build(); - /* execute + test */ - assertThrows(ScriptException.class, () -> scriptExecutorToTest.executeScript(scriptFile, null, zapScanContext)); + /* execute */ + ScriptLoginResult loginResult = scriptExecutorToTest.executeScript(scriptFile, zapScanContext); + + /* test */ + assertTrue(loginResult.isLoginFailed()); } @Test @@ -70,8 +100,11 @@ void valid_script_is_executed_as_expected() throws Exception { ZapScanContext zapScanContext = ZapScanContext.builder().setSecHubWebScanConfiguration(webScanConfig).setTargetUrl(webScanConfig.getUrl().toURL()) .build(); - /* execute + test */ - assertDoesNotThrow(() -> scriptExecutorToTest.executeScript(scriptFile, null, zapScanContext)); + /* execute */ + ScriptLoginResult loginResult = scriptExecutorToTest.executeScript(scriptFile, zapScanContext); + + /* test */ + assertFalse(loginResult.isLoginFailed()); } } From b05e13b3b7a2c4bfa1de9e96e2b576a67433675b Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Tue, 26 Nov 2024 09:08:19 +0100 Subject: [PATCH 12/13] Remove not necessary call and add documentation #3622 --- sechub-wrapper-owasp-zap/README.adoc | 3 +++ .../zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sechub-wrapper-owasp-zap/README.adoc b/sechub-wrapper-owasp-zap/README.adoc index 15dbaf0ce2..dd4908d2e2 100644 --- a/sechub-wrapper-owasp-zap/README.adoc +++ b/sechub-wrapper-owasp-zap/README.adoc @@ -224,6 +224,9 @@ The script can also be created completely without using anything of the pre-defi The `TOTPGenerator` is an easy to use implementation of TOTP for two-factor-authentication if necessary. Using `totpGenerator.now()` returns the currently valid TOTP. To make use of the script authentication the wrapper application expects a SecHub configuration json for the scan, which contains a template data definition and optionally a TOTP configuration. See web scan example configurations for details. + +WARNING: **The script should always ensure that the target URL is loaded in the browser at the end after the authentication because the caller needs to access the session data.** + The following example contains all available bindings, even if they are unused in the script below: [source,groovy] diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java index 909cc6ca18..cd89f50717 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java @@ -65,9 +65,6 @@ public ScriptLoginResult executeScript(File scriptFile, ZapScanContext scanConte LOG.info("Execute groovy login script."); scriptEngine.eval(script, bindings); - // load target URL to ensure the correct page is loaded in the browser - firefox.get(scanContext.getTargetUrlAsString()); - LOG.info("Execution successful, perparing login result with session data."); loginResult.setSessionCookies(firefox.manage().getCookies()); loginResult.setSessionStorage(retrieveStorage(firefox, SESSION_STORAGE)); From 024e09e33eda8e045d418a4e799fed30c7123b22 Mon Sep 17 00:00:00 2001 From: Jan Winz Date: Wed, 27 Nov 2024 10:37:27 +0100 Subject: [PATCH 13/13] PR Review suggestions #3622 --- .../zapwrapper/scan/login/JWTSupport.java | 11 +- .../login/ZapWrapperGroovyScriptExecutor.java | 2 +- .../config/ZapScanContextFactoryTest.java | 26 ++--- .../zapwrapper/scan/ZapScannerTest.java | 110 +++++++++--------- ...ZapScriptLoginSessionConfiguratorTest.java | 34 +++--- .../scan/login/ZapScriptLoginTest.java | 12 +- 6 files changed, 100 insertions(+), 95 deletions(-) diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java index a35d298f4a..b144f45609 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/JWTSupport.java @@ -3,18 +3,19 @@ import java.util.regex.Pattern; -public class JWTSupport { +class JWTSupport { private static final Pattern JWT_PATTERN = Pattern.compile("^[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_.+/=]*$"); /** * Performs some tests to see if the given value is a JWT. * - * @param value + * @param value a string which could represent a JWT token (look at + * https://jwt.io/ for detailed description about JWT content) * @return true if all tests pass and the value is a JWT, * false otherwise. */ - public boolean isJWT(String value) { + boolean isJWT(String value) { if (value == null) { return false; } @@ -22,6 +23,10 @@ public boolean isJWT(String value) { return false; } String[] split = value.split("\\."); + // Simple way to check it is a JWT: When looking at https://jwt.io/ we can see, + // that every JWT has the structure "eyJ${someData}.eyJ${OtherData}" so we use + // this to identify JWT. Since this is only used for data extracted from HTTP + // sessions the test should be sufficient. return split[0].startsWith("eyJ") && split[1].startsWith("eyJ"); } } diff --git a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java index cd89f50717..3eb49de147 100644 --- a/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java +++ b/sechub-wrapper-owasp-zap/src/main/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapWrapperGroovyScriptExecutor.java @@ -65,7 +65,7 @@ public ScriptLoginResult executeScript(File scriptFile, ZapScanContext scanConte LOG.info("Execute groovy login script."); scriptEngine.eval(script, bindings); - LOG.info("Execution successful, perparing login result with session data."); + LOG.info("Execution successful, preparing login result with session data."); loginResult.setSessionCookies(firefox.manage().getCookies()); loginResult.setSessionStorage(retrieveStorage(firefox, SESSION_STORAGE)); loginResult.setLocalStorage(retrieveStorage(firefox, LOCAL_STORAGE)); diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java index a5f4ef3f30..cd1701f589 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/config/ZapScanContextFactoryTest.java @@ -159,15 +159,15 @@ void result_contains_server_config_with_arguments_from_environment_when_command_ ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsInt(ZAP_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(ZAP_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(ZAP_API_KEY_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(PROXY_REALM_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(PROXY_USERNAME_ENV_VARIABLE_NAME); - verify(envVariableReader, times(1)).readAsString(PROXY_PASSWORD_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(PROXY_HOST_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsInt(PROXY_PORT_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(PROXY_REALM_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(PROXY_USERNAME_ENV_VARIABLE_NAME); + verify(envVariableReader).readAsString(PROXY_PASSWORD_ENV_VARIABLE_NAME); ZapServerConfiguration serverConfig = result.getServerConfig(); assertNotNull(serverConfig); @@ -330,7 +330,7 @@ void fullruleset_returned_by_provider_is_in_result() { ZapFullRuleset fullRuleset = result.getFullRuleset(); /* test */ - verify(ruleProvider, times(1)).fetchFullRuleset(any()); + verify(ruleProvider).fetchFullRuleset(any()); assertNotNull(fullRuleset); assertNotNull(fullRuleset.getRules()); assertEquals("https://www.zaproxy.org/docs/alerts/", fullRuleset.getOrigin()); @@ -349,7 +349,7 @@ void rules_to_deactivate_returned_by_provider_is_inside_result() { DeactivatedRuleReferences deactivatedRuleReferences = result.getDeactivatedRuleReferences(); /* test */ - verify(ruleProvider, times(1)).fetchDeactivatedRuleReferences(any()); + verify(ruleProvider).fetchDeactivatedRuleReferences(any()); assertNotNull(deactivatedRuleReferences); assertNotNull(deactivatedRuleReferences.getDeactivatedRuleReferences()); assertEquals(2, deactivatedRuleReferences.getDeactivatedRuleReferences().size()); @@ -419,7 +419,7 @@ void rules_to_deactivate_returned_by_command_line_is_null_environment_varibale_r factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); + verify(envVariableReader).readAsString(ZAP_DEACTIVATED_RULE_REFERENCES); } @Test @@ -573,7 +573,7 @@ void no_template_data_results_in_no_template_data_set() { ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); + verify(envVariableReader).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); assertNull(result.getGroovyScriptLoginFile()); } @@ -609,7 +609,7 @@ void cmd_param_not_set_results_in_environment_variable_reader_being_called_as_fa ZapScanContext result = factoryToTest.create(settings); /* test */ - verify(envVariableReader, times(1)).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); + verify(envVariableReader).readAsString(ZAP_GROOVY_LOGIN_SCRIPT_FILE); assertEquals(groovyScriptFile, result.getGroovyScriptLoginFile().getName()); } diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java index e4260a0486..03b48e2667 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/ZapScannerTest.java @@ -117,11 +117,11 @@ void setup_standard_configuration_results_in_expected_calls() throws ClientApiEx scannerToTest.setupStandardConfiguration(); /* test */ - verify(clientApiWrapper, times(1)).createNewSession(scanContext.getContextName(), true); - verify(clientApiWrapper, times(1)).setMaximumAlertsForEachRuleToUnlimited(); - verify(clientApiWrapper, times(1)).enableAllPassiveScannerRules(); - verify(clientApiWrapper, times(1)).enableAllActiveScannerRulesForDefaultPolicy(); - verify(clientApiWrapper, times(1)).setAjaxSpiderBrowserId(BROWSER_ID); + verify(clientApiWrapper).createNewSession(scanContext.getContextName(), true); + verify(clientApiWrapper).setMaximumAlertsForEachRuleToUnlimited(); + verify(clientApiWrapper).enableAllPassiveScannerRules(); + verify(clientApiWrapper).enableAllActiveScannerRulesForDefaultPolicy(); + verify(clientApiWrapper).setAjaxSpiderBrowserId(BROWSER_ID); } @Test @@ -161,7 +161,7 @@ void deactivate_rules_results_in_rules_are_deactivated() throws ClientApiExcepti scannerToTest.deactivateRules(ruleSet, deactivatedReferences); /* test */ - verify(clientApiWrapper, times(1)).disablePassiveScannerRule(any()); + verify(clientApiWrapper).disablePassiveScannerRule(any()); verify(clientApiWrapper, times(2)).disableActiveScannerRuleForDefaultPolicy(any()); } @@ -175,7 +175,7 @@ void setup_addtional_proxy_information_with_proxy_information_null_results_in_pr scannerToTest.setupAdditonalProxyConfiguration(null); /* test */ - verify(clientApiWrapper, times(1)).setHttpProxyEnabled(false); + verify(clientApiWrapper).setHttpProxyEnabled(false); } @Test @@ -193,9 +193,9 @@ void setup_addtional_proxy_information_results_in_proxy_enabled() throws ClientA scannerToTest.setupAdditonalProxyConfiguration(proxyInformation); /* test */ - verify(clientApiWrapper, times(1)).configureHttpProxy(proxyInformation); - verify(clientApiWrapper, times(1)).setHttpProxyEnabled(true); - verify(clientApiWrapper, times(1)).setHttpProxyAuthEnabled(false); + verify(clientApiWrapper).configureHttpProxy(proxyInformation); + verify(clientApiWrapper).setHttpProxyEnabled(true); + verify(clientApiWrapper).setHttpProxyAuthEnabled(false); } @Test @@ -210,7 +210,7 @@ void create_context_results_in_expected_calls() throws ClientApiException { /* test */ assertEquals(expectedContextId, contextId); verify(scanContext, times(2)).getContextName(); - verify(clientApiWrapper, times(1)).createNewContext(CONTEXT_NAME); + verify(clientApiWrapper).createNewContext(CONTEXT_NAME); } @Test @@ -318,8 +318,8 @@ void add_replacer_rules_for_headers_with_data_section_results_add_replacer_rule_ scannerToTest.addReplacerRulesForHeaders(); /* test */ - verify(clientApiWrapper, times(1)).addReplacerRule("Key", true, "REQ_HEADER", false, "Key", "header-token", null, null); - verify(clientApiWrapper, times(1)).addReplacerRule("Other", true, "REQ_HEADER", false, "Other", "token", null, null); + verify(clientApiWrapper).addReplacerRule("Key", true, "REQ_HEADER", false, "Key", "header-token", null, null); + verify(clientApiWrapper).addReplacerRule("Other", true, "REQ_HEADER", false, "Other", "token", null, null); } @ParameterizedTest @@ -397,7 +397,7 @@ void import_openapi_file_api_support_is_called_once(String sechubConfigFile) thr scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), anyInt()); + verify(clientApiWrapper).importOpenApiFile(any(), any(), anyInt()); } @ParameterizedTest @@ -417,7 +417,7 @@ void import_openapi_defintion_from_url_api_support_is_called_once(String sechubC /* test */ verify(clientApiWrapper, never()).importOpenApiFile(any(), any(), anyInt()); - verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), anyInt()); + verify(clientApiWrapper).importOpenApiDefintionFromUrl(any(), any(), anyInt()); } @ParameterizedTest @@ -440,8 +440,8 @@ void import_openapi_from_file_and_from_url_api_support_is_called_once(String sec scannerToTest.loadApiDefinitions(contextId); /* test */ - verify(clientApiWrapper, times(1)).importOpenApiFile(any(), any(), anyInt()); - verify(clientApiWrapper, times(1)).importOpenApiDefintionFromUrl(any(), any(), anyInt()); + verify(clientApiWrapper).importOpenApiFile(any(), any(), anyInt()); + verify(clientApiWrapper).importOpenApiDefintionFromUrl(any(), any(), anyInt()); } @Test @@ -516,7 +516,7 @@ void import_client_certificate_file_api_support_is_called_once() throws ClientAp scannerToTest.importClientCertificate(); /* test */ - verify(clientApiWrapper, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiWrapper).importPkcs12ClientCertificate(any(), any()); } @Test @@ -549,7 +549,7 @@ void import_client_certificate_file_but_without_password_api_support_is_called_o scannerToTest.importClientCertificate(); /* test */ - verify(clientApiWrapper, times(1)).importPkcs12ClientCertificate(any(), any()); + verify(clientApiWrapper).importPkcs12ClientCertificate(any(), any()); } @ParameterizedTest @@ -603,12 +603,12 @@ void configure_login_inside_zap_using_basic_auth_results_in_expected_calls() thr verify(scanContext, times(2)).getTargetUrl(); - verify(clientApiWrapper, times(1)).setAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); - verify(clientApiWrapper, times(1)).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); - verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); - verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(clientApiWrapper, times(1)).setForcedUser(contextId, userId); - verify(clientApiWrapper, times(1)).setForcedUserModeEnabled(true); + verify(clientApiWrapper).setAuthenticationMethod(eq(contextId), eq(zapAuthenticationMethod), any()); + verify(clientApiWrapper).setSessionManagementMethod(eq(contextId), eq(zapSessionManagementMethod), any()); + verify(clientApiWrapper).createNewUser(contextId, userName); + verify(clientApiWrapper).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiWrapper).setForcedUser(contextId, userId); + verify(clientApiWrapper).setForcedUserModeEnabled(true); } @Test @@ -645,7 +645,7 @@ void configure_login_inside_zap_using_script_auth_without_script_file_results_in /* test */ assertNull(userInformation); verify(scriptLogin, never()).login(scanContext, clientApiWrapper); - verify(scanContext, times(1)).getGroovyScriptLoginFile(); + verify(scanContext).getGroovyScriptLoginFile(); } @Test @@ -682,15 +682,15 @@ void configure_login_inside_zap_using_script_auth_with_existing_script_file_resu assertEquals(userName, userInformation.userName()); assertEquals(userId, userInformation.zapuserId()); - verify(scriptLogin, times(1)).login(scanContext, clientApiWrapper); - verify(scanContext, times(1)).getGroovyScriptLoginFile(); + verify(scriptLogin).login(scanContext, clientApiWrapper); + verify(scanContext).getGroovyScriptLoginFile(); - verify(clientApiWrapper, times(1)).setManualAuthenticationMethod(contextId); - verify(clientApiWrapper, times(1)).setCookieBasedSessionManagementMethod(contextId); - verify(clientApiWrapper, times(1)).createNewUser(contextId, userName); - verify(clientApiWrapper, times(1)).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); - verify(clientApiWrapper, times(1)).setForcedUser(contextId, userId); - verify(clientApiWrapper, times(1)).setForcedUserModeEnabled(true); + verify(clientApiWrapper).setManualAuthenticationMethod(contextId); + verify(clientApiWrapper).setCookieBasedSessionManagementMethod(contextId); + verify(clientApiWrapper).createNewUser(contextId, userName); + verify(clientApiWrapper).configureAuthenticationCredentials(eq(contextId), eq(userId), any()); + verify(clientApiWrapper).setForcedUser(contextId, userId); + verify(clientApiWrapper).setForcedUserModeEnabled(true); } @Test @@ -706,7 +706,7 @@ void generate_report_calls_api_support_once() throws ClientApiException { scannerToTest.generateZapReport(); /* test */ - verify(clientApiWrapper, times(1)).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), + verify(clientApiWrapper).generateReport(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any()); } @@ -721,8 +721,8 @@ void cleanup_after_scan() throws ClientApiException { scannerToTest.cleanUp(); /* test */ - verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); + verify(clientApiWrapper).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(scriptLogin).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @ParameterizedTest @@ -739,9 +739,9 @@ void cleanup_after_scan_without_onylForUrls_headers_set_cleans_up_all_replacer_r /* test */ int times = sechubWebScanConfig.getHeaders().get().size(); - verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiWrapper).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); verify(clientApiWrapper, times(times + 1)).removeReplacerRule(any()); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); + verify(scriptLogin).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @ParameterizedTest @@ -764,9 +764,9 @@ void cleanup_after_scan_with_onylForUrls_headers_set_cleans_up_all_replacer_rule times += header.getOnlyForUrls().get().size() - 1; } } - verify(clientApiWrapper, times(1)).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); + verify(clientApiWrapper).removeReplacerRule(ZapScanner.X_SECHUB_DAST_HEADER_NAME); verify(clientApiWrapper, times(times + 1)).removeReplacerRule(any()); - verify(scriptLogin, times(1)).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); + verify(scriptLogin).cleanUpScriptLoginData(scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test @@ -786,7 +786,7 @@ void wait_for_ajaxSpider_scan_is_cancelled_results_in_exception_with_dedicated_e /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(clientApiWrapper, times(1)).stopAjaxSpider(); + verify(clientApiWrapper).stopAjaxSpider(); } @Test @@ -802,7 +802,7 @@ void wait_for_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApi /* test */ verify(clientApiWrapper, times(2)).getAjaxSpiderStatus(); - verify(clientApiWrapper, times(1)).stopAjaxSpider(); + verify(clientApiWrapper).stopAjaxSpider(); } @Test @@ -822,7 +822,7 @@ void wait_for_spider_scan_is_cancelled_results_in_exception_with_dedicated_exit_ /* test */ assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); - verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); + verify(clientApiWrapper).stopSpiderScan(scanId); } @Test @@ -858,7 +858,7 @@ void wait_for_passiveScan_scan_is_ended_results_in_expected_calls() throws Clien scannerToTest.runAndWaitForPassiveScan(); /* test */ - verify(clientApiWrapper, times(1)).getNumberOfPassiveScannerRecordsToScan(); + verify(clientApiWrapper).getNumberOfPassiveScannerRecordsToScan(); } @Test @@ -880,7 +880,7 @@ void wait_for_activeScan_scan_is_cancelled_results_in_exception_with_dedicated_e assertEquals(ZapWrapperExitCode.SCAN_JOB_CANCELLED, exception.getExitCode()); verify(zapPDSEventHandler, times(2)).isScanCancelled(); verify(clientApiWrapper, never()).getActiveScannerStatusForScan(scanId); - verify(clientApiWrapper, times(1)).stopActiveScan(scanId); + verify(clientApiWrapper).stopActiveScan(scanId); } @Test @@ -897,7 +897,7 @@ void wait_for_activeScan_scan_is_ended_results_in_expected_calls() throws Client /* test */ verify(clientApiWrapper, atLeast(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiWrapper, times(1)).stopActiveScan(scanId); + verify(clientApiWrapper).stopActiveScan(scanId); } @Test @@ -913,7 +913,7 @@ void run_ajaxSpider_scan_ended_results_in_expected_calls() throws ClientApiExcep /* test */ verify(clientApiWrapper, times(2)).getAjaxSpiderStatus(); - verify(clientApiWrapper, times(1)).stopAjaxSpider(); + verify(clientApiWrapper).stopAjaxSpider(); } @Test @@ -934,11 +934,11 @@ void run_spider_scan_ended_results_in_expected_calls() throws ClientApiException scannerToTest.runAndWaitForSpider(); /* test */ - verify(scanContext, times(1)).getZapProductMessageHelper(); + verify(scanContext).getZapProductMessageHelper(); verify(clientApiWrapper, times(2)).getSpiderStatusForScan(scanId); - verify(clientApiWrapper, times(1)).stopSpiderScan(scanId); - verify(clientApiWrapper, times(1)).logFullSpiderResults(scanId); - verify(clientApiWrapper, times(1)).startSpiderScan(any(), any(), anyBoolean(), any(), anyBoolean()); + verify(clientApiWrapper).stopSpiderScan(scanId); + verify(clientApiWrapper).logFullSpiderResults(scanId); + verify(clientApiWrapper).startSpiderScan(any(), any(), anyBoolean(), any(), anyBoolean()); } @Test @@ -956,9 +956,9 @@ void run_activeScan_scan_is_ended_results_in_expected_calls() throws ClientApiEx scannerToTest.runAndWaitActiveScan(scanId); /* test */ - verify(clientApiWrapper, times(1)).getActiveScannerStatusForScan(scanId); - verify(clientApiWrapper, times(1)).stopActiveScan(scanId); - verify(clientApiWrapper, times(1)).startActiveScan(any(), anyBoolean(), anyBoolean(), any(), any(), any(), anyInt()); + verify(clientApiWrapper).getActiveScannerStatusForScan(scanId); + verify(clientApiWrapper).stopActiveScan(scanId); + verify(clientApiWrapper).startActiveScan(any(), anyBoolean(), anyBoolean(), any(), any(), any(), anyInt()); } static Stream headerPartWithoutOnlyForUrlsTestNamedArguments() { diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java index 39796f414d..6b3ba3d8e3 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginSessionConfiguratorTest.java @@ -66,16 +66,16 @@ void one_cookie_and_one_jwt_results_in_each_mock_called_once() throws ClientApiE sessionConfiguratorToTest.passSessionDataToZAP(loginResult, TARGET_URL, clientApiWrapper); /* test */ - verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).removeReplacerRule(any()); - verify(clientApiWrapper, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); - verify(clientApiWrapper, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); - - verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(clientApiWrapper).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper).removeReplacerRule(any()); + verify(clientApiWrapper).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).setHTTPSessionTokenValue(eq(TARGET_URL), any(), eq(cookie.getName()), eq(cookie.getValue())); + verify(clientApiWrapper).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).addReplacerRule(any(), anyBoolean(), any(), anyBoolean(), any(), any(), any(), any()); + + verify(clientApiWrapper).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } @Test @@ -97,14 +97,14 @@ void no_cookie_and_no_jwt_results_clienapiwrapper_not_adding_replacer_rule() thr // no cookie can be added verify(clientApiWrapper, never()).setHTTPSessionTokenValue(eq(TARGET_URL), any(), any(), any()); - verify(clientApiWrapper, times(1)).removeHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).removeHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).removeReplacerRule(any()); - verify(clientApiWrapper, times(1)).addHTTPSessionToken(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).createEmptyHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).setActiveHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).removeHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).removeHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper).removeReplacerRule(any()); + verify(clientApiWrapper).addHTTPSessionToken(eq(TARGET_URL), any()); + verify(clientApiWrapper).createEmptyHTTPSession(eq(TARGET_URL), any()); + verify(clientApiWrapper).setActiveHTTPSession(eq(TARGET_URL), any()); - verify(clientApiWrapper, times(1)).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); + verify(clientApiWrapper).accessUrlViaZap(TARGET_URL, FOLLOW_REDIRECTS); } @Test diff --git a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java index 84934feaba..0cc45dbc3f 100644 --- a/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java +++ b/sechub-wrapper-owasp-zap/src/test/java/com/mercedesbenz/sechub/zapwrapper/scan/login/ZapScriptLoginTest.java @@ -53,8 +53,8 @@ void script_login_execution_is_perfomed_as_expected() throws Exception { scriptLoginToTest.login(scanContext, clientApiWrapper); /* test */ - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); - verify(sessionConfigurator, times(1)).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); + verify(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @Test @@ -71,7 +71,7 @@ void script_can_not_be_read_results_in_firefox_closed_and_session_configurator_n assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); verify(sessionConfigurator, never()).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @@ -89,7 +89,7 @@ void script_login_execution_fails_results_in_firefox_closed_and_session_configur assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); verify(sessionConfigurator, never()).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } @@ -106,8 +106,8 @@ void session_configurator_fails_results_in_excpetion_thrown() throws Exception { assertThrows(ZapWrapperRuntimeException.class, () -> scriptLoginToTest.login(scanContext, clientApiWrapper)); /* test */ - verify(groovyScriptExecutor, times(1)).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); - verify(sessionConfigurator, times(1)).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); + verify(groovyScriptExecutor).executeScript(scanContext.getGroovyScriptLoginFile(), scanContext); + verify(sessionConfigurator).passSessionDataToZAP(loginResult, scanContext.getTargetUrlAsString(), clientApiWrapper); } private ZapScanContext createValidZapScanContext() throws MalformedURLException, URISyntaxException {