From 563e16c30ff25fb6d9e2a6f4c44edf65c8a6bd92 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 15:16:05 +0100 Subject: [PATCH 01/25] Use Lombok to Access Redonly Property Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 74a0b07037..e457390f36 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -57,12 +57,9 @@ public String getFindingUploadUrl() { return findingUploadUrl; } + @Getter final boolean readOnly; - public boolean isReadOnly() { - return readOnly; - } - public boolean isReadAndWrite() { return !readOnly; } From d3e00b47057c130f1eb06e77483aca226c0869b9 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 15:16:29 +0100 Subject: [PATCH 02/25] Improves GRammar of Exception Messages Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index e457390f36..70d1bbe313 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -45,14 +45,14 @@ public class PersistenceProviderConfig { public String getRawResultUploadUrl() { if (isReadOnly()) { - throw new DefectDojoPersistenceException("Cannot Access RawResult Upload URL as the hook is run is ReadOnly mode."); + throw new DefectDojoPersistenceException("Cannot access the RawResult Upload URL because the hook is executed in ReadOnly mode!"); } return rawResultUploadUrl; } public String getFindingUploadUrl() { if (isReadOnly()) { - throw new DefectDojoPersistenceException("Cannot Access Finding Upload URL as the hook is run is ReadOnly mode."); + throw new DefectDojoPersistenceException("Cannot access the Finding Upload URL because the hook is executed in ReadOnly mode!"); } return findingUploadUrl; } From decfdd37224b01a1f9fb31e67b4181ad75c2026e Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 15:18:11 +0100 Subject: [PATCH 03/25] Move Property to top of Class to the Others Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 70d1bbe313..0d130f101a 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -32,6 +32,8 @@ public class PersistenceProviderConfig { // has to be assumed for DefectDojo. It defaults to the Time Zone of the system clock @Getter ZoneId defectDojoTimezoneId = ZoneId.systemDefault(); + @Getter + final boolean readOnly; // Download Urls @Getter @@ -57,9 +59,6 @@ public String getFindingUploadUrl() { return findingUploadUrl; } - @Getter - final boolean readOnly; - public boolean isReadAndWrite() { return !readOnly; } From 1600c8c3cab8bf2a233f921a0ef9340e2e6a8655 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 15:31:54 +0100 Subject: [PATCH 04/25] Make PersistenceProviderConfig Final to Prevent Extension Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 0d130f101a..d62afb5ed1 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -18,7 +18,7 @@ * the Hook is run in ReadOnly or ReadAndWrite mode based on the number of args. */ @Slf4j -public class PersistenceProviderConfig { +public final class PersistenceProviderConfig { private final EnvConfig env = new EnvConfig(); private static final int RAW_RESULT_DOWNLOAD_ARG_POSITION = 0; From 511c19b66b2ccaab78c4c04728e723a4382e5477 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 15:33:28 +0100 Subject: [PATCH 05/25] Make Time Zone Final Becuase Never Changed Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index d62afb5ed1..245807cf8e 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -31,7 +31,7 @@ public final class PersistenceProviderConfig { // to guarantee consistent results when converting back and forth a time zone // has to be assumed for DefectDojo. It defaults to the Time Zone of the system clock @Getter - ZoneId defectDojoTimezoneId = ZoneId.systemDefault(); + final ZoneId defectDojoTimezoneId = ZoneId.systemDefault(); @Getter final boolean readOnly; From 7deb89bdb39aa2bfd6ffc4edb11c125155b48884 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 19:57:22 +0100 Subject: [PATCH 06/25] Move Cosntructor Before Methods As Expected Signed-off-by: Sven Strittmatter --- .../config/PersistenceProviderConfig.java | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 245807cf8e..e0f409a5e3 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -45,28 +45,6 @@ public final class PersistenceProviderConfig { final String rawResultUploadUrl; final String findingUploadUrl; - public String getRawResultUploadUrl() { - if (isReadOnly()) { - throw new DefectDojoPersistenceException("Cannot access the RawResult Upload URL because the hook is executed in ReadOnly mode!"); - } - return rawResultUploadUrl; - } - - public String getFindingUploadUrl() { - if (isReadOnly()) { - throw new DefectDojoPersistenceException("Cannot access the Finding Upload URL because the hook is executed in ReadOnly mode!"); - } - return findingUploadUrl; - } - - public boolean isReadAndWrite() { - return !readOnly; - } - - public boolean isInLowPrivilegedMode() { - return env.lowPrivilegedMode(); - } - public PersistenceProviderConfig(String[] args) { // Parse Hook Args passed via command line flags if (args == null) { @@ -91,4 +69,27 @@ public PersistenceProviderConfig(String[] args) { throw new DefectDojoPersistenceException("DefectDojo Hook received a unexpected number of command line flags. Expected exactly two (for ReadOnly Mode) or four (for ReadAndWrite mode)"); } } + + public String getRawResultUploadUrl() { + if (isReadOnly()) { + throw new DefectDojoPersistenceException("Cannot access the RawResult Upload URL because the hook is executed in ReadOnly mode!"); + } + return rawResultUploadUrl; + } + + public String getFindingUploadUrl() { + if (isReadOnly()) { + throw new DefectDojoPersistenceException("Cannot access the Finding Upload URL because the hook is executed in ReadOnly mode!"); + } + return findingUploadUrl; + } + + public boolean isReadAndWrite() { + return !readOnly; + } + + public boolean isInLowPrivilegedMode() { + return env.lowPrivilegedMode(); + } + } From 67b144b154bdd3b39faf8a31a5c262540d758d96 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 19:59:37 +0100 Subject: [PATCH 07/25] Generate toString Method for Better Debugging Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index e0f409a5e3..b4cafbb3bc 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -6,6 +6,7 @@ import io.securecodebox.persistence.exceptions.DefectDojoPersistenceException; import lombok.Getter; +import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,6 +19,7 @@ * the Hook is run in ReadOnly or ReadAndWrite mode based on the number of args. */ @Slf4j +@ToString public final class PersistenceProviderConfig { private final EnvConfig env = new EnvConfig(); @@ -91,5 +93,5 @@ public boolean isReadAndWrite() { public boolean isInLowPrivilegedMode() { return env.lowPrivilegedMode(); } - + } From 1dde6ac40e4ccda4909e9ac566943c4c7d2280c3 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 20:15:29 +0100 Subject: [PATCH 08/25] Use Generated Nullcheck to simplify Code Signed-off-by: Sven Strittmatter --- .../config/PersistenceProviderConfig.java | 15 ++++++++------- .../config/PersistenceProviderConfigTest.java | 12 ++++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index b4cafbb3bc..39f8707bfe 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -6,6 +6,7 @@ import io.securecodebox.persistence.exceptions.DefectDojoPersistenceException; import lombok.Getter; +import lombok.NonNull; import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; @@ -47,13 +48,14 @@ public final class PersistenceProviderConfig { final String rawResultUploadUrl; final String findingUploadUrl; - public PersistenceProviderConfig(String[] args) { - // Parse Hook Args passed via command line flags - if (args == null) { - throw new DefectDojoPersistenceException("Received `null` as command line flags. Expected exactly four (RawResult & Finding Up/Download Urls)"); - } else if (args.length == 2) { + /** + * Provider configuration + * + * @param args not {@code null}, hook args passed via command line flags + */ + public PersistenceProviderConfig(@NonNull final String[] args) { + if (args.length == 2) { this.readOnly = true; - this.rawResultDownloadUrl = args[RAW_RESULT_DOWNLOAD_ARG_POSITION]; this.findingDownloadUrl = args[FINDING_DOWNLOAD_ARG_POSITION]; // Not set for ReadOnly hooks @@ -61,7 +63,6 @@ public PersistenceProviderConfig(String[] args) { this.findingUploadUrl = null; } else if (args.length == 4) { this.readOnly = false; - this.rawResultDownloadUrl = args[RAW_RESULT_DOWNLOAD_ARG_POSITION]; this.findingDownloadUrl = args[FINDING_DOWNLOAD_ARG_POSITION]; this.rawResultUploadUrl = args[RAW_RESULT_UPLOAD_ARG_POSITION]; diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java new file mode 100644 index 0000000000..a722e1f2bb --- /dev/null +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java @@ -0,0 +1,12 @@ +package io.securecodebox.persistence.config; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class PersistenceProviderConfigTest { + @Test + void constructorRequiresNonNullArgument() { + assertThrows(NullPointerException.class, () -> new PersistenceProviderConfig(null)); + } +} From 294f303f5c414b647826b351dfb4be12c97b2266 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 20:45:40 +0100 Subject: [PATCH 09/25] Group Properties Together in Class Signed-off-by: Sven Strittmatter --- .../config/PersistenceProviderConfig.java | 19 +++++++---- .../config/PersistenceProviderConfigTest.java | 32 +++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 39f8707bfe..7cce522fda 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -22,14 +22,12 @@ @Slf4j @ToString public final class PersistenceProviderConfig { - private final EnvConfig env = new EnvConfig(); - private static final int RAW_RESULT_DOWNLOAD_ARG_POSITION = 0; private static final int FINDING_DOWNLOAD_ARG_POSITION = 1; - private static final int RAW_RESULT_UPLOAD_ARG_POSITION = 2; private static final int FINDING_UPLOAD_ARG_POSITION = 3; + private final EnvConfig env = new EnvConfig(); // DefectDojo does in contrast to secureCodeBox not pay attention to time zones // to guarantee consistent results when converting back and forth a time zone // has to be assumed for DefectDojo. It defaults to the Time Zone of the system clock @@ -38,14 +36,23 @@ public final class PersistenceProviderConfig { @Getter final boolean readOnly; - // Download Urls + /** + * URL where to download the raw result file + */ @Getter final String rawResultDownloadUrl; + /** + * URL where to download the parsed finding file + */ @Getter final String findingDownloadUrl; - - // Upload Urls + /** + * URL where to upload the raw result file, maybe {@code null} + */ final String rawResultUploadUrl; + /** + * URL where to upload the parsed finding file, maybe {@code null} + */ final String findingUploadUrl; /** diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java index a722e1f2bb..13bcbecd8f 100644 --- a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java @@ -1,7 +1,11 @@ package io.securecodebox.persistence.config; +import io.securecodebox.persistence.exceptions.DefectDojoPersistenceException; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.jupiter.api.Assertions.*; class PersistenceProviderConfigTest { @@ -9,4 +13,32 @@ class PersistenceProviderConfigTest { void constructorRequiresNonNullArgument() { assertThrows(NullPointerException.class, () -> new PersistenceProviderConfig(null)); } + + @Test + void constructorWithTwoArgsCreatesReadOnlyConfig() { + final var sut = new PersistenceProviderConfig(new String[]{"foo", "bar"}); + + assertAll( + () -> assertThat(sut.isReadOnly(), is(true)), + () -> assertThat(sut.isReadAndWrite(), is(false)), + () -> assertThat(sut.getRawResultDownloadUrl(), is("foo")), + () -> assertThat(sut.getFindingDownloadUrl(), is("bar")), + () -> assertThrows(DefectDojoPersistenceException.class, sut::getRawResultUploadUrl), + () -> assertThrows(DefectDojoPersistenceException.class, sut::getFindingUploadUrl) + ); + } + + @Test + void constructorWithFourArgsCreatesReadWriteConfig() { + final var sut = new PersistenceProviderConfig(new String[]{"foo", "bar", "baz", "snafu"}); + + assertAll( + () -> assertThat(sut.isReadOnly(), is(false)), + () -> assertThat(sut.isReadAndWrite(), is(true)), + () -> assertThat(sut.getRawResultDownloadUrl(), is("foo")), + () -> assertThat(sut.getFindingDownloadUrl(), is("bar")), + () -> assertThat(sut.getRawResultUploadUrl(), is("baz")), + () -> assertThat(sut.getFindingUploadUrl(), is("snafu")) + ); + } } From 87ee12223406a83f458253bf6aa7bb589dadbc0a Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 21:12:46 +0100 Subject: [PATCH 10/25] Make Inline Comment A Real JavaDoc to be Visible in Intellisense Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 7cce522fda..4afdae6749 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -28,9 +28,14 @@ public final class PersistenceProviderConfig { private static final int FINDING_UPLOAD_ARG_POSITION = 3; private final EnvConfig env = new EnvConfig(); - // DefectDojo does in contrast to secureCodeBox not pay attention to time zones - // to guarantee consistent results when converting back and forth a time zone - // has to be assumed for DefectDojo. It defaults to the Time Zone of the system clock + /** + * Assumed time zone of DefectDojo + *

+ * DefectDojo does in contrast to secureCodeBox not pay attention to time zones + * to guarantee consistent results when converting back and forth a time zone + * has to be assumed for DefectDojo. It defaults to the Time Zone of the system clock. + *

+ */ @Getter final ZoneId defectDojoTimezoneId = ZoneId.systemDefault(); @Getter From a0974d5a44d0dea5627af7e7e334190c124bd465 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 21:15:44 +0100 Subject: [PATCH 11/25] Docuemnt Unchecked Exception Condition Signed-off-by: Sven Strittmatter --- .../persistence/config/PersistenceProviderConfig.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index 4afdae6749..d29bd1079a 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -85,6 +85,9 @@ public PersistenceProviderConfig(@NonNull final String[] args) { } } + /** + * Throws {@link DefectDojoPersistenceException} if {@link #isReadOnly()} is {@code true} + */ public String getRawResultUploadUrl() { if (isReadOnly()) { throw new DefectDojoPersistenceException("Cannot access the RawResult Upload URL because the hook is executed in ReadOnly mode!"); @@ -92,6 +95,9 @@ public String getRawResultUploadUrl() { return rawResultUploadUrl; } + /** + * Throws {@link DefectDojoPersistenceException} if {@link #isReadOnly()} is {@code true} + */ public String getFindingUploadUrl() { if (isReadOnly()) { throw new DefectDojoPersistenceException("Cannot access the Finding Upload URL because the hook is executed in ReadOnly mode!"); From 6e1eaf004c78f98448fc0edc76f230d25934eb28 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Mon, 30 Dec 2024 21:31:27 +0100 Subject: [PATCH 12/25] Improve and Test Wrong Argument Length Check Signed-off-by: Sven Strittmatter --- .../config/PersistenceProviderConfig.java | 13 +++++++------ .../config/PersistenceProviderConfigTest.java | 10 ++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java index d29bd1079a..56a345d3ee 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/PersistenceProviderConfig.java @@ -9,8 +9,6 @@ import lombok.NonNull; import lombok.ToString; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.time.ZoneId; import java.util.List; @@ -26,6 +24,8 @@ public final class PersistenceProviderConfig { private static final int FINDING_DOWNLOAD_ARG_POSITION = 1; private static final int RAW_RESULT_UPLOAD_ARG_POSITION = 2; private static final int FINDING_UPLOAD_ARG_POSITION = 3; + public static final int NUMBER_OF_ARGS_READONLY = 2; + public static final int NUMBER_OF_ARGS_READWRITE = 4; private final EnvConfig env = new EnvConfig(); /** @@ -66,22 +66,23 @@ public final class PersistenceProviderConfig { * @param args not {@code null}, hook args passed via command line flags */ public PersistenceProviderConfig(@NonNull final String[] args) { - if (args.length == 2) { + if (args.length == NUMBER_OF_ARGS_READONLY) { this.readOnly = true; this.rawResultDownloadUrl = args[RAW_RESULT_DOWNLOAD_ARG_POSITION]; this.findingDownloadUrl = args[FINDING_DOWNLOAD_ARG_POSITION]; // Not set for ReadOnly hooks this.rawResultUploadUrl = null; this.findingUploadUrl = null; - } else if (args.length == 4) { + } else if (args.length == NUMBER_OF_ARGS_READWRITE) { this.readOnly = false; this.rawResultDownloadUrl = args[RAW_RESULT_DOWNLOAD_ARG_POSITION]; this.findingDownloadUrl = args[FINDING_DOWNLOAD_ARG_POSITION]; this.rawResultUploadUrl = args[RAW_RESULT_UPLOAD_ARG_POSITION]; this.findingUploadUrl = args[FINDING_UPLOAD_ARG_POSITION]; } else { - log.error("Received unexpected command line arguments: {}", List.of(args)); - throw new DefectDojoPersistenceException("DefectDojo Hook received a unexpected number of command line flags. Expected exactly two (for ReadOnly Mode) or four (for ReadAndWrite mode)"); + final var msg = "Unexpected number of arguments given %d! Expected are either %d or %d arguments in array!"; + throw new DefectDojoPersistenceException( + String.format(msg, args.length, NUMBER_OF_ARGS_READONLY, NUMBER_OF_ARGS_READWRITE)); } } diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java index 13bcbecd8f..29fb972296 100644 --- a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java @@ -41,4 +41,14 @@ void constructorWithFourArgsCreatesReadWriteConfig() { () -> assertThat(sut.getFindingUploadUrl(), is("snafu")) ); } + + @Test + void constructorThrowsExceptionForWrongArgumentLength() { + assertAll( + () -> assertThrows(DefectDojoPersistenceException.class, () -> new PersistenceProviderConfig(new String[0])), + () -> assertThrows(DefectDojoPersistenceException.class, () -> new PersistenceProviderConfig(new String[]{"foo"})), + () -> assertThrows(DefectDojoPersistenceException.class, () -> new PersistenceProviderConfig(new String[]{"foo", "bar", "baz"})), + () -> assertThrows(DefectDojoPersistenceException.class, () -> new PersistenceProviderConfig(new String[]{"foo", "bar", "baz", "snafu", "shtf"})) + ); + } } From dfbbfad5fb969658427dab440fa08bd77c067078 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 14:48:30 +0100 Subject: [PATCH 13/25] Document Constructors of Exception Signed-off-by: Sven Strittmatter --- .../exceptions/DefectDojoPersistenceException.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/exceptions/DefectDojoPersistenceException.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/exceptions/DefectDojoPersistenceException.java index 1a2c81346b..dedb3a2d25 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/exceptions/DefectDojoPersistenceException.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/exceptions/DefectDojoPersistenceException.java @@ -7,10 +7,21 @@ * The base error type of this hook */ public class DefectDojoPersistenceException extends RuntimeException { + /** + * Creates an exception with a message + * + * @param message must not be {@code null} ar empty. Should be formatted to be directly printed to STDERR. + */ public DefectDojoPersistenceException(String message) { - super(message); + this(message, null); } + /** + * Dedicated constructor + * + * @param message see {@link #DefectDojoPersistenceException(String} + * @param cause may be {@code null} if context where the exception occurred is unnecessary. + */ public DefectDojoPersistenceException(String message, Throwable cause) { super(message, cause); } From ee60cfa166f7b8785b874da8f42015f8d805b8a2 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 14:55:34 +0100 Subject: [PATCH 14/25] Show Helpfull Errormessage When K8s Env Vars Not Set Signed-off-by: Sven Strittmatter --- .../DefectDojoPersistenceProvider.java | 24 ++++++++++++++----- .../service/KubernetesService.java | 11 ++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java index 2e2648a40f..2205d06767 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java @@ -8,6 +8,7 @@ import io.securecodebox.persistence.defectdojo.model.Finding; import io.securecodebox.persistence.defectdojo.service.EndpointService; import io.securecodebox.persistence.defectdojo.service.FindingService; +import io.securecodebox.persistence.exceptions.DefectDojoPersistenceException; import io.securecodebox.persistence.mapping.DefectDojoFindingToSecureCodeBoxMapper; import io.securecodebox.persistence.models.Scan; import io.securecodebox.persistence.service.KubernetesService; @@ -20,16 +21,27 @@ @Slf4j public class DefectDojoPersistenceProvider { + private static final String HELP_HINT = "Use option -h or --help to get more details about the arguments."; + private static final int EXIT_CODE_OK = 0; + private static final int EXIT_CODE_ERROR = 1; private final S3Service s3Service = new S3Service(); private final KubernetesService kubernetesService = new KubernetesService(); public static void main(String[] args) { - try { - new DefectDojoPersistenceProvider().execute(args); - } catch (Exception e) { - log.error(e.getMessage(), e); - System.exit(1); - } + try { + new DefectDojoPersistenceProvider().execute(args); + System.exit(EXIT_CODE_OK); + } catch (final DefectDojoPersistenceException e) { + // We do not log stack traces on own errors because the message itself must be helpful enough to fix it! + log.error(e.getMessage()); + log.error(HELP_HINT); + System.exit(EXIT_CODE_ERROR); + } catch (final Exception e) { + // Also log the stack trace as context for unforeseen errors. + log.error(e.getMessage(), e); + log.error(HELP_HINT); + System.exit(EXIT_CODE_ERROR); + } } private void execute(String[] args) throws Exception { diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java index 740b33d3b9..e8189c2a36 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java @@ -6,6 +6,7 @@ import io.kubernetes.client.openapi.ApiClient; import io.kubernetes.client.util.ClientBuilder; +import io.kubernetes.client.util.Config; import io.kubernetes.client.util.KubeConfig; import io.kubernetes.client.util.generic.GenericKubernetesApi; import io.securecodebox.models.V1Scan; @@ -46,7 +47,15 @@ public void init() throws IOException { String kubeConfigPath = System.getProperty("user.home") + "/.kube/config"; clientBuilder = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))); } else { - clientBuilder = ClientBuilder.cluster(); + try { + clientBuilder = ClientBuilder.cluster(); + } catch (final IllegalStateException e) { + final var msg = String.format( + "Could not create Kubernetes client config! Maybe the env var '%s' and/or '%s' is not set correct" + + "ly.", + Config.ENV_SERVICE_HOST,Config.ENV_SERVICE_PORT); + throw new DefectDojoPersistenceException(msg); + } } this.client = clientBuilder From cb28f6316a23d07b452956d0c214678194e38300 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 15:23:38 +0100 Subject: [PATCH 15/25] Implement Help Message for Easier Usage of Final Binary Signed-off-by: Sven Strittmatter --- .../DefectDojoPersistenceProvider.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java index 2205d06767..e2ddbe05e0 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java @@ -17,10 +17,37 @@ import io.securecodebox.persistence.strategies.VersionedEngagementsStrategy; import lombok.extern.slf4j.Slf4j; +import java.util.Arrays; import java.util.List; @Slf4j public class DefectDojoPersistenceProvider { + private static final String JAR_FILE = "defectdojo-persistenceprovider-1.0.0-SNAPSHOT.jar"; + private static final String USAGE = "Usage: java -jar " + JAR_FILE + " [ ] [-h|--help]"; + private static final String HELP = """ + This hook imports secureCodeBox findings into DefectDojo. + + This provider supports two modes: + + 1. Read-only Mode: Only imports the findings oneway from secureCodeBox into DefectDojo. + 2. syncFindingBack Mode: Replace the finding in secureCodeBox with the finding modified by DefectDojo. + + This provider uses positional arguments. The first and second argument is required (Read-only Mode). + The third and fourth arguments are optional (syncFindingBack Mode). + + Required arguments + + 1st argument (RAW_RESULT_DOWNLOAD_URL): HTTP URL where the raw finding file (various formats depending on scanner) is available. + 2nd argument (FINDING_DOWNLOAD_URL): HTTP URL where the secureCodeBox finding file (JSON) is available. + + Optional arguments: + + 3rd argument (RAW_RESULT_UPLOAD_URL): HTTP URL where to store modified finding file (various formats depending on scanner). + 4th argument (FINDING_UPLOAD_URL): HTTP URL where to store modified secureCodeBox finding file (JSON). + -h|--help Show this help. + + See the documentation for more details: https://www.securecodebox.io/docs/hooks/defectdojo + """; private static final String HELP_HINT = "Use option -h or --help to get more details about the arguments."; private static final int EXIT_CODE_OK = 0; private static final int EXIT_CODE_ERROR = 1; @@ -34,11 +61,13 @@ public static void main(String[] args) { } catch (final DefectDojoPersistenceException e) { // We do not log stack traces on own errors because the message itself must be helpful enough to fix it! log.error(e.getMessage()); + log.error(USAGE); log.error(HELP_HINT); System.exit(EXIT_CODE_ERROR); } catch (final Exception e) { // Also log the stack trace as context for unforeseen errors. log.error(e.getMessage(), e); + log.error(USAGE); log.error(HELP_HINT); System.exit(EXIT_CODE_ERROR); } @@ -46,6 +75,12 @@ public static void main(String[] args) { private void execute(String[] args) throws Exception { log.info("Starting DefectDojo persistence provider"); + + if (shouldShowHelp(args)) { + showHelp(); + return; // Someone showing the help does not expect that anything more is done. + } + kubernetesService.init(); var scan = new Scan(kubernetesService.getScanFromKubernetes()); @@ -86,4 +121,14 @@ private void overwriteFindingWithDefectDojoFinding(Config config, List kubernetesService.updateScanInKubernetes(findings); } + private boolean shouldShowHelp(String[] args) { + return Arrays.stream(args).anyMatch(arg -> arg.equals("-h") || arg.equals("--help")); + } + + private void showHelp() { + System.out.println(USAGE); + System.out.println(); + System.out.println(HELP); + } + } From c09cc785d1045f87f49b07cc1829b3f82ad50f18 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 20:42:45 +0100 Subject: [PATCH 16/25] Verify Number of Passed In Arguments With Proper Error Message Signed-off-by: Sven Strittmatter --- .../DefectDojoPersistenceProvider.java | 15 ++++++++ .../DefectDojoPersistenceProviderTest.java | 38 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java index e2ddbe05e0..288a368af2 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java @@ -81,6 +81,10 @@ private void execute(String[] args) throws Exception { return; // Someone showing the help does not expect that anything more is done. } + if (!wrongNumberOfArguments(args)) { + throw new DefectDojoPersistenceException("Wrong number of arguments!"); + } + kubernetesService.init(); var scan = new Scan(kubernetesService.getScanFromKubernetes()); @@ -131,4 +135,15 @@ private void showHelp() { System.out.println(HELP); } + boolean wrongNumberOfArguments(String[] args) { + if (args.length == 2) { + return true; + } + + if (args.length == 4) { + return true; + } + + return false; + } } diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java new file mode 100644 index 0000000000..f9bf8cbfff --- /dev/null +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java @@ -0,0 +1,38 @@ +package io.securecodebox.persistence; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +class DefectDojoPersistenceProviderTest { + + private final DefectDojoPersistenceProvider sut = new DefectDojoPersistenceProvider(); + + private static Stream provideWrongNumberOfArgumentsFixtures() { + return Stream.of( + Arguments.of(new String[0], false), + Arguments.of(new String[1], false), + Arguments.of(new String[2], true), + Arguments.of(new String[3], false), + Arguments.of(new String[4], true), + Arguments.of(new String[5], false), + Arguments.of(new String[6], false), + Arguments.of(new String[7], false), + Arguments.of(new String[8], false), + Arguments.of(new String[9], false), + Arguments.of(new String[10], false) + ); + } + + @ParameterizedTest + @MethodSource("provideWrongNumberOfArgumentsFixtures") + void wrongNumberOfArguments(final String[] args, final boolean numberOfArgsCorrect) { + assertThat(sut.wrongNumberOfArguments(args), is(numberOfArgsCorrect)); + } + +} From c2e7e806f4d19f9f8042163bb5feaa60c6338926 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 20:48:36 +0100 Subject: [PATCH 17/25] Tests For Help Flag Signed-off-by: Sven Strittmatter --- .../DefectDojoPersistenceProvider.java | 2 +- .../DefectDojoPersistenceProviderTest.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java index 288a368af2..f74c21ad62 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java @@ -125,7 +125,7 @@ private void overwriteFindingWithDefectDojoFinding(Config config, List kubernetesService.updateScanInKubernetes(findings); } - private boolean shouldShowHelp(String[] args) { + boolean shouldShowHelp(String[] args) { return Arrays.stream(args).anyMatch(arg -> arg.equals("-h") || arg.equals("--help")); } diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java index f9bf8cbfff..bc5f49a808 100644 --- a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java @@ -35,4 +35,23 @@ void wrongNumberOfArguments(final String[] args, final boolean numberOfArgsCorre assertThat(sut.wrongNumberOfArguments(args), is(numberOfArgsCorrect)); } + private static Stream provideShouldShowHelpFixtures() { + return Stream.of( + Arguments.of(new String[]{}, false), + Arguments.of(new String[]{"foo"}, false), + Arguments.of(new String[]{"foo", "bar"}, false), + Arguments.of(new String[]{"foo", "bar", "baz"}, false), + Arguments.of(new String[]{"-h"}, true), + Arguments.of(new String[]{"--help"}, true), + Arguments.of(new String[]{"foo", "-h", "baz"}, true), + Arguments.of(new String[]{"foo", "bar", "--help"}, true) + ); + } + + @ParameterizedTest + @MethodSource("provideShouldShowHelpFixtures") + void shouldShowHelp(final String[] args, final boolean showHelp) { + assertThat(sut.shouldShowHelp(args), is(showHelp)); + } + } From d7419e7de9e1bbecc604413e835a20f7771aacd9 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 21:00:28 +0100 Subject: [PATCH 18/25] Log Warning When Running In Dev Mode To PRevent It In Production Signed-off-by: Sven Strittmatter --- .../io/securecodebox/persistence/service/KubernetesService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java index e8189c2a36..4eaac07fef 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java @@ -42,6 +42,7 @@ public void init() throws IOException { final ClientBuilder clientBuilder; if (env.isDev()) { + log.warn("Hook is executed in DEV MODE!"); // loading the out-of-cluster config, a kubeconfig from file-system // FIXME: Usage of reading system properties should be encapsulated in own class. String kubeConfigPath = System.getProperty("user.home") + "/.kube/config"; From 1467ec2d74b38472c57f0f1f06584da77075cbc8 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 21:01:38 +0100 Subject: [PATCH 19/25] Close File Reader By Using Try-With-Resource Signed-off-by: Sven Strittmatter --- .../persistence/service/KubernetesService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java index 4eaac07fef..32e62281fc 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java @@ -45,8 +45,11 @@ public void init() throws IOException { log.warn("Hook is executed in DEV MODE!"); // loading the out-of-cluster config, a kubeconfig from file-system // FIXME: Usage of reading system properties should be encapsulated in own class. - String kubeConfigPath = System.getProperty("user.home") + "/.kube/config"; - clientBuilder = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))); + final var kubeConfigPath = System.getProperty("user.home") + "/.kube/config"; + // FIXME: Better error message if file not exists. + try (final var kubeConfigReader = new FileReader(kubeConfigPath)) { + clientBuilder = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(kubeConfigReader)); + } } else { try { clientBuilder = ClientBuilder.cluster(); From fbb20fac2a8db5be0a95de93bf2902da5e046dde Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 21:02:11 +0100 Subject: [PATCH 20/25] Add Shorthand Script to Execute Jar File Signed-off-by: Sven Strittmatter --- hooks/persistence-defectdojo/hook/run.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 hooks/persistence-defectdojo/hook/run.sh diff --git a/hooks/persistence-defectdojo/hook/run.sh b/hooks/persistence-defectdojo/hook/run.sh new file mode 100755 index 0000000000..70ec2e274e --- /dev/null +++ b/hooks/persistence-defectdojo/hook/run.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -euo pipefail + +java -jar ./build/libs/defectdojo-persistenceprovider-1.0.0-SNAPSHOT.jar "$@" From 3730f8630d9f9dd81c5e9b00357a2bdc2e0815d3 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 21:23:53 +0100 Subject: [PATCH 21/25] Improve Error Message If Kubernetes Config Can't Be Read In Dev Mode Signed-off-by: Sven Strittmatter --- .../securecodebox/persistence/service/KubernetesService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java index 32e62281fc..a3d0db5b8c 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java @@ -21,6 +21,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; @@ -46,9 +47,11 @@ public void init() throws IOException { // loading the out-of-cluster config, a kubeconfig from file-system // FIXME: Usage of reading system properties should be encapsulated in own class. final var kubeConfigPath = System.getProperty("user.home") + "/.kube/config"; - // FIXME: Better error message if file not exists. try (final var kubeConfigReader = new FileReader(kubeConfigPath)) { clientBuilder = ClientBuilder.kubeconfig(KubeConfig.loadKubeConfig(kubeConfigReader)); + } catch (final IOException e) { + final var msg = String.format("Can't read Kubernetes configuration! Tried file path was '%s'.", kubeConfigPath); + throw new DefectDojoPersistenceException(msg); } } else { try { From 2365ba7a1b981636f9c0393431a2b0ae6431acf1 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 21:29:27 +0100 Subject: [PATCH 22/25] Handle Erros Parsing Kubernetes Config Since the error handling of Kubernetes lib and the used YAML parser lib is quite shitty the resulting error message is not very precise. The problem is that e.g. for empty file they just throw an NPE on a underlying Map<>. For bad format it just throw random errors such as class cast excpetions. Signed-off-by: Sven Strittmatter --- .../securecodebox/persistence/service/KubernetesService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java index a3d0db5b8c..58194eefb5 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/service/KubernetesService.java @@ -52,6 +52,9 @@ public void init() throws IOException { } catch (final IOException e) { final var msg = String.format("Can't read Kubernetes configuration! Tried file path was '%s'.", kubeConfigPath); throw new DefectDojoPersistenceException(msg); + } catch (final Exception e) { + final var msg = "Can't parse and create Kubernetes config! Reason: " + e.getMessage(); + throw new DefectDojoPersistenceException(msg, e); } } else { try { From 6f4a291b1e2758a2f3aee7e177d6422d2a780b28 Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 22:00:17 +0100 Subject: [PATCH 23/25] Show Env Vars Also In Help Message Signed-off-by: Sven Strittmatter --- .../DefectDojoPersistenceProvider.java | 11 +++++- .../persistence/config/EnvConfig.java | 34 ++++++------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java index f74c21ad62..f6c853ec93 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/DefectDojoPersistenceProvider.java @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 package io.securecodebox.persistence; +import io.securecodebox.persistence.config.EnvConfig; import io.securecodebox.persistence.config.PersistenceProviderConfig; import io.securecodebox.persistence.defectdojo.config.Config; import io.securecodebox.persistence.defectdojo.model.Finding; @@ -19,6 +20,7 @@ import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; @Slf4j public class DefectDojoPersistenceProvider { @@ -46,6 +48,10 @@ The third and fourth arguments are optional (syncFindingBack Mode). 4th argument (FINDING_UPLOAD_URL): HTTP URL where to store modified secureCodeBox finding file (JSON). -h|--help Show this help. + The hook also looks for various environment variables: + + + See the documentation for more details: https://www.securecodebox.io/docs/hooks/defectdojo """; private static final String HELP_HINT = "Use option -h or --help to get more details about the arguments."; @@ -132,7 +138,10 @@ boolean shouldShowHelp(String[] args) { private void showHelp() { System.out.println(USAGE); System.out.println(); - System.out.println(HELP); + final var envVars = Arrays.stream(EnvConfig.EnvVarNames.values()) + .map(name -> " " + name.getLiteral() + ": " + name.getDescription()) + .collect(Collectors.joining("\n")); + System.out.println(HELP.replace("", envVars)); } boolean wrongNumberOfArguments(String[] args) { diff --git a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/EnvConfig.java b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/EnvConfig.java index deb982dde5..f6c61e5d04 100644 --- a/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/EnvConfig.java +++ b/hooks/persistence-defectdojo/hook/src/main/java/io/securecodebox/persistence/config/EnvConfig.java @@ -119,42 +119,28 @@ private String retrieveEnvVar(EnvVarNames name) { * Enumerates all environment variable names used in this hook */ @Getter - enum EnvVarNames { + public enum EnvVarNames { /** - * Enable development mode. - * * @deprecated use {@link #IS_DEV} instead */ @Deprecated - IS_DEV_LEGACY("IS_DEV"), + IS_DEV_LEGACY("IS_DEV", "(deprecated) Enable development mode."), + IS_DEV("DEFECTDOJO_IS_DEV", "Enable development mode."), + SCAN_NAME("SCAN_NAME", "(provided) secureCodeBox wide environment variable populated with name of the scan custom resource."), + NAMESPACE("NAMESPACE", "(provided) secureCodeBox wide environment variable populated with the Kubernetes namespace the scan is running in."), + LOW_PRIVILEGED_MODE("DEFECTDOJO_LOW_PRIVILEGED_MODE", "Whether low privilege mode is enabled."), /** - * Enable development mode. - */ - IS_DEV("DEFECTDOJO_IS_DEV"), - /** - * secureCodeBox wide environment variable populated with name of the scan custom resource - */ - SCAN_NAME("SCAN_NAME"), - /** - * secureCodeBox wide environment variable populated with the Kubernetes namespace the scan is running in - */ - NAMESPACE("NAMESPACE"), - /** - * Whether low privilege mode is enabled - */ - LOW_PRIVILEGED_MODE("DEFECTDOJO_LOW_PRIVILEGED_MODE"), - /** - * Seconds to wait until re-fetching findings from DefectDojo - * * @deprecated see {@link EnvConfig#refetchWaitSeconds()} */ @Deprecated - REFETCH_WAIT_SECONDS("DEFECTDOJO_REFETCH_WAIT_SECONDS"); + REFETCH_WAIT_SECONDS("DEFECTDOJO_REFETCH_WAIT_SECONDS", "(deprecated) Seconds to wait until re-fetching findings from DefectDojo."); private final String literal; + private final String description; - EnvVarNames(String literal) { + EnvVarNames(String literal, String description) { this.literal = literal; + this.description = description; } } } From c31d60041242e464a252d04520f898bc4e6496ef Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Tue, 7 Jan 2025 22:07:55 +0100 Subject: [PATCH 24/25] Add Missing License Headers Signed-off-by: Sven Strittmatter --- .../persistence/DefectDojoPersistenceProviderTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java index bc5f49a808..c6c15de057 100644 --- a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 package io.securecodebox.persistence; import org.junit.jupiter.params.ParameterizedTest; From 0be20ca9fd24a61839d5aaeb7b2d404a1dedd5fd Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Thu, 16 Jan 2025 12:38:23 +0100 Subject: [PATCH 25/25] Add Missing SPDX Headers Signed-off-by: Sven Strittmatter --- hooks/persistence-defectdojo/hook/run.sh | 4 ++++ .../persistence/config/PersistenceProviderConfigTest.java | 3 +++ 2 files changed, 7 insertions(+) diff --git a/hooks/persistence-defectdojo/hook/run.sh b/hooks/persistence-defectdojo/hook/run.sh index 70ec2e274e..3ed8b3a33b 100755 --- a/hooks/persistence-defectdojo/hook/run.sh +++ b/hooks/persistence-defectdojo/hook/run.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# SPDX-FileCopyrightText: the secureCodeBox authors +# +# SPDX-License-Identifier: Apache-2.0 + set -euo pipefail java -jar ./build/libs/defectdojo-persistenceprovider-1.0.0-SNAPSHOT.jar "$@" diff --git a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java index 29fb972296..5d5655f4dd 100644 --- a/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java +++ b/hooks/persistence-defectdojo/hook/src/test/java/io/securecodebox/persistence/config/PersistenceProviderConfigTest.java @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 package io.securecodebox.persistence.config; import io.securecodebox.persistence.exceptions.DefectDojoPersistenceException;