diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidatorExitcode.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/InputValidatorExitcode.java similarity index 88% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidatorExitcode.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/InputValidatorExitcode.java index b23d6ae85..e77c0b72b 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidatorExitcode.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/InputValidatorExitcode.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; +package com.mercedesbenz.sechub.wrapper.prepare; public enum InputValidatorExitcode { diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/LogSanitizerProvider.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/LogSanitizerProvider.java new file mode 100644 index 000000000..9155e586b --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/LogSanitizerProvider.java @@ -0,0 +1,8 @@ +package com.mercedesbenz.sechub.wrapper.prepare; + +import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; + +public interface LogSanitizerProvider { + + public PDSLogSanitizer getLogSanitizer(); +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareAcceptFilter.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareAcceptFilter.java new file mode 100644 index 000000000..ac0d841be --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareAcceptFilter.java @@ -0,0 +1,13 @@ +package com.mercedesbenz.sechub.wrapper.prepare; + +public interface PrepareAcceptFilter { + + /** + * Checks if it is possible to prepare by the given context informatoin + * + * @param context current context + * @return true when prepare is possible, otherwise + * false + */ + public boolean isAccepting(PrepareWrapperContext context); +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidationSupport.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidationSupport.java new file mode 100644 index 000000000..b6c0ddf41 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidationSupport.java @@ -0,0 +1,234 @@ +package com.mercedesbenz.sechub.wrapper.prepare; + +import static com.mercedesbenz.sechub.wrapper.prepare.InputValidatorExitcode.*; +import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; + +public class PrepareInputValidationSupport { + + private static final Logger LOG = LoggerFactory.getLogger(PrepareInputValidationSupport.class); + private String type; + + private Pattern locationPattern; + private Pattern usernamePattern; + private Pattern passwordPattern; + + private final List forbiddenCharacters = Collections + .unmodifiableList(Arrays.asList(">", "<", "!", "?", "*", "'", "\"", ";", "&", "|", "`", "$", "{", "}")); + + private LogSanitizerProvider logSanitizerProvider; + + public static InputValidationSupportBuilder builder() { + return new InputValidationSupportBuilder(); + } + + private static boolean isTypeNullOrEmpty(String type) { + return type == null || type.isEmpty(); + } + + private static void assertPatternNotNull(Pattern pattern) { + if (pattern == null) { + throw new IllegalArgumentException("Pattern must not be null."); + } + } + + public void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { + validateModuleData(context); + validateCredentials(context); + } + + private void validateModuleData(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { + SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); + String location = secHubRemoteDataConfiguration.getLocation(); + String type = secHubRemoteDataConfiguration.getType(); + + if (isTypeNullOrEmpty(type)) { + if (LOG.isDebugEnabled()) { + LOG.debug("No type was defined for location {}.", logSanitizerProvider.getLogSanitizer().sanitize(location, 1024)); + } + validateLocation(location); + return; + } else if (isTypeMatching(type)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Type is matching type {}. Location is: {}", type, logSanitizerProvider.getLogSanitizer().sanitize(location, 1024)); + } + validateLocation(location); + return; + } + throw new PrepareWrapperInputValidatorException("Defined type " + type + " was not modules type " + type + ".", TYPE_NOT_MATCHING_PATTERN); + } + + private void validateCredentials(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { + SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); + + if (secHubRemoteDataConfiguration.getCredentials().isPresent()) { + SecHubRemoteCredentialConfiguration remoteCredentialConfiguration = secHubRemoteDataConfiguration.getCredentials().get(); + if (remoteCredentialConfiguration.getUser().isPresent()) { + SecHubRemoteCredentialUserData user = remoteCredentialConfiguration.getUser().get(); + validateUsername(user.getName()); + validatePassword(user.getPassword()); + return; + } + // credentials object was empty + throw new PrepareWrapperUsageException("Defined credentials must contain credential user and can not be empty.", CREDENTIALS_NOT_DEFINED); + } + } + + private void validateUsername(String username) throws PrepareWrapperInputValidatorException { + if (isLocationUndefined(username)) { + throw new PrepareWrapperUsageException("Defined username must not be null or empty. Username is required for login.", + CREDENTIAL_USER_NAME_NOT_DEFINED); + } + + if (!usernamePattern.matcher(username).matches()) { + throw new PrepareWrapperInputValidatorException("Defined username must match the " + type + " pattern.", CREDENTIALS_USERNAME_NOT_MATCHING_PATTERN); + } + } + + private void validatePassword(String password) throws PrepareWrapperInputValidatorException { + if (isLocationUndefined(password)) { + throw new PrepareWrapperUsageException("Defined password must not be null or empty. Password is required for login.", + CREDENTIAL_USER_PASSWORD_NOT_DEFINED); + } + + if (!passwordPattern.matcher(password).matches()) { + throw new PrepareWrapperInputValidatorException("Defined password must match the " + type + " Api token pattern.", + CREDENTIALS_PASSWORD_NOT_MATCHING_PATTERN); + } + } + + private void validateLocation(String location) throws PrepareWrapperInputValidatorException { + if (isLocationUndefined(location)) { + throw new PrepareWrapperUsageException("Defined location must not be null or empty. Location is required for download remote data.", + LOCATION_NOT_DEFINED); + } + validateLocationCharacters(location); + if (!isLocationPatternMatching(location)) { + throw new PrepareWrapperInputValidatorException("Defined location must match the " + type + " pattern.", LOCATION_NOT_MATCHING_PATTERN); + } + } + + private boolean isLocationPatternMatching(String location) { + return locationPattern.matcher(location).matches(); + } + + private boolean isLocationUndefined(String location) { + return location == null || location.isBlank(); + } + + private boolean isTypeMatching(String type) { + return type.equalsIgnoreCase(this.type); + } + + private void validateLocationCharacters(String url) { + if (url.contains(" ")) { + throw new PrepareWrapperUsageException("Defined location URL must not contain whitespaces.", LOCATION_CONTAINS_FORBIDDEN_CHARACTER); + } + for (String forbiddenCharacter : forbiddenCharacters) { + if (url.contains(forbiddenCharacter)) { + throw new PrepareWrapperUsageException("Defined location URL must not contain forbidden characters: " + forbiddenCharacter, + LOCATION_CONTAINS_FORBIDDEN_CHARACTER); + } + } + } + + public static class InputValidationSupportBuilder { + private String type; + + private Pattern locationPattern; + private Pattern usernamePattern; + private Pattern passwordPattern; + + private LogSanitizerProvider logSanitizerProvider; + + private InputValidationSupportBuilder() { + + } + + public InputValidationSupportBuilder setLocationPattern(Pattern locationPattern) { + this.locationPattern = locationPattern; + return this; + } + + public InputValidationSupportBuilder setUserNamePattern(Pattern usernamePattern) { + this.usernamePattern = usernamePattern; + return this; + } + + public InputValidationSupportBuilder setPasswordPattern(Pattern passwordPattern) { + this.passwordPattern = passwordPattern; + return this; + } + + public InputValidationSupportBuilder setType(String type) { + this.type = type; + return this; + } + + public InputValidationSupportBuilder setLogSanitizerProvider(LogSanitizerProvider logSanitizerProvider) { + this.logSanitizerProvider = logSanitizerProvider; + return this; + } + + public PrepareInputValidationSupport build() { + assertPatternNotNull(locationPattern); + assertPatternNotNull(usernamePattern); + assertPatternNotNull(passwordPattern); + + if (isTypeNullOrEmpty(type)) { + throw new IllegalArgumentException("Type must not be null or empty."); + } + + if (logSanitizerProvider == null) { + throw new IllegalArgumentException("Log sanitizer provider not defined"); + } + + if (type == null) { + type = ""; + } + PrepareInputValidationSupport result = new PrepareInputValidationSupport(); + + result.type = type.trim(); + result.locationPattern = locationPattern; + result.usernamePattern = usernamePattern; + result.passwordPattern = passwordPattern; + result.logSanitizerProvider = logSanitizerProvider; + + return result; + } + } + + public boolean isAccepting(PrepareWrapperContext context) { + + SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); + if (secHubRemoteDataConfiguration == null) { + return false; + } + + String type = secHubRemoteDataConfiguration.getType(); + + if (isTypeNullOrEmpty(type)) { + /* no explicit type set - we must check by location */ + String location = secHubRemoteDataConfiguration.getLocation(); + if (isLocationUndefined(location)) { + return false; + } + + return isLocationPatternMatching(location); + } else { + return isTypeMatching(type); + } + } + +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidator.java new file mode 100644 index 000000000..b36db0a1c --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareInputValidator.java @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare; + +public interface PrepareInputValidator { + + void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException; +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContext.java similarity index 96% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContext.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContext.java index c325d3c11..b7a74bd3d 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContext.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContext.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; import java.util.ArrayList; import java.util.List; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactory.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactory.java similarity index 86% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactory.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactory.java index 0cbdd9b6b..f6621d214 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactory.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactory.java @@ -1,12 +1,14 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.mercedesbenz.sechub.commons.model.*; +import com.mercedesbenz.sechub.commons.model.JSONConverter; +import com.mercedesbenz.sechub.commons.model.JSONConverterException; +import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; @Component diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperInputValidatorException.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperInputValidatorException.java similarity index 78% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperInputValidatorException.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperInputValidatorException.java index 4632cd68e..9a871a6ae 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperInputValidatorException.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperInputValidatorException.java @@ -1,7 +1,9 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; +package com.mercedesbenz.sechub.wrapper.prepare; -public class PrepareWrapperInputValidatorException extends Exception { +import java.io.IOException; + +public class PrepareWrapperInputValidatorException extends IOException { private static final long serialVersionUID = 1L; private InputValidatorExitcode exitCode; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPDSUserMessageSupportPojoFactory.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPDSUserMessageSupportFactory.java similarity index 75% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPDSUserMessageSupportPojoFactory.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPDSUserMessageSupportFactory.java index 231737199..838738ec7 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPDSUserMessageSupportPojoFactory.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPDSUserMessageSupportFactory.java @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.factory; +package com.mercedesbenz.sechub.wrapper.prepare; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import com.mercedesbenz.sechub.commons.TextFileWriter; @@ -10,7 +11,8 @@ import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; @Component -public class PrepareWrapperPDSUserMessageSupportPojoFactory { +public class PrepareWrapperPDSUserMessageSupportFactory { + @Autowired PrepareWrapperEnvironment environment; @@ -18,6 +20,7 @@ public class PrepareWrapperPDSUserMessageSupportPojoFactory { TextFileWriter writer; @Bean + @Lazy // lazy, to have possibility to mock environment in spring boot tests PDSUserMessageSupport createUserMessageSupport() { String userMessageFolder = environment.getPdsUserMessagesFolder(); return new PDSUserMessageSupport(userMessageFolder, writer); diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPojoFactory.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPojoFactory.java similarity index 94% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPojoFactory.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPojoFactory.java index 4c12c4220..109f68a5c 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/factory/PrepareWrapperPojoFactory.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPojoFactory.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.factory; +package com.mercedesbenz.sechub.wrapper.prepare; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationService.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationService.java similarity index 68% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationService.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationService.java index d8a405058..d8f4eaf2f 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationService.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationService.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; import java.io.IOException; import java.util.ArrayList; @@ -14,7 +14,9 @@ import com.mercedesbenz.sechub.adapter.AdapterExecutionResult; import com.mercedesbenz.sechub.commons.core.prepare.PrepareResult; import com.mercedesbenz.sechub.commons.core.prepare.PrepareStatus; -import com.mercedesbenz.sechub.commons.model.*; +import com.mercedesbenz.sechub.commons.model.SecHubMessage; +import com.mercedesbenz.sechub.commons.model.SecHubMessageType; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; @@ -27,7 +29,7 @@ public class PrepareWrapperPreparationService { PrepareWrapperEnvironment environment; @Autowired - PrepareWrapperContextFactory factory; + PrepareWrapperContextFactory contextFactory; @Autowired List modules = new ArrayList<>(); @@ -35,7 +37,7 @@ public class PrepareWrapperPreparationService { public AdapterExecutionResult startPreparation() throws IOException { LOG.debug("Start preparation"); - PrepareWrapperContext context = factory.create(environment); + PrepareWrapperContext context = contextFactory.create(environment); SecHubRemoteDataConfiguration remoteDataConfiguration = context.getRemoteDataConfiguration(); if (remoteDataConfiguration == null) { @@ -43,15 +45,28 @@ public AdapterExecutionResult startPreparation() throws IOException { return createAdapterExecutionResult(PrepareStatus.OK, SecHubMessageType.WARNING, "No Remote Configuration found."); } - LOG.warn(modules.toString()); + String location = remoteDataConfiguration.getLocation(); + if (location == null || location.isBlank()) { + return createAdapterExecutionResult(PrepareStatus.FAILED, SecHubMessageType.ERROR, "Remote Configuration has no location defined!"); + } + + LOG.info("Start preparation with following modules: {}", modules); for (PrepareWrapperModule module : modules) { + if (!module.isEnabled()) { + LOG.debug("Module: {} is not enabled - so skipped", module); + continue; + } + + if (module.isResponsibleToPrepare(context)) { + LOG.debug("Module: {} is responsible and will be used to prepare", module); + + module.prepare(context); - if (module.prepare(context)) { - context.getUserMessages().add(new SecHubMessage(SecHubMessageType.INFO, "Executed prepare module: " + module.getClass().getSimpleName())); PrepareResult result = new PrepareResult(PrepareStatus.OK); return new AdapterExecutionResult(result.toString(), context.getUserMessages()); } + } return createAdapterExecutionResult(PrepareStatus.FAILED, SecHubMessageType.ERROR, "No module was able to prepare the defined remote data."); @@ -60,8 +75,10 @@ public AdapterExecutionResult startPreparation() throws IOException { private AdapterExecutionResult createAdapterExecutionResult(PrepareStatus status, SecHubMessageType type, String message) { PrepareResult result = new PrepareResult(status); SecHubMessage secHubMessage = new SecHubMessage(type, message); + Collection messages = new ArrayList<>(); messages.add(secHubMessage); + return new AdapterExecutionResult(result.toString(), messages); } } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractor.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractor.java similarity index 91% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractor.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractor.java index b606ecdb1..2d40735e9 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractor.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractor.java @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.ONLY_ONE_REMOTE_DATA_CONFIGURATION_ALLOWED; +import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; import java.util.ArrayList; import java.util.List; @@ -12,7 +12,6 @@ import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubSourceDataConfiguration; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; @Component public class PrepareWrapperRemoteConfigurationExtractor { diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageService.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageService.java similarity index 96% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageService.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageService.java index f884d6917..ffbba556b 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageService.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageService.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; import java.io.File; import java.io.IOException; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperUsageException.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperUsageException.java similarity index 81% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperUsageException.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperUsageException.java index 1202f120c..7abc9878c 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperUsageException.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperUsageException.java @@ -1,4 +1,6 @@ -package com.mercedesbenz.sechub.wrapper.prepare.modules; +package com.mercedesbenz.sechub.wrapper.prepare; + +import com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode; public class PrepareWrapperUsageException extends RuntimeException { diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLI.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLI.java index 99d340886..0d0392d82 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLI.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLI.java @@ -15,9 +15,9 @@ import com.mercedesbenz.sechub.commons.core.prepare.PrepareStatus; import com.mercedesbenz.sechub.commons.model.SecHubMessage; import com.mercedesbenz.sechub.commons.model.SecHubMessageType; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperPreparationService; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperResultStorageService; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperPreparationService; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperResultStorageService; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadException; @Component diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperKeyConstants.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperKeyConstants.java index f88ebc579..d1fb1f6ae 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperKeyConstants.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperKeyConstants.java @@ -11,22 +11,22 @@ public class PrepareWrapperKeyConstants { public static final String KEY_PDS_PREPARE_PROCESS_TIMEOUT_SECONDS = "pds.prepare.process.timeout.seconds"; /** - * Flag to enable the git prepare module + * Flag to enable the gitWrapper prepare module */ public static final String KEY_PDS_PREPARE_MODULE_GIT_ENABLED = "pds.prepare.module.git.enabled"; /** - * Flag to enable the skopeo prepare module + * Flag to enable the skopeoWrapper prepare module */ public static final String KEY_PDS_PREPARE_MODULE_SKOPEO_ENABLED = "pds.prepare.module.skopeo.enabled"; /** - * Flag to clean the git folder from git files and clone without history + * Flag to clean the gitWrapper folder from git files and clone without history */ public static final String KEY_PDS_PREPARE_AUTO_CLEANUP_GIT_FOLDER = "pds.prepare.auto.cleanup.git.folder"; /** - * Filename for skopeo authentication file + * Filename for skopeoWrapper authentication file */ public static final String KEY_PDS_PREPARE_AUTHENTICATION_FILE_SKOPEO = "pds.prepare.authentication.file.skopeo"; } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidator.java deleted file mode 100644 index 52e723327..000000000 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidator.java +++ /dev/null @@ -1,144 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; - -import static com.mercedesbenz.sechub.wrapper.prepare.modules.InputValidatorExitcode.*; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -import com.mercedesbenz.sechub.commons.model.*; -import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; - -public class AbstractInputValidator implements InputValidator { - - private static final Logger LOG = LoggerFactory.getLogger(AbstractInputValidator.class); - private final String TYPE; - private final Pattern LOCATION_PATTERN; - private final Pattern USERNAME_PATTERN; - private final Pattern PASSWORD_PATTERN; - private final List forbiddenCharacters = Collections - .unmodifiableList(Arrays.asList(">", "<", "!", "?", "*", "'", "\"", ";", "&", "|", "`", "$", "{", "}")); - - @Autowired - public PDSLogSanitizer pdsLogSanitizer; - - public AbstractInputValidator(String type, Pattern locationPattern, Pattern usernamePattern, Pattern passwordPattern) { - assertPatternNotNull(locationPattern); - assertPatternNotNull(usernamePattern); - assertPatternNotNull(passwordPattern); - if (isTypeNullOrEmpty(type)) { - throw new IllegalArgumentException("Type must not be null or empty."); - } - - this.TYPE = type; - this.LOCATION_PATTERN = locationPattern; - this.USERNAME_PATTERN = usernamePattern; - this.PASSWORD_PATTERN = passwordPattern; - } - - public void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { - validateModule(context); - validateCredentials(context); - } - - private void validateModule(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { - SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); - String location = secHubRemoteDataConfiguration.getLocation(); - String type = secHubRemoteDataConfiguration.getType(); - - if (isTypeNullOrEmpty(type)) { - LOG.debug("No type was defined for location {}.", pdsLogSanitizer.sanitize(location, 1024)); - validateLocation(location); - return; - } else if (isMatchingType(type)) { - LOG.debug("Type is matching type {}. Location is: {}", TYPE, pdsLogSanitizer.sanitize(location, 1024)); - validateLocation(location); - return; - } - throw new PrepareWrapperInputValidatorException("Defined type " + type + " was not modules type " + TYPE + ".", TYPE_NOT_MATCHING_PATTERN); - } - - private void validateCredentials(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { - SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); - - if (secHubRemoteDataConfiguration.getCredentials().isPresent()) { - SecHubRemoteCredentialConfiguration remoteCredentialConfiguration = secHubRemoteDataConfiguration.getCredentials().get(); - if (remoteCredentialConfiguration.getUser().isPresent()) { - SecHubRemoteCredentialUserData user = remoteCredentialConfiguration.getUser().get(); - validateUsername(user.getName()); - validatePassword(user.getPassword()); - return; - } - // credentials object was empty - throw new PrepareWrapperUsageException("Defined credentials must contain credential user and can not be empty.", CREDENTIALS_NOT_DEFINED); - } - } - - public void validateUsername(String username) throws PrepareWrapperInputValidatorException { - if (username == null || username.isBlank()) { - throw new PrepareWrapperUsageException("Defined username must not be null or empty. Username is required for login.", - CREDENTIAL_USER_NAME_NOT_DEFINED); - } - - if (!USERNAME_PATTERN.matcher(username).matches()) { - throw new PrepareWrapperInputValidatorException("Defined username must match the " + TYPE + " pattern.", CREDENTIALS_USERNAME_NOT_MATCHING_PATTERN); - } - } - - public void validatePassword(String password) throws PrepareWrapperInputValidatorException { - if (password == null || password.isBlank()) { - throw new PrepareWrapperUsageException("Defined password must not be null or empty. Password is required for login.", - CREDENTIAL_USER_PASSWORD_NOT_DEFINED); - } - - if (!PASSWORD_PATTERN.matcher(password).matches()) { - throw new PrepareWrapperInputValidatorException("Defined password must match the " + TYPE + " Api token pattern.", - CREDENTIALS_PASSWORD_NOT_MATCHING_PATTERN); - } - } - - public void validateLocation(String location) throws PrepareWrapperInputValidatorException { - if (location == null || location.isBlank()) { - throw new PrepareWrapperUsageException("Defined location must not be null or empty. Location is required for download remote data.", - LOCATION_NOT_DEFINED); - } - validateLocationCharacters(location); - if (!LOCATION_PATTERN.matcher(location).matches()) { - throw new PrepareWrapperInputValidatorException("Defined location must match the " + TYPE + " pattern.", LOCATION_NOT_MATCHING_PATTERN); - } - } - - private boolean isTypeNullOrEmpty(String type) { - return type == null || type.isEmpty(); - } - - private boolean isMatchingType(String type) { - return TYPE.equalsIgnoreCase(type); - } - - private void validateLocationCharacters(String url) { - if (url.contains(" ")) { - throw new PrepareWrapperUsageException("Defined location URL must not contain whitespaces.", LOCATION_CONTAINS_FORBIDDEN_CHARACTER); - } - for (String forbiddenCharacter : forbiddenCharacters) { - if (url.contains(forbiddenCharacter)) { - throw new PrepareWrapperUsageException("Defined location URL must not contain forbidden characters: " + forbiddenCharacter, - LOCATION_CONTAINS_FORBIDDEN_CHARACTER); - } - } - } - - private void assertPatternNotNull(Pattern pattern) { - if (pattern == null) { - throw new IllegalArgumentException("Pattern must not be null."); - } - } -} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareToolContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareToolContext.java new file mode 100644 index 000000000..4ee1c0bd0 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareToolContext.java @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare.modules; + +import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.*; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import javax.crypto.SealedObject; + +import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; + +public abstract class AbstractPrepareToolContext implements PrepareToolContext { + + private static final String UPLOAD_DIRECTORY_NAME = "upload"; + + private String location; + protected Path uploadDirectory; + + private Map credentialMap = new HashMap<>(); + + public void setLocation(String location) { + this.location = location; + } + + public void init(Path workingDirectory) { + if (workingDirectory == null) { + throw new IllegalArgumentException("Upload directory may not be null!"); + } + this.uploadDirectory = workingDirectory.resolve(UPLOAD_DIRECTORY_NAME); + } + + @Override + public String getLocation() { + return location; + } + + @Override + public Path getUploadDirectory() { + return uploadDirectory; + } + + public String getUnsealedUsername() { + return CryptoAccess.CRYPTO_STRING.unseal(credentialMap.get(PDS_PREPARE_CREDENTIAL_USERNAME)); + } + + public String getUnsealedPassword() { + return CryptoAccess.CRYPTO_STRING.unseal(credentialMap.get(PDS_PREPARE_CREDENTIAL_PASSWORD)); + } + + public boolean hasCredentials() { + return !credentialMap.isEmpty(); + } + + /* + * TODO Albert Tregnaghi, 2024-06-06: the user data is still in memory - means + * context does seal, but sensitive data is still plain inside memory (caller + * side)! Must be fixed with config encryption! + */ + public void setSealedCredentials(SecHubRemoteCredentialUserData user) { + setSealedCredentials(user.getName(), user.getPassword()); + } + + public void setSealedCredentials(String username, String password) { + + SealedObject sealedUsername = CryptoAccess.CRYPTO_STRING.seal(username); + credentialMap.put(PDS_PREPARE_CREDENTIAL_USERNAME, sealedUsername); + + SealedObject sealedPassword = CryptoAccess.CRYPTO_STRING.seal(password); + credentialMap.put(PDS_PREPARE_CREDENTIAL_PASSWORD, sealedPassword); + } +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareWrapperModule.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareWrapperModule.java new file mode 100644 index 000000000..eaf238718 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractPrepareWrapperModule.java @@ -0,0 +1,41 @@ +package com.mercedesbenz.sechub.wrapper.prepare.modules; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import com.mercedesbenz.sechub.commons.model.SecHubMessage; +import com.mercedesbenz.sechub.commons.model.SecHubMessageType; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; + +public abstract class AbstractPrepareWrapperModule implements PrepareWrapperModule { + + @Override + public final void prepare(PrepareWrapperContext context) throws IOException { + prepareImpl(context); + + String userMessageForPreparationDone = getUserMessageForPreparationDone(); + if (userMessageForPreparationDone != null) { + context.getUserMessages().add(new SecHubMessage(SecHubMessageType.INFO, userMessageForPreparationDone)); + } + + } + + protected abstract void prepareImpl(PrepareWrapperContext context) throws IOException; + + protected void ensureDirectoryExists(Path path) { + if (Files.exists(path)) { + return; + } + try { + Files.createDirectories(path); + } catch (IOException e) { + throw new RuntimeException("Error while creating download directory: " + path, e); + } + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidator.java deleted file mode 100644 index c6398840f..000000000 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidator.java +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; - -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; - -public interface InputValidator { - void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException; -} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareToolContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareToolContext.java new file mode 100644 index 000000000..bb6981c1f --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareToolContext.java @@ -0,0 +1,13 @@ +package com.mercedesbenz.sechub.wrapper.prepare.modules; + +import java.nio.file.Path; + +public interface PrepareToolContext { + + String getLocation(); + + Path getUploadDirectory(); + + Path getToolDownloadDirectory(); + +} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperModule.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperModule.java index c6bacfcdb..f43f2cc32 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperModule.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/PrepareWrapperModule.java @@ -1,42 +1,45 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_PASSWORD; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_USERNAME; - import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; - -import javax.crypto.SealedObject; import org.springframework.stereotype.Service; -import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; -import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; @Service public interface PrepareWrapperModule { - boolean prepare(PrepareWrapperContext context) throws IOException; - - default void addSealedUserCredentials(SecHubRemoteCredentialUserData user, HashMap credentialMap) { - SealedObject sealedUsername = CryptoAccess.CRYPTO_STRING.seal(user.getName()); - SealedObject sealedPassword = CryptoAccess.CRYPTO_STRING.seal(user.getPassword()); - credentialMap.put(PDS_PREPARE_CREDENTIAL_USERNAME, sealedUsername); - credentialMap.put(PDS_PREPARE_CREDENTIAL_PASSWORD, sealedPassword); - } - - default void createDownloadDirectory(Path path) { - if (Files.exists(path)) { - return; - } - try { - Files.createDirectories(path); - } catch (IOException e) { - throw new RuntimeException("Error while creating download directory: " + path, e); - } - } + /** + * Checks if the module is responsible to prepare. + * + * @param context the current context with data inside to check responsibility + * @return true when responsible, false otherwise + */ + boolean isResponsibleToPrepare(PrepareWrapperContext context); + + /** + * Does prepare + * + * @param context current context + * @throws IOException when preparation failed + */ + void prepare(PrepareWrapperContext context) throws IOException; + + /** + * Resolves user message which is send back to user when preparation was done by + * module + * + * @return user message or null when no message shall be sent to + * user + */ + String getUserMessageForPreparationDone(); + + /** + * Resolves if this module is enabled or not + * + * @return true when enabled, otherwise false + */ + boolean isEnabled(); + } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolContext.java deleted file mode 100644 index 959b48d0a..000000000 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolContext.java +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; - -import java.nio.file.Path; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import javax.crypto.SealedObject; - -public abstract class ToolContext { - - private static final String UPLOAD_DIRECTORY_NAME = "upload"; - private String location; - protected Path uploadDirectory; - protected Path toolDownloadDirectory; - - private Map credentialMap = new HashMap<>(); - - public void setLocation(String location) { - this.location = location; - } - - public void setupRequiredToolDirectories(Path workingDirectory) { - if (workingDirectory == null) { - throw new IllegalArgumentException("Upload directory may not be null!"); - } - this.uploadDirectory = workingDirectory.resolve(UPLOAD_DIRECTORY_NAME); - } - - public void setCredentialMap(Map credentialMap) { - this.credentialMap = credentialMap; - } - - public String getLocation() { - return location; - } - - public Path getUploadDirectory() { - return uploadDirectory; - } - - public Map getCredentialMap() { - return Collections.unmodifiableMap(credentialMap); - } - - public Path getToolDownloadDirectory() { - return toolDownloadDirectory; - } - -} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/WrapperTool.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolWrapper.java similarity index 92% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/WrapperTool.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolWrapper.java index fa212714c..7042e28e8 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/WrapperTool.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/ToolWrapper.java @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules; -import static com.mercedesbenz.sechub.commons.pds.PDSDefaultParameterKeyConstants.PARAM_KEY_PDS_CONFIG_PRODUCT_TIMEOUT_MINUTES; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.KEY_PDS_PREPARE_PROCESS_TIMEOUT_SECONDS; +import static com.mercedesbenz.sechub.commons.pds.PDSDefaultParameterKeyConstants.*; +import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.*; import java.io.IOException; import java.nio.file.Path; @@ -17,9 +17,9 @@ import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; @Component -public abstract class WrapperTool { +public abstract class ToolWrapper { - private static final Logger LOG = LoggerFactory.getLogger(WrapperTool.class); + private static final Logger LOG = LoggerFactory.getLogger(ToolWrapper.class); private static final int defaultMinutesToWaitForProduct = PDSDefaultParameterValueConstants.DEFAULT_MINUTES_TO_WAIT_FOR_PRODUCT; @Value("${" + PARAM_KEY_PDS_CONFIG_PRODUCT_TIMEOUT_MINUTES + ":" + defaultMinutesToWaitForProduct + "}") diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitContext.java index 72ae437c2..7488d078e 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitContext.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitContext.java @@ -3,21 +3,22 @@ import java.nio.file.Path; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; -public class GitContext extends ToolContext { +public class GitContext extends AbstractPrepareToolContext { static final String DOWNLOAD_DIRECTORY_NAME = "git-download"; private boolean cloneWithoutHistory; private String repositoryName = "git-repository"; + private Path toolDownloadDirectory; public void setCloneWithoutHistory(boolean cloneWithoutHistory) { this.cloneWithoutHistory = cloneWithoutHistory; } @Override - public void setupRequiredToolDirectories(Path workingDirectory) { - super.setupRequiredToolDirectories(workingDirectory); + public void init(Path workingDirectory) { + super.init(workingDirectory); toolDownloadDirectory = workingDirectory.resolve(DOWNLOAD_DIRECTORY_NAME); } @@ -33,4 +34,9 @@ public boolean isCloneWithoutHistory() { return cloneWithoutHistory; } + @Override + public Path getToolDownloadDirectory() { + return toolDownloadDirectory; + } + } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidator.java deleted file mode 100644 index c214fe267..000000000 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidator.java +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules.git; - -import java.util.regex.Pattern; - -import org.springframework.stereotype.Component; - -import com.mercedesbenz.sechub.commons.model.*; -import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractInputValidator; - -@Component -public class GitInputValidator extends AbstractInputValidator { - - private static final String TYPE = "git"; - private static final String GIT_LOCATION_REGEX = "((git|ssh|http(s)?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?$"; - private static final Pattern GIT_LOCATION_PATTERN = Pattern.compile(GIT_LOCATION_REGEX); - private static final String GIT_USERNAME_REGEX = "^[a-zA-Z0-9-_\\d](?:[a-zA-Z0-9-_\\d]|(?=[a-zA-Z0-9-_\\d])){0,38}$"; - private static final Pattern GIT_USERNAME_PATTERN = Pattern.compile(GIT_USERNAME_REGEX); - private static final String GIT_PASSWORD_REGEX = "^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$"; - private static final Pattern GIT_PASSWORD_PATTERN = Pattern.compile(GIT_PASSWORD_REGEX); - - public GitInputValidator() { - super(TYPE, GIT_LOCATION_PATTERN, GIT_USERNAME_PATTERN, GIT_PASSWORD_PATTERN); - } -} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareInputValidator.java new file mode 100644 index 000000000..a0d1b15b5 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareInputValidator.java @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare.modules.git; + +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; +import com.mercedesbenz.sechub.wrapper.prepare.LogSanitizerProvider; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareAcceptFilter; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareInputValidationSupport; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareInputValidator; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; + +@Component +public class GitPrepareInputValidator implements PrepareInputValidator, LogSanitizerProvider, PrepareAcceptFilter { + + private static final String TYPE = "git"; + + private static final String GIT_LOCATION_REGEX = "((git|ssh|http(s)?)|(git@[\\w\\.]+))(:(//)?)([\\w\\.@\\:/\\-~]+)(\\.git)(/)?$"; + private static final Pattern GIT_LOCATION_PATTERN = Pattern.compile(GIT_LOCATION_REGEX); + + private static final String GIT_USERNAME_REGEX = "^[a-zA-Z0-9-_\\d](?:[a-zA-Z0-9-_\\d]|(?=[a-zA-Z0-9-_\\d])){0,38}$"; + private static final Pattern GIT_USERNAME_PATTERN = Pattern.compile(GIT_USERNAME_REGEX); + + private static final String GIT_PASSWORD_REGEX = "^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$"; + private static final Pattern GIT_PASSWORD_PATTERN = Pattern.compile(GIT_PASSWORD_REGEX); + + private PrepareInputValidationSupport support; + + @Autowired + PDSLogSanitizer logSanitizer; + + public GitPrepareInputValidator() { + /* @formatter:off */ + this.support = PrepareInputValidationSupport.builder(). + setType(TYPE). + setLogSanitizerProvider(this). + setLocationPattern(GIT_LOCATION_PATTERN). + setUserNamePattern(GIT_USERNAME_PATTERN). + setPasswordPattern(GIT_PASSWORD_PATTERN). + build(); + /* @formatter:on */ + } + + @Override + public void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { + support.validate(context); + } + + @Override + public PDSLogSanitizer getLogSanitizer() { + return logSanitizer; + } + + @Override + public boolean isAccepting(PrepareWrapperContext context) { + return support.isAccepting(context); + } +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGit.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModule.java similarity index 67% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGit.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModule.java index 8014c9c65..3aad62c9b 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGit.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModule.java @@ -1,19 +1,16 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.git; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.KEY_PDS_PREPARE_AUTO_CLEANUP_GIT_FOLDER; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.KEY_PDS_PREPARE_MODULE_GIT_ENABLED; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.CREDENTIALS_NOT_DEFINED; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.DOWNLOAD_NOT_SUCCESSFUL; -import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.GIT_REPOSITORY_UPLOAD_FAILED; +import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.*; +import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; +import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.*; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.*; - -import javax.crypto.SealedObject; +import java.util.List; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,32 +18,35 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import com.mercedesbenz.sechub.commons.model.*; +import com.mercedesbenz.sechub.commons.model.SecHubMessage; +import com.mercedesbenz.sechub.commons.model.SecHubMessageType; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareWrapperModule; import com.mercedesbenz.sechub.wrapper.prepare.upload.FileNameSupport; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadException; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; @Service -public class PrepareWrapperModuleGit implements PrepareWrapperModule { +public class GitPrepareWrapperModule extends AbstractPrepareWrapperModule { - private static final Logger LOG = LoggerFactory.getLogger(PrepareWrapperModuleGit.class); + private static final Logger LOG = LoggerFactory.getLogger(GitPrepareWrapperModule.class); @Value("${" + KEY_PDS_PREPARE_AUTO_CLEANUP_GIT_FOLDER + ":true}") - private boolean pdsPrepareAutoCleanupGitFolder; + boolean autoCleanupGitFolder; @Value("${" + KEY_PDS_PREPARE_MODULE_GIT_ENABLED + ":true}") - private boolean pdsPrepareModuleGitEnabled; + boolean enabled; @Autowired - WrapperGit git; + GitWrapper gitWrapper; @Autowired - GitInputValidator gitInputValidator; + GitPrepareInputValidator gitPrepareInputValidator; @Autowired PrepareWrapperUploadService uploadService; @@ -57,25 +57,29 @@ public class PrepareWrapperModuleGit implements PrepareWrapperModule { @Autowired PDSLogSanitizer pdsLogSanitizer; - public boolean prepare(PrepareWrapperContext context) throws IOException { + @Override + public boolean isEnabled() { + return enabled; + } - if (!pdsPrepareModuleGitEnabled) { - LOG.debug("Git module is disabled."); - return false; - } + @Override + public boolean isResponsibleToPrepare(PrepareWrapperContext context) { + return gitPrepareInputValidator.isAccepting(context); + } - try { - gitInputValidator.validate(context); - } catch (PrepareWrapperInputValidatorException e) { - LOG.warn("Module {} could not resolve remote configuration.", getClass().getSimpleName(), e); - return false; - } + @Override + public String getUserMessageForPreparationDone() { + return "Git repository fetched remote"; + } + + protected void prepareImpl(PrepareWrapperContext context) throws IOException { + gitPrepareInputValidator.validate(context); LOG.debug("Module {} resolved remote configuration and will prepare.", getClass().getSimpleName()); SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); GitContext gitContext = initializeGitContext(context, secHubRemoteDataConfiguration); - createDownloadDirectory(gitContext.getToolDownloadDirectory()); + ensureDirectoryExists(gitContext.getToolDownloadDirectory()); SecHubMessage message = new SecHubMessage(SecHubMessageType.INFO, "Preparing git repository."); context.getUserMessages().add(message); @@ -90,17 +94,15 @@ public boolean prepare(PrepareWrapperContext context) throws IOException { LOG.error("Upload of git repository to shared storage failed.", e); throw new PrepareWrapperUploadException("Upload of git repository failed.", e, GIT_REPOSITORY_UPLOAD_FAILED); } - - return true; } private GitContext initializeGitContext(PrepareWrapperContext context, SecHubRemoteDataConfiguration secHubRemoteDataConfiguration) { Path workingDirectory = Paths.get(context.getEnvironment().getPdsJobWorkspaceLocation()); GitContext gitContext = new GitContext(); - gitContext.setCloneWithoutHistory(pdsPrepareAutoCleanupGitFolder); + gitContext.setCloneWithoutHistory(autoCleanupGitFolder); gitContext.setLocation(secHubRemoteDataConfiguration.getLocation()); - gitContext.setupRequiredToolDirectories(workingDirectory); + gitContext.init(workingDirectory); return gitContext; } @@ -138,7 +140,7 @@ private void prepareRemoteConfiguration(GitContext gitContext, SecHubRemoteDataC Optional credentials = secHubRemoteDataConfiguration.getCredentials(); if (credentials.isEmpty()) { - git.downloadRemoteData(gitContext); + gitWrapper.downloadRemoteData(gitContext); return; } @@ -149,20 +151,15 @@ private void prepareRemoteConfiguration(GitContext gitContext, SecHubRemoteDataC } SecHubRemoteCredentialUserData user = optUser.get(); - clonePrivateRepository(gitContext, user); - } - - private void clonePrivateRepository(GitContext gitContext, SecHubRemoteCredentialUserData user) { - HashMap credentialMap = new HashMap<>(); - addSealedUserCredentials(user, credentialMap); + gitContext.setSealedCredentials(user); - gitContext.setCredentialMap(credentialMap); - git.downloadRemoteData(gitContext); + gitWrapper.downloadRemoteData(gitContext); } private void cleanup(GitContext gitContext) throws IOException { - if (pdsPrepareAutoCleanupGitFolder) { - git.cleanUploadDirectory(gitContext.getToolDownloadDirectory()); + if (autoCleanupGitFolder) { + gitWrapper.cleanUploadDirectory(gitContext.getToolDownloadDirectory()); } } + } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGit.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapper.java similarity index 88% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGit.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapper.java index 9f5c867d0..7ce3cf3d2 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGit.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapper.java @@ -6,19 +6,15 @@ import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.mercedesbenz.sechub.commons.pds.PDSProcessAdapterFactory; import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; -import com.mercedesbenz.sechub.wrapper.prepare.modules.WrapperTool; +import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolWrapper; @Component -public class WrapperGit extends WrapperTool { - - private static final Logger LOG = LoggerFactory.getLogger(WrapperGit.class); +public class GitWrapper extends ToolWrapper { @Autowired JGitAdapter jGitAdapter; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/JGitAdapter.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/JGitAdapter.java index ad396fa8a..ba2eadf12 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/JGitAdapter.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/JGitAdapter.java @@ -1,16 +1,10 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.git; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_PASSWORD; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_USERNAME; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.GIT_CLONING_FAILED; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.LOCATION_URL_NOT_VALID_URL; +import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; import java.nio.file.Path; import java.util.List; -import java.util.Map; - -import javax.crypto.SealedObject; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; @@ -21,9 +15,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; @Component public class JGitAdapter { @@ -36,7 +29,6 @@ public class JGitAdapter { public void clone(GitContext gitContext) { String location = transformLocationToURL(gitContext.getLocation()); Path downloadDirectory = gitContext.getToolDownloadDirectory(); - Map credentialMap = gitContext.getCredentialMap(); Path repository = Path.of(gitContext.getRepositoryName()); @@ -46,8 +38,9 @@ public void clone(GitContext gitContext) { setDirectory(downloadDirectory.resolve(repository).toFile()); /* @formatter:on */ - String username = getUserNameFromMap(credentialMap); - String password = getPasswordFromMap(credentialMap); + String username = gitContext.getUnsealedUsername(); + String password = gitContext.getUnsealedPassword(); + if (username != null && password != null) { LOG.debug("Cloning private repository: {} with username and password to: {} ", pdsLogSanitizer.sanitize(location, 1024), downloadDirectory); command = command.setCredentialsProvider(new UsernamePasswordCredentialsProvider(username, password)); @@ -67,14 +60,6 @@ public void clone(GitContext gitContext) { } } - private String getUserNameFromMap(Map credentialMap) { - return CryptoAccess.CRYPTO_STRING.unseal(credentialMap.get(PDS_PREPARE_CREDENTIAL_USERNAME)); - } - - private String getPasswordFromMap(Map credentialMap) { - return CryptoAccess.CRYPTO_STRING.unseal(credentialMap.get(PDS_PREPARE_CREDENTIAL_PASSWORD)); - } - private String transformLocationToURL(String location) { if (location.startsWith("https://")) { diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoContext.java index 4db09b2f5..536a13d5b 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoContext.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoContext.java @@ -4,31 +4,28 @@ import java.io.File; import java.nio.file.Path; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; -public class SkopeoContext extends ToolContext { +public class SkopeoContext extends AbstractPrepareToolContext { - static final String DOWNLOAD_DIRECTORY_NAME = "skopeo-download"; - private File downloadTarFilename = new File("skopeo-download.tar"); + private File downloadTarFilename; + private Path skopeoDownloadDirectory; @Override - public void setupRequiredToolDirectories(Path workingDirectory) { - super.setupRequiredToolDirectories(workingDirectory); - toolDownloadDirectory = workingDirectory.resolve(DOWNLOAD_DIRECTORY_NAME); - } + public void init(Path workingDirectory) { + super.init(workingDirectory); - public void setDownloadTarFilename(File downloadTarFilename) { - if (downloadTarFilename == null) { - throw new IllegalArgumentException("Download filename may not be null."); - } - if (!downloadTarFilename.getName().endsWith(".tar")) { - throw new IllegalArgumentException("Download filename must end with .tar."); - } - this.downloadTarFilename = downloadTarFilename; + skopeoDownloadDirectory = workingDirectory.resolve(SkopeoWrapperConstants.DOWNLOAD_DIRECTORY_NAME); + downloadTarFilename = skopeoDownloadDirectory.resolve(SkopeoWrapperConstants.DOWNLOAD_FILENAME).toFile(); } - public File getDownloadTarFilename() { + public File getDownloadTarFile() { return downloadTarFilename; } + @Override + public Path getToolDownloadDirectory() { + return skopeoDownloadDirectory; + } + } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidator.java deleted file mode 100644 index 76fc47c18..000000000 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidator.java +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; - -import java.util.regex.Pattern; - -import org.springframework.stereotype.Component; - -import com.mercedesbenz.sechub.commons.model.*; -import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractInputValidator; - -@Component -public class SkopeoInputValidator extends AbstractInputValidator { - - public static final String TYPE = "docker"; - private static final String SKOPEO_LOCATION_REGEX = "((docker://|https://)?([a-zA-Z0-9-_.].[a-zA-Z0-9-_.]/)?[a-zA-Z0-9-_.]+(:[a-zA-Z0-9-_.]+)?(/)?)+(@sha256:[a-f0-9]{64})?"; - private static final Pattern SKOPEO_LOCATION_PATTERN = Pattern.compile(SKOPEO_LOCATION_REGEX); - private static final String SKOPEO_USERNAME_REGEX = "^[a-zA-Z0-9-_\\d](?:[a-zA-Z0-9-_\\d]|(?=[a-zA-Z0-9-_\\d])){0,38}$"; - private static final Pattern SKOPEO_USERNAME_PATTERN = Pattern.compile(SKOPEO_USERNAME_REGEX); - private static final String SKOPEO_PASSWORD_REGEX = "^[a-zA-Z0-9-_\\d]{0,80}$"; - private static final Pattern SKOPEO_PASSWORD_PATTERN = Pattern.compile(SKOPEO_PASSWORD_REGEX); - - public SkopeoInputValidator() { - super(TYPE, SKOPEO_LOCATION_PATTERN, SKOPEO_USERNAME_PATTERN, SKOPEO_PASSWORD_PATTERN); - } - -} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareInputValidator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareInputValidator.java new file mode 100644 index 000000000..7004bfbd6 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareInputValidator.java @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; + +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; +import com.mercedesbenz.sechub.wrapper.prepare.LogSanitizerProvider; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareAcceptFilter; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareInputValidationSupport; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareInputValidator; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; + +@Component +public class SkopeoPrepareInputValidator implements PrepareInputValidator, LogSanitizerProvider, PrepareAcceptFilter { + + public static final String TYPE = "docker"; + private static final String SKOPEO_LOCATION_REGEX = "((docker://|https://)?([a-zA-Z0-9-_.].[a-zA-Z0-9-_.]/)?[a-zA-Z0-9-_.]+(:[a-zA-Z0-9-_.]+)?(/)?)+(@sha256:[a-f0-9]{64})?"; + private static final Pattern SKOPEO_LOCATION_PATTERN = Pattern.compile(SKOPEO_LOCATION_REGEX); + private static final String SKOPEO_USERNAME_REGEX = "^[a-zA-Z0-9-_\\d](?:[a-zA-Z0-9-_\\d]|(?=[a-zA-Z0-9-_\\d])){0,38}$"; + private static final Pattern SKOPEO_USERNAME_PATTERN = Pattern.compile(SKOPEO_USERNAME_REGEX); + private static final String SKOPEO_PASSWORD_REGEX = "^[a-zA-Z0-9-_\\d]{0,80}$"; + private static final Pattern SKOPEO_PASSWORD_PATTERN = Pattern.compile(SKOPEO_PASSWORD_REGEX); + + PrepareInputValidationSupport support; + + @Autowired + PDSLogSanitizer logSanitizer; + + public SkopeoPrepareInputValidator() { + /* @formatter:off */ + this.support = PrepareInputValidationSupport.builder(). + setType(TYPE). + setLogSanitizerProvider(this). + setLocationPattern(SKOPEO_LOCATION_PATTERN). + setUserNamePattern(SKOPEO_USERNAME_PATTERN). + setPasswordPattern(SKOPEO_PASSWORD_PATTERN). + build(); + /* @formatter:on */ + } + + @Override + public void validate(PrepareWrapperContext context) throws PrepareWrapperInputValidatorException { + support.validate(context); + } + + @Override + public PDSLogSanitizer getLogSanitizer() { + return logSanitizer; + } + + @Override + public boolean isAccepting(PrepareWrapperContext context) { + return support.isAccepting(context); + } +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeo.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModule.java similarity index 64% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeo.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModule.java index dffb5b6c6..1be75587c 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeo.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModule.java @@ -1,49 +1,46 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.KEY_PDS_PREPARE_MODULE_SKOPEO_ENABLED; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.CREDENTIALS_NOT_DEFINED; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.DOWNLOAD_NOT_SUCCESSFUL; -import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.SKOPEO_BINARY_UPLOAD_FAILED; +import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.*; +import static com.mercedesbenz.sechub.wrapper.prepare.modules.UsageExceptionExitCode.*; +import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.*; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; import java.util.List; import java.util.Optional; -import javax.crypto.SealedObject; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import com.mercedesbenz.sechub.commons.model.*; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareWrapperModule; import com.mercedesbenz.sechub.wrapper.prepare.upload.FileNameSupport; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadException; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; @Service -public class PrepareWrapperModuleSkopeo implements PrepareWrapperModule { +public class SkopeoPrepareWrapperModule extends AbstractPrepareWrapperModule { - private static final Logger LOG = LoggerFactory.getLogger(PrepareWrapperModuleSkopeo.class); + private static final Logger LOG = LoggerFactory.getLogger(SkopeoPrepareWrapperModule.class); @Value("${" + KEY_PDS_PREPARE_MODULE_SKOPEO_ENABLED + ":true}") - private boolean pdsPrepareModuleSkopeoEnabled; + boolean enabled; @Autowired - SkopeoInputValidator skopeoInputValidator; + SkopeoPrepareInputValidator inputValidator; @Autowired - WrapperSkopeo skopeo; + SkopeoWrapper skopeoWrapper; @Autowired FileNameSupport filesSupport; @@ -55,24 +52,29 @@ public class PrepareWrapperModuleSkopeo implements PrepareWrapperModule { PDSLogSanitizer pdsLogSanitizer; @Override - public boolean prepare(PrepareWrapperContext context) throws IOException { + public boolean isEnabled() { + return enabled; + } - if (!pdsPrepareModuleSkopeoEnabled) { - LOG.debug("Skopeo module is disabled."); - return false; - } + @Override + public boolean isResponsibleToPrepare(PrepareWrapperContext context) { + return inputValidator.isAccepting(context); + } - try { - skopeoInputValidator.validate(context); - } catch (PrepareWrapperInputValidatorException e) { - LOG.warn("Module {} could not resolve remote configuration.", getClass().getSimpleName(), e); - return false; - } + @Override + public String getUserMessageForPreparationDone() { + return "Docker image fetched remote"; + } + + @Override + protected void prepareImpl(PrepareWrapperContext context) throws IOException { + + inputValidator.validate(context); LOG.debug("Module {} resolved remote configuration and will prepare.", getClass().getSimpleName()); SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); SkopeoContext skopeoContext = initializeSkopeoContext(context, secHubRemoteDataConfiguration); - createDownloadDirectory(skopeoContext.getToolDownloadDirectory()); + ensureDirectoryExists(skopeoContext.getToolDownloadDirectory()); prepareRemoteConfiguration(skopeoContext, secHubRemoteDataConfiguration); if (!isDownloadSuccessful(skopeoContext)) { @@ -87,7 +89,6 @@ public boolean prepare(PrepareWrapperContext context) throws IOException { LOG.error("Upload of docker image failed.", e); throw new PrepareWrapperUploadException("Upload of docker image failed.", e, SKOPEO_BINARY_UPLOAD_FAILED); } - return true; } protected boolean isDownloadSuccessful(SkopeoContext skopeoContext) { @@ -103,13 +104,13 @@ private SkopeoContext initializeSkopeoContext(PrepareWrapperContext context, Sec SkopeoContext skopeoContext = new SkopeoContext(); skopeoContext.setLocation(secHubRemoteDataConfiguration.getLocation()); - skopeoContext.setupRequiredToolDirectories(workingDirectory); + skopeoContext.init(workingDirectory); return skopeoContext; } private void cleanup(SkopeoContext skopeoContext) throws IOException { - skopeo.cleanUploadDirectory(skopeoContext.getToolDownloadDirectory()); + skopeoWrapper.cleanUploadDirectory(skopeoContext.getToolDownloadDirectory()); } private void prepareRemoteConfiguration(SkopeoContext skopeoContext, SecHubRemoteDataConfiguration secHubRemoteDataConfiguration) throws IOException { @@ -124,16 +125,10 @@ private void prepareRemoteConfiguration(SkopeoContext skopeoContext, SecHubRemot } SecHubRemoteCredentialUserData user = optUser.get(); - addCredentialsToContext(skopeoContext, user); + skopeoContext.setSealedCredentials(user); } - skopeo.download(skopeoContext); + skopeoWrapper.download(skopeoContext); } - private void addCredentialsToContext(SkopeoContext skopeoContext, SecHubRemoteCredentialUserData user) { - HashMap credentialMap = new HashMap<>(); - addSealedUserCredentials(user, credentialMap); - - skopeoContext.setCredentialMap(credentialMap); - } } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeo.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapper.java similarity index 86% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeo.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapper.java index 9f2417a1e..c29c6c271 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeo.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapper.java @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.*; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.KEY_PDS_PREPARE_AUTHENTICATION_FILE_SKOPEO; +import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperKeyConstants.*; import java.io.File; import java.io.IOException; @@ -14,22 +13,23 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; import com.mercedesbenz.sechub.commons.pds.PDSProcessAdapterFactory; import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; -import com.mercedesbenz.sechub.wrapper.prepare.modules.WrapperTool; +import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolWrapper; @Component -public class WrapperSkopeo extends WrapperTool { +public class SkopeoWrapper extends ToolWrapper { - @Value("${" + KEY_PDS_PREPARE_AUTHENTICATION_FILE_SKOPEO + ":authentication.json}") - String pdsPrepareAuthenticationFileSkopeo; + private static final String AUTHENTICATION_DEFAULT_FILENAME = "authentication.json"; + + @Value("${" + KEY_PDS_PREPARE_AUTHENTICATION_FILE_SKOPEO + ":" + AUTHENTICATION_DEFAULT_FILENAME + "}") + String pdsPrepareAuthenticationFileSkopeo = AUTHENTICATION_DEFAULT_FILENAME;// when not initialized by spring @Autowired PDSProcessAdapterFactory processAdapterFactory; public void download(SkopeoContext context) throws IOException { - if (!context.getCredentialMap().isEmpty()) { + if (context.hasCredentials()) { login(context); } @@ -82,9 +82,9 @@ private ProcessBuilder buildProcessLogin(SkopeoContext context) { commands.add("login"); commands.add(location); commands.add("--username"); - commands.add(CryptoAccess.CRYPTO_STRING.unseal(context.getCredentialMap().get(PDS_PREPARE_CREDENTIAL_USERNAME))); + commands.add(context.getUnsealedUsername()); commands.add("--password"); - commands.add(CryptoAccess.CRYPTO_STRING.unseal(context.getCredentialMap().get(PDS_PREPARE_CREDENTIAL_PASSWORD))); + commands.add(context.getUnsealedPassword()); commands.add("--authfile"); commands.add(pdsPrepareAuthenticationFileSkopeo); @@ -104,8 +104,8 @@ private ProcessBuilder buildProcessDownload(SkopeoContext context) { commands.add("skopeo"); commands.add("copy"); commands.add(location); - commands.add("docker-archive:" + context.getDownloadTarFilename()); - if (!context.getCredentialMap().isEmpty()) { + commands.add("docker-archive:" + context.getDownloadTarFile()); + if (context.hasCredentials()) { commands.add("--authfile"); commands.add(pdsPrepareAuthenticationFileSkopeo); } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperConstants.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperConstants.java new file mode 100644 index 000000000..027c5e882 --- /dev/null +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperConstants.java @@ -0,0 +1,8 @@ +package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; + +public class SkopeoWrapperConstants { + + public static final String DOWNLOAD_DIRECTORY_NAME = "skopeo-download"; + + public static final String DOWNLOAD_FILENAME = "skopeo-download.tar"; +} diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestContext.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestContext.java index 2cfb6241c..1ab73f570 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestContext.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestContext.java @@ -2,15 +2,16 @@ import java.nio.file.Path; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; -public class IntegrationTestContext extends ToolContext { +public class IntegrationTestContext extends AbstractPrepareToolContext { static final String DOWNLOAD_DIRECTORY_NAME = "integration-test-download"; private String repositoryName = "integration-test-repository"; + private Path toolDownloadDirectory; @Override - public void setupRequiredToolDirectories(Path workingDirectory) { - super.setupRequiredToolDirectories(workingDirectory); + public void init(Path workingDirectory) { + super.init(workingDirectory); toolDownloadDirectory = workingDirectory.resolve(DOWNLOAD_DIRECTORY_NAME); } @@ -18,4 +19,9 @@ public String getRepositoryName() { return repositoryName; } + @Override + public Path getToolDownloadDirectory() { + return toolDownloadDirectory; + } + } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestModule.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestPrepareWrapperModule.java similarity index 69% rename from sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestModule.java rename to sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestPrepareWrapperModule.java index cc9b3c67f..ae0a7448b 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestModule.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/modules/test/IntegrationTestPrepareWrapperModule.java @@ -11,27 +11,56 @@ import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSProfiles; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareWrapperModule; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; @Service @Profile(PDSProfiles.INTEGRATIONTEST) -public class IntegrationTestModule implements PrepareWrapperModule { +/** + * Special integration test prepare wrapper module. Is always active in profile + * integration test but only responsible for a defined type "test" + * + * @author Albert Tregnaghi + * + */ +public class IntegrationTestPrepareWrapperModule extends AbstractPrepareWrapperModule { @Autowired PrepareWrapperUploadService uploadService; - public boolean prepare(PrepareWrapperContext context) throws IOException { + @Override + public boolean isEnabled() { + return true; + } + + @Override + public boolean isResponsibleToPrepare(PrepareWrapperContext context) { + SecHubRemoteDataConfiguration config = context.getRemoteDataConfiguration(); + if (config == null) { + return false; + } + String type = config.getType(); + if (type == null) { + return false; + } + return type.equals("test"); + } + + @Override + public String getUserMessageForPreparationDone() { + return "Integration test preparation done"; + } + + protected void prepareImpl(PrepareWrapperContext context) throws IOException { SecHubRemoteDataConfiguration secHubRemoteDataConfiguration = context.getRemoteDataConfiguration(); IntegrationTestContext integrationTestContext = initializeIntegrationTestContext(context, secHubRemoteDataConfiguration); - createDownloadDirectory(integrationTestContext.getToolDownloadDirectory()); + ensureDirectoryExists(integrationTestContext.getToolDownloadDirectory()); prepareRemoteConfiguration(integrationTestContext, secHubRemoteDataConfiguration); uploadService.upload(context, integrationTestContext); - return true; } private IntegrationTestContext initializeIntegrationTestContext(PrepareWrapperContext context, @@ -40,7 +69,7 @@ private IntegrationTestContext initializeIntegrationTestContext(PrepareWrapperCo IntegrationTestContext integrationTestContext = new IntegrationTestContext(); integrationTestContext.setLocation(secHubRemoteDataConfiguration.getLocation()); - integrationTestContext.setupRequiredToolDirectories(workingDirectory); + integrationTestContext.init(workingDirectory); return integrationTestContext; } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/FileNameSupport.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/FileNameSupport.java index e111628ee..2b1b11be2 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/FileNameSupport.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/FileNameSupport.java @@ -3,7 +3,8 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.List; import org.springframework.stereotype.Component; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreator.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreator.java index 6571f9380..59d115b3c 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreator.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreator.java @@ -7,8 +7,8 @@ import com.mercedesbenz.sechub.commons.archive.ArchiveSupport; import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; @Service public class PrepareWrapperArchiveCreator { @@ -19,13 +19,13 @@ public class PrepareWrapperArchiveCreator { @Autowired PrepareWrapperSechubConfigurationSupport sechubConfigurationSupport; - public void create(PrepareWrapperContext context, ToolContext toolContext) throws IOException { - // replace remote with filesystem entry in configuration model, this + public void create(PrepareWrapperContext context, PrepareToolContext abstractToolContext) throws IOException { + // replace remote with file system entry in configuration model, this // is necessary for doing the upload by archive support which uses // the file system information - SecHubConfigurationModel model = sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel model = sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, abstractToolContext); - archiveSupport.createArchives(model, toolContext.getToolDownloadDirectory(), toolContext.getUploadDirectory()); + archiveSupport.createArchives(model, abstractToolContext.getToolDownloadDirectory(), abstractToolContext.getUploadDirectory()); } } diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadService.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadService.java index 784de734b..b2badb7be 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadService.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadService.java @@ -1,7 +1,7 @@ package com.mercedesbenz.sechub.wrapper.prepare.upload; import static com.mercedesbenz.sechub.commons.core.CommonConstants.*; -import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.UNABLE_TO_STORE_FILE; +import static com.mercedesbenz.sechub.wrapper.prepare.upload.UploadExceptionExitCode.*; import java.io.File; import java.io.FileInputStream; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupport.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupport.java index b0d19e58c..562d9d48d 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupport.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupport.java @@ -10,8 +10,8 @@ import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.commons.model.SecHubFileSystemConfiguration; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; @Component public class PrepareWrapperSechubConfigurationSupport { @@ -21,7 +21,7 @@ public class PrepareWrapperSechubConfigurationSupport { private static Logger LOG = LoggerFactory.getLogger(PrepareWrapperSechubConfigurationSupport.class); - public SecHubConfigurationModel replaceRemoteDataWithFilesystem(PrepareWrapperContext context, ToolContext toolContext) { + public SecHubConfigurationModel replaceRemoteDataWithFilesystem(PrepareWrapperContext context, PrepareToolContext toolContext) { SecHubConfigurationModel modifiedModel = context.getSecHubConfiguration(); if (modifiedModel == null) { @@ -44,8 +44,8 @@ public SecHubConfigurationModel replaceRemoteDataWithFilesystem(PrepareWrapperCo return modifiedModel; } - private SecHubConfigurationModel replaceRemoteBinariesWithFileSystem(ToolContext toolContext, SecHubConfigurationModel modifiedModel) { - List tarFiles = fileNameSupport.getTarFilesFromDirectory(toolContext.getToolDownloadDirectory()); + private SecHubConfigurationModel replaceRemoteBinariesWithFileSystem(PrepareToolContext context, SecHubConfigurationModel modifiedModel) { + List tarFiles = fileNameSupport.getTarFilesFromDirectory(context.getToolDownloadDirectory()); SecHubFileSystemConfiguration fileSystemConfiguration = new SecHubFileSystemConfiguration(); for (Path tarFile : tarFiles) { @@ -60,7 +60,7 @@ private SecHubConfigurationModel replaceRemoteBinariesWithFileSystem(ToolContext return modifiedModel; } - private SecHubConfigurationModel replaceRemoteSourcesWithFileSystem(ToolContext context, SecHubConfigurationModel modifiedModel) { + private SecHubConfigurationModel replaceRemoteSourcesWithFileSystem(PrepareToolContext context, SecHubConfigurationModel modifiedModel) { List repositories = fileNameSupport.getRepositoriesFromDirectory(context.getToolDownloadDirectory()); SecHubFileSystemConfiguration fileSystemConfiguration = new SecHubFileSystemConfiguration(); diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSharedVolumePropertiesSetup.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSharedVolumePropertiesSetup.java index 419d0072e..5bf8cc081 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSharedVolumePropertiesSetup.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSharedVolumePropertiesSetup.java @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.upload; -import static com.mercedesbenz.sechub.pds.commons.core.config.PDSStorageConstants.PDS_STORAGE_SHAREDVOLUME_UPLOAD_DIR; +import static com.mercedesbenz.sechub.pds.commons.core.config.PDSStorageConstants.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperStorageService.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperStorageService.java index 14a877770..8f1a47e66 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperStorageService.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperStorageService.java @@ -5,7 +5,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.mercedesbenz.sechub.storage.core.*; +import com.mercedesbenz.sechub.storage.core.JobStorage; +import com.mercedesbenz.sechub.storage.core.JobStorageFactory; +import com.mercedesbenz.sechub.storage.core.S3Setup; +import com.mercedesbenz.sechub.storage.core.SharedVolumeSetup; +import com.mercedesbenz.sechub.storage.core.StorageService; import com.mercedesbenz.sechub.storage.s3.AwsS3JobStorageFactory; import com.mercedesbenz.sechub.storage.sharevolume.spring.SharedVolumeJobStorageFactory; diff --git a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadService.java b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadService.java index fd3742a82..0c4e740b0 100644 --- a/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadService.java +++ b/sechub-wrapper-prepare/src/main/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadService.java @@ -1,7 +1,6 @@ package com.mercedesbenz.sechub.wrapper.prepare.upload; -import static com.mercedesbenz.sechub.commons.core.CommonConstants.FILENAME_BINARIES_TAR; -import static com.mercedesbenz.sechub.commons.core.CommonConstants.FILENAME_SOURCECODE_ZIP; +import static com.mercedesbenz.sechub.commons.core.CommonConstants.*; import java.io.File; import java.io.IOException; @@ -13,8 +12,8 @@ import com.mercedesbenz.sechub.commons.core.security.CheckSumSupport; import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.commons.model.SecHubDataConfiguration; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; @Service public class PrepareWrapperUploadService { @@ -34,15 +33,15 @@ public class PrepareWrapperUploadService { @Autowired CheckSumSupport checkSumSupport; - public void upload(PrepareWrapperContext context, ToolContext toolContext) throws IOException { + public void upload(PrepareWrapperContext context, PrepareToolContext abstractToolContext) throws IOException { // creates archives for sourcecode or binary file - archiveCreator.create(context, toolContext); + archiveCreator.create(context, abstractToolContext); String projectId = context.getSecHubConfiguration().getProjectId(); UUID sechubJobUUID = UUID.fromString(context.getEnvironment().getSechubJobUUID()); - SecHubConfigurationModel model = sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel model = sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, abstractToolContext); if (model.getData().isEmpty()) { throw new IllegalStateException("SecHubConfigurationModel data is not configured."); @@ -51,14 +50,14 @@ public void upload(PrepareWrapperContext context, ToolContext toolContext) throw SecHubDataConfiguration data = model.getData().get(); if (!data.getSources().isEmpty()) { - File file = new File(toolContext.getUploadDirectory() + File.separator + FILENAME_SOURCECODE_ZIP); + File file = new File(abstractToolContext.getUploadDirectory() + File.separator + FILENAME_SOURCECODE_ZIP); String checkSum = checkSumSupport.createSha256Checksum(file.getPath()); fileUploadService.uploadFile(projectId, sechubJobUUID, file, checkSum); } if (!data.getBinaries().isEmpty()) { - File file = new File(toolContext.getUploadDirectory() + File.separator + FILENAME_BINARIES_TAR); + File file = new File(abstractToolContext.getUploadDirectory() + File.separator + FILENAME_BINARIES_TAR); String checkSum = checkSumSupport.createSha256Checksum(file.getPath()); fileUploadService.uploadFile(projectId, sechubJobUUID, file, checkSum); diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperApplicationSpringBootTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperApplicationSpringBootTest.java index c1122d93d..c5e2aab84 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperApplicationSpringBootTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperApplicationSpringBootTest.java @@ -1,50 +1,115 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; import java.io.IOException; +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.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mercedesbenz.sechub.adapter.AdapterExecutionResult; import com.mercedesbenz.sechub.commons.archive.ArchiveSupport; +import com.mercedesbenz.sechub.test.TestUtil; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.factory.PrepareWrapperPDSUserMessageSupportPojoFactory; -import com.mercedesbenz.sechub.wrapper.prepare.factory.PrepareWrapperPojoFactory; -import com.mercedesbenz.sechub.wrapper.prepare.modules.*; -import com.mercedesbenz.sechub.wrapper.prepare.modules.git.GitInputValidator; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; +import com.mercedesbenz.sechub.wrapper.prepare.modules.git.GitPrepareInputValidator; +import com.mercedesbenz.sechub.wrapper.prepare.modules.git.GitPrepareWrapperModule; +import com.mercedesbenz.sechub.wrapper.prepare.modules.git.GitWrapper; import com.mercedesbenz.sechub.wrapper.prepare.modules.git.JGitAdapter; -import com.mercedesbenz.sechub.wrapper.prepare.modules.git.PrepareWrapperModuleGit; -import com.mercedesbenz.sechub.wrapper.prepare.modules.git.WrapperGit; -import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.PrepareWrapperModuleSkopeo; -import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.SkopeoInputValidator; -import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.WrapperSkopeo; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContextFactory; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperPreparationService; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperRemoteConfigurationExtractor; -import com.mercedesbenz.sechub.wrapper.prepare.upload.*; - -@SpringBootTest(classes = { PrepareWrapperContextFactory.class, PrepareWrapperPreparationService.class, PrepareWrapperPojoFactory.class, - PrepareWrapperEnvironment.class, PrepareWrapperPDSUserMessageSupportPojoFactory.class, PrepareWrapperRemoteConfigurationExtractor.class, - PrepareWrapperModuleGit.class, PrepareWrapperModule.class, WrapperGit.class, GitInputValidator.class, JGitAdapter.class, - PrepareWrapperModuleSkopeo.class, WrapperSkopeo.class, SkopeoInputValidator.class, PrepareWrapperStorageService.class, - PrepareWrapperUploadService.class, PrepareWrapperFileUploadService.class, PrepareWrapperSechubConfigurationSupport.class, FileNameSupport.class, - PrepareWrapperArchiveCreator.class, ArchiveSupport.class, PrepareWrapperSharedVolumePropertiesSetup.class, PrepareWrapperS3PropertiesSetup.class }) +import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.SkopeoPrepareInputValidator; +import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.SkopeoPrepareWrapperModule; +import com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo.SkopeoWrapper; +import com.mercedesbenz.sechub.wrapper.prepare.upload.FileNameSupport; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperArchiveCreator; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperFileUploadService; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperS3PropertiesSetup; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperSechubConfigurationSupport; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperSharedVolumePropertiesSetup; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperStorageService; +import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; + +/* @formatter:off */ +@SpringBootTest(classes = { PrepareWrapperContextFactory.class, + PrepareWrapperPreparationService.class, + PrepareWrapperPojoFactory.class, + PrepareWrapperPDSUserMessageSupportFactory.class, + PrepareWrapperRemoteConfigurationExtractor.class, + GitPrepareWrapperModule.class, + PrepareWrapperModule.class, + GitPrepareInputValidator.class, + JGitAdapter.class, + SkopeoPrepareWrapperModule.class, + SkopeoWrapper.class, + SkopeoPrepareInputValidator.class, + PrepareWrapperStorageService.class, + PrepareWrapperUploadService.class, + PrepareWrapperFileUploadService.class, + PrepareWrapperSechubConfigurationSupport.class, + PrepareWrapperArchiveCreator.class, + ArchiveSupport.class, + FileNameSupport.class, + PrepareWrapperSharedVolumePropertiesSetup.class, + PrepareWrapperS3PropertiesSetup.class }) +/* @formatter:on */ @ExtendWith(SpringExtension.class) -@TestPropertySource(locations = "classpath:application-test-fail.properties") +@TestPropertySource(locations = "classpath:init-testdata-prepare-wrapper-spring-boot.properties") class PrepareWrapperApplicationSpringBootTest { @Autowired PrepareWrapperPreparationService preparationService; + @MockBean + PrepareWrapperEnvironment environment; + + @MockBean + GitWrapper gitWrapper; + + private UUID sechubJobUUID; + + @BeforeEach + void beforeEach() throws Exception { + Path testFolder = TestUtil.createTempDirectoryInBuildFolder("prepare-wrapper-sb"); + + sechubJobUUID = UUID.randomUUID(); + when(environment.getSechubJobUUID()).thenReturn(sechubJobUUID.toString()); + when(environment.getPdsUserMessagesFolder()).thenReturn(testFolder.resolve("/messages").toString()); + when(environment.getPdsJobWorkspaceLocation()).thenReturn(testFolder.resolve("workspace").toString()); + } + @Test - void start_preparation_with_remote_test_properties_and_empty_prepare_service_list_fails() throws IOException { + void start_preparation_remote_data_but_cannot_handled__results_in_failed() throws IOException { + /* prepare */ + when(environment.getSechubConfigurationModelAsJson()).thenReturn( + """ + { + "projectId" : "project1", + "data" : { + "binaries" : [ { + "name" : "remote_example_name", + "remote" : { + "location" : "https://not-any.repo/", + "type" : "not-git" + } + } ] + }, + "codeScan" : { + "use" : [ "remote_example_name" ] + } + } + """ + ); + + /* execute */ AdapterExecutionResult result = preparationService.startPreparation(); @@ -54,4 +119,69 @@ void start_preparation_with_remote_test_properties_and_empty_prepare_service_lis assertEquals("No module was able to prepare the defined remote data.", result.getProductMessages().get(0).getText()); } + @Test + void start_preparation_remote_data_handled_by_git_but_location_not_correct_results_in_failed() throws IOException { + /* prepare */ + when(environment.getSechubConfigurationModelAsJson()).thenReturn( + """ + { + "projectId" : "project1", + "data" : { + "binaries" : [ { + "name" : "remote_example_name", + "remote" : { + "location" : "https://not-any.repo/", + "type" : "git" + } + } ] + }, + "codeScan" : { + "use" : [ "remote_example_name" ] + } + } + """ + ); + + + /* execute + test */ + assertThrows(PrepareWrapperInputValidatorException.class, ()-> preparationService.startPreparation()); + + } + + @Test + void start_preparation_remote_data_handled_by_git_and_location_correct_results_in_success() throws IOException { + /* prepare */ + when(environment.getSechubConfigurationModelAsJson()).thenReturn( + """ + { + "projectId" : "project1", + "data" : { + "binaries" : [ { + "name" : "remote_example_name", + "remote" : { + "location" : "https://somewhere.example.com/testrepository.git", + "type" : "git" + } + } ] + }, + "codeScan" : { + "use" : [ "remote_example_name" ] + } + } + """ + ); + + + /* execute + test */ + IllegalStateException exception = assertThrows(IllegalStateException.class, ()-> preparationService.startPreparation()); + + /* test */ + String message = exception.getMessage(); + String expected = "Download of git repository was not successful"; // the mocked git wrapper does not download + if(!message.contains(expected)) { + assertEquals(expected, message); + } + + } + } \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactoryTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactoryTest.java similarity index 94% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactoryTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactoryTest.java index 648c3bf95..c5c0240bc 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperContextFactoryTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperContextFactoryTest.java @@ -1,9 +1,8 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationServiceTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationServiceTest.java new file mode 100644 index 000000000..f66ad2eeb --- /dev/null +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperPreparationServiceTest.java @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.util.ArrayList; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import com.mercedesbenz.sechub.adapter.AdapterExecutionResult; +import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; +import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperModule; + +class PrepareWrapperPreparationServiceTest { + + private PrepareWrapperPreparationService serviceToTest; + private PrepareWrapperContext context; + private PrepareWrapperModule testPrepareWrapperModule1; + private PrepareWrapperModule testPrepareWrapperModule2; + private static boolean NOT_ENABLED = false; + private static boolean ENABLED = true; + + private static boolean NOT_RESPONSIBLE = false; + private static boolean RESPONSIBLE = true; + + @BeforeEach + void beforeEach() { + context = mock(PrepareWrapperContext.class); + PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); + PrepareWrapperContextFactory contextFactory = mock(PrepareWrapperContextFactory.class); + when(contextFactory.create(environment)).thenReturn(context); + + serviceToTest = new PrepareWrapperPreparationService(); + serviceToTest.environment = environment; + serviceToTest.contextFactory = contextFactory; + serviceToTest.modules = new ArrayList<>(); + } + + @Test + void when_no_remote_data_was_configured_and_no_modules_defined_return_preparation_success_with_warn_message() throws IOException { + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); // no remote data configured, nor a module + + /* test */ + assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); + assertEquals(1, result.getProductMessages().size()); + assertEquals("No Remote Configuration found.", result.getProductMessages().get(0).getText()); + } + + @Test + void when_no_remote_data_was_configured_and_module_defined_and_enabled_and_responsible() throws IOException { + /* prepare */ + installModule1(ENABLED, RESPONSIBLE); // but here we have no remote configuration! + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); + assertEquals(1, result.getProductMessages().size()); + assertEquals("No Remote Configuration found.", result.getProductMessages().get(0).getText()); + + // check no interaction with installed module in this case + verify(testPrepareWrapperModule1, never()).isEnabled(); + verify(testPrepareWrapperModule1, never()).isResponsibleToPrepare(context); + verify(testPrepareWrapperModule1, never()).prepare(context); + } + + @Test + void when_remote_data_was_configured_but_no_module_exists_preparation_failes_with_message() throws IOException { + setupValidTestGitRemoteDataConfiguration(); + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + assertEquals("SECHUB_PREPARE_RESULT;status=FAILED", result.getProductResult()); + assertEquals(1, result.getProductMessages().size()); + assertEquals("No module was able to prepare the defined remote data.", result.getProductMessages().get(0).getText()); + } + + @Test + void when_remote_data_was_configured_module_responsible_but_not_enabled_preparation_failes_with_message() throws IOException { + /* prepare */ + installModule1(NOT_ENABLED, RESPONSIBLE); + setupValidTestGitRemoteDataConfiguration(); + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + verify(testPrepareWrapperModule1, never()).prepare(context); // prepare is never called at this module! + assertEquals("SECHUB_PREPARE_RESULT;status=FAILED", result.getProductResult()); + assertEquals(1, result.getProductMessages().size()); + assertEquals("No module was able to prepare the defined remote data.", result.getProductMessages().get(0).getText()); + } + + @Test + void when_remote_data_was_configured_but_module_enabled_but_not_responsible_preparation_failes_with_message() throws IOException { + /* prepare */ + installModule1(ENABLED, NOT_RESPONSIBLE); + setupValidTestGitRemoteDataConfiguration(); + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + verify(testPrepareWrapperModule1, never()).prepare(context); // prepare is never called at this module! + assertEquals("SECHUB_PREPARE_RESULT;status=FAILED", result.getProductResult()); + assertEquals(1, result.getProductMessages().size()); + assertEquals("No module was able to prepare the defined remote data.", result.getProductMessages().get(0).getText()); + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void data_available_two_modules_enabled_and_one_reponsible_calls_module_with_success(boolean firstModuleResponsible) throws IOException { + /* prepare */ + /* prepare */ + installModule1(ENABLED, firstModuleResponsible); + installModule2(ENABLED, !firstModuleResponsible); + setupValidTestGitRemoteDataConfiguration(); + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); + assertEquals(0, result.getProductMessages().size()); + + if (firstModuleResponsible) { + verify(testPrepareWrapperModule1).prepare(context); + verify(testPrepareWrapperModule2, never()).prepare(context); + } else { + verify(testPrepareWrapperModule1, never()).prepare(context); + verify(testPrepareWrapperModule2).prepare(context); + } + } + + @Test + void data_available_one_module_enabled_and_reponsible_calls_module_with_success() throws IOException { + /* prepare */ + /* prepare */ + installModule1(ENABLED, RESPONSIBLE); + setupValidTestGitRemoteDataConfiguration(); + + /* execute */ + AdapterExecutionResult result = serviceToTest.startPreparation(); + + /* test */ + assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); + assertEquals(0, result.getProductMessages().size()); + + verify(testPrepareWrapperModule1).prepare(context); + } + + private void setupValidTestGitRemoteDataConfiguration() { + SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); + remoteDataConfiguration.setLocation("my-example_location"); + remoteDataConfiguration.setType("git"); + when(context.getRemoteDataConfiguration()).thenReturn(remoteDataConfiguration); + } + + private void installModule1(boolean moduleIsEnabled, boolean moduleIsResponsible) { + testPrepareWrapperModule1 = mock(PrepareWrapperModule.class, "mockModule-1"); + serviceToTest.modules.add(testPrepareWrapperModule1); + + when(testPrepareWrapperModule1.isEnabled()).thenReturn(moduleIsEnabled); + when(testPrepareWrapperModule1.isResponsibleToPrepare(context)).thenReturn(moduleIsResponsible); + } + + private void installModule2(boolean moduleIsEnabled, boolean moduleIsResponsible) { + testPrepareWrapperModule2 = mock(PrepareWrapperModule.class, "mockModule-2"); + serviceToTest.modules.add(testPrepareWrapperModule2); + + when(testPrepareWrapperModule2.isEnabled()).thenReturn(moduleIsEnabled); + when(testPrepareWrapperModule2.isResponsibleToPrepare(context)).thenReturn(moduleIsResponsible); + } +} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java similarity index 95% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java index 0703ea7f9..f984aae5f 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperRemoteConfigurationExtractorTest.java @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; +import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.*; import static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeEach; @@ -9,7 +9,6 @@ import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; class PrepareWrapperRemoteConfigurationExtractorTest { diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageServiceTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageServiceTest.java similarity index 96% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageServiceTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageServiceTest.java index 0412712b3..8c0740a01 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperResultStorageServiceTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/PrepareWrapperResultStorageServiceTest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; +package com.mercedesbenz.sechub.wrapper.prepare; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLITest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLITest.java index 7b89abe59..7b25b631d 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLITest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/cli/PrepareWrapperCLITest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.cli; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.IOException; @@ -12,8 +13,8 @@ import com.mercedesbenz.sechub.adapter.AdapterExecutionResult; import com.mercedesbenz.sechub.commons.core.prepare.PrepareResult; import com.mercedesbenz.sechub.commons.core.prepare.PrepareStatus; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperPreparationService; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperResultStorageService; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperPreparationService; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperResultStorageService; class PrepareWrapperCLITest { diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidatorTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidatorTest.java deleted file mode 100644 index 93c5f088b..000000000 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/AbstractInputValidatorTest.java +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules; - -import static org.junit.jupiter.api.Assertions.*; - -import java.util.regex.Pattern; - -import org.junit.jupiter.api.Test; - -class AbstractInputValidatorTest { - - private TestInputValidator validatorToTest; - - @Test - void constructor_throws_exception_when_type_is_null() { - /* prepare */ - Pattern locationPattern = Pattern.compile(".*"); - Pattern usernamePattern = Pattern.compile(".*"); - Pattern passwordPattern = Pattern.compile(".*"); - - /* execute */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - validatorToTest = new TestInputValidator(null, locationPattern, usernamePattern, passwordPattern); - }); - - /* test */ - assertEquals("Type must not be null or empty.", exception.getMessage()); - } - - @Test - void constructor_throws_exception_when_type_is_empty() { - /* prepare */ - Pattern locationPattern = Pattern.compile(".*"); - Pattern usernamePattern = Pattern.compile(".*"); - Pattern passwordPattern = Pattern.compile(".*"); - - /* execute */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - validatorToTest = new TestInputValidator("", locationPattern, usernamePattern, passwordPattern); - }); - - /* test */ - assertEquals("Type must not be null or empty.", exception.getMessage()); - } - - @Test - void constructor_throws_exception_when_locationPattern_is_null() { - /* prepare */ - Pattern usernamePattern = Pattern.compile(".*"); - Pattern passwordPattern = Pattern.compile(".*"); - - /* execute */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - validatorToTest = new TestInputValidator("type", null, usernamePattern, passwordPattern); - }); - - /* test */ - assertEquals("Pattern must not be null.", exception.getMessage()); - } - - @Test - void constructor_throws_exception_when_usernamePattern_is_null() { - /* prepare */ - Pattern locationPattern = Pattern.compile(".*"); - Pattern passwordPattern = Pattern.compile(".*"); - - /* execute */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - validatorToTest = new TestInputValidator("type", locationPattern, null, passwordPattern); - }); - - /* test */ - assertEquals("Pattern must not be null.", exception.getMessage()); - } - - @Test - void constructor_throws_exception_when_passwordPattern_is_null() { - /* prepare */ - Pattern locationPattern = Pattern.compile(".*"); - Pattern usernamePattern = Pattern.compile(".*"); - - /* execute */ - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { - validatorToTest = new TestInputValidator("type", locationPattern, usernamePattern, null); - }); - - /* test */ - assertEquals("Pattern must not be null.", exception.getMessage()); - } - - @Test - void constructor_creates_instance_when_all_parameters_are_valid() { - /* prepare */ - Pattern locationPattern = Pattern.compile(".*"); - Pattern usernamePattern = Pattern.compile(".*"); - Pattern passwordPattern = Pattern.compile(".*"); - - /* execute */ - validatorToTest = new TestInputValidator("type", locationPattern, usernamePattern, passwordPattern); - - /* test */ - assertNotNull(validatorToTest); - } - - private class TestInputValidator extends AbstractInputValidator { - public TestInputValidator(String type, Pattern locationPattern, Pattern usernamePattern, Pattern passwordPattern) { - super(type, locationPattern, usernamePattern, passwordPattern); - } - } - -} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidationSupportTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidationSupportTest.java new file mode 100644 index 000000000..cd3748b50 --- /dev/null +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/InputValidationSupportTest.java @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare.modules; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.regex.Pattern; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; +import com.mercedesbenz.sechub.wrapper.prepare.LogSanitizerProvider; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareInputValidationSupport; + +class InputValidationSupportTest implements LogSanitizerProvider { + + private static final Pattern PATTERN_ACCEPT_ALL = Pattern.compile(".*"); + + private PrepareInputValidationSupport supportToTest; + + private PDSLogSanitizer logSanitizer; + + @BeforeEach + void beforeEach() { + this.logSanitizer = mock(PDSLogSanitizer.class); + } + + @Test + void builder_throws_exception_when_type_is_null() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType(null). + setLogSanitizerProvider(this). + setLocationPattern(locationPattern). + setUserNamePattern(usernamePattern). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Type must not be null or empty.", exception.getMessage()); + } + + @Test + void builder_throws_exception_when_type_is_empty() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType(""). + setLogSanitizerProvider(this). + setLocationPattern(locationPattern). + setUserNamePattern(usernamePattern). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Type must not be null or empty.", exception.getMessage()); + } + + @Test + void builder_throws_exception_when_locationPattern_is_null() { + /* prepare */ + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType("type1"). + setLogSanitizerProvider(this). + setLocationPattern(null). + setUserNamePattern(usernamePattern). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Pattern must not be null.", exception.getMessage()); + } + + @Test + void builder_throws_exception_when_usernamePattern_is_null() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType("type1"). + setLogSanitizerProvider(this). + setLocationPattern(locationPattern). + setUserNamePattern(null). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Pattern must not be null.", exception.getMessage()); + } + + @Test + void builder_throws_exception_when_passwordPattern_is_null() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType("type1"). + setLogSanitizerProvider(this). + setLocationPattern(locationPattern). + setUserNamePattern(usernamePattern). + setPasswordPattern(null). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Pattern must not be null.", exception.getMessage()); + } + + @Test + void builder_creates_instance_when_all_parameters_are_valid() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType("type1"). + setLogSanitizerProvider(this). + setLocationPattern(locationPattern). + setUserNamePattern(usernamePattern). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + + /* test */ + assertNotNull(supportToTest); + } + + @Test + void builder_creates_not_instance_when_log_sanitizer_provider_not_set() { + /* prepare */ + Pattern locationPattern = PATTERN_ACCEPT_ALL; + Pattern usernamePattern = PATTERN_ACCEPT_ALL; + Pattern passwordPattern = PATTERN_ACCEPT_ALL; + + /* execute */ + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + /* @formatter:off */ + supportToTest = PrepareInputValidationSupport.builder(). + setType("type1"). + setLogSanitizerProvider(null). + setLocationPattern(locationPattern). + setUserNamePattern(usernamePattern). + setPasswordPattern(passwordPattern). + build(); + /* @formatter:on */ + }); + + /* test */ + assertEquals("Log sanitizer provider not defined", exception.getMessage()); + } + + @Override + public PDSLogSanitizer getLogSanitizer() { + return logSanitizer; + } + +} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidatorTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidatorTest.java index f916eb142..2ffcd6e9c 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidatorTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitInputValidatorTest.java @@ -1,15 +1,11 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.git; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; -import static com.mercedesbenz.sechub.wrapper.prepare.modules.InputValidatorExitcode.LOCATION_NOT_MATCHING_PATTERN; +import static com.mercedesbenz.sechub.wrapper.prepare.InputValidatorExitcode.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -20,31 +16,40 @@ import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.test.TestFileWriter; -import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; class GitInputValidatorTest { - private GitInputValidator gitInputValidatorToTest; - private TestFileWriter writer; + private static final String VALID_USERNAME = "user1"; + private static final String VALID_PWD = "ghp_123456789012345678901234567890123456"; + private static final String VALID_REPO_URL = "https://my-repo.com.git"; + + private GitPrepareInputValidator gitInputValidatorToTest; + private PrepareWrapperContext context; + private SecHubRemoteDataConfiguration remoteDataConfiguration; @BeforeEach void beforeEach() { - gitInputValidatorToTest = new GitInputValidator(); - writer = new TestFileWriter(); + gitInputValidatorToTest = new GitPrepareInputValidator(); + + gitInputValidatorToTest.logSanitizer = mock(PDSLogSanitizer.class); - gitInputValidatorToTest.pdsLogSanitizer = mock(PDSLogSanitizer.class); + context = mock(PrepareWrapperContext.class); + remoteDataConfiguration = new SecHubRemoteDataConfiguration(); + when(context.getRemoteDataConfiguration()).thenReturn(remoteDataConfiguration); } @ParameterizedTest @ValueSource(strings = { "https://example.com;echoMalicious", "https://example.com.git>text.txt", "https://example.com/some-git-repo.git&&cd.." }) - void validateLocation_throws_exception_when_url_does_contain_forbidden_characters(String repositoryUrl) { + void validate_throws_exception_when_url_does_contain_forbidden_characters(String repositoryUrl) { + + /* prepare */ + initRemoteDataWithOutCredentials(repositoryUrl); + /* execute */ - PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, - () -> gitInputValidatorToTest.validateLocation(repositoryUrl)); + PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> gitInputValidatorToTest.validate(context)); /* test */ assertTrue(exception.getMessage().contains("Defined location URL must not contain forbidden characters: ")); @@ -52,26 +57,35 @@ void validateLocation_throws_exception_when_url_does_contain_forbidden_character @ParameterizedTest @ValueSource(strings = { "https://y-git-host/my-git-user/my-git-repo.git", "https://example.org/some-git-repo.git", "git@gitrepo:my-repo.git" }) - void validateLocation_does_not_throw_exception_when_url_is_valid(String repositoryUrl) { + void validate_does_not_throw_exception_when_url_is_valid_and_no_credentials(String repositoryUrl) { + /* prepare */ + initRemoteDataWithOutCredentials(repositoryUrl); + /* execute + test */ - assertDoesNotThrow(() -> gitInputValidatorToTest.validateLocation(repositoryUrl)); + assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); } @ParameterizedTest - @ValueSource(strings = { "https://my-repo.com.git", "http://my-repo.com.git", "git://host.xz/~user/path/to/repo.git", "git@github.com:my/repo.git", + @ValueSource(strings = { VALID_REPO_URL, "http://my-repo.com.git", "git://host.xz/~user/path/to/repo.git", "git@github.com:my/repo.git", "https://host.xz/path/to/repo.git/", "http://host.xz/path/to/repo.git/", "git://host.xz/path/to/repo.git/", "git@host.com:my-repo/example.git" }) - void validateLocation_does_not_throw_exception_when_git_pattern_is_configured(String location) { + void validate_does_not_throw_exception_when_git_pattern_is_configured_and_no_credentials(String repositoryUrl) { + /* prepare */ + initRemoteDataWithOutCredentials(repositoryUrl); + remoteDataConfiguration.setType("git"); + /* execute + test */ - assertDoesNotThrow(() -> gitInputValidatorToTest.validateLocation(location)); + assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "https://my-repo.com.notAgit_repo", "http://my-repo.com.git./bin/bash", "git://host.xz/~user/path/to/repo.gitsomeevalexecution", "git@github.com:my/repo.git\nexecuteMalicious" }) - void validateLocation_throws_exception_when_invalid_git_location_is_configured(String location) { + void validate_throws_exception_when_invalid_git_location_is_configured(String repositoryUrl) { + /* prepare */ + initRemoteDataWithOutCredentials(repositoryUrl); + /* execute */ - PrepareWrapperInputValidatorException e = assertThrows(PrepareWrapperInputValidatorException.class, - () -> gitInputValidatorToTest.validateLocation(location)); + PrepareWrapperInputValidatorException e = assertThrows(PrepareWrapperInputValidatorException.class, () -> gitInputValidatorToTest.validate(context)); /* test */ assertEquals(LOCATION_NOT_MATCHING_PATTERN, e.getExitCode()); @@ -79,48 +93,55 @@ void validateLocation_throws_exception_when_invalid_git_location_is_configured(S @ParameterizedTest @ValueSource(strings = { "user", "user-name", "user_name", "user-name-123", "user-name-123-456", "user-name_23" }) - void validateUsername_does_not_throw_exception_when_username_is_valid(String username) { + void validate_does_not_throw_exception_when_username_is_valid(String username) { + /* prepare */ + initRemoteDataWithCredentials(VALID_REPO_URL, username, VALID_PWD); + /* execute + test */ - assertDoesNotThrow(() -> gitInputValidatorToTest.validateUsername(username)); + assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "user name", "user name 123", "./bin/bash" }) - void validateUsername_throws_exception_when_username_is_invalid(String username) { + void validate_throws_exception_when_username_is_invalid(String username) { + /* prepare */ + initRemoteDataWithCredentials(VALID_REPO_URL, username, VALID_PWD); + /* execute + test */ PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, - () -> gitInputValidatorToTest.validateUsername(username)); + () -> gitInputValidatorToTest.validate(context)); assertEquals("Defined username must match the git pattern.", exception.getMessage()); } @ParameterizedTest @ValueSource(strings = { "ghp_123456789012345678901234567890123456", "ghs_123456789012345678901234567890123456", "github_pat_1234567890123456789012_1234567890123456789012345678901234567890123456789012example" }) - void validatePassword_does_not_throw_exception_when_password_is_valid(String password) { + void validate_does_not_throw_exception_when_password_is_valid(String password) { + /* prepare */ + initRemoteDataWithCredentials(VALID_REPO_URL, VALID_USERNAME, password); + /* execute + test */ - assertDoesNotThrow(() -> gitInputValidatorToTest.validatePassword(password)); + assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "./bin/bash", "ghp_1234567890123456789012345678901234567", "ghs_1234567890123456789012345678901234567", "github_pat_123456789012345678901234567890123456_;echo 'malicious'" }) - void validatePassword_throws_exception_when_password_is_invalid(String password) { + void validate_throws_exception_when_password_is_invalid(String password) { + /* prepare */ + initRemoteDataWithCredentials(VALID_REPO_URL, VALID_USERNAME, password); + /* execute + test */ PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, - () -> gitInputValidatorToTest.validatePassword(password)); + () -> gitInputValidatorToTest.validate(context)); assertEquals("Defined password must match the git Api token pattern.", exception.getMessage()); } @Test - void validate_throws_exception_when_credentials_are_empty() { + void validate_throws_exception_when_credentials_not_null_but_user_is_null() { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("https://example.com/my-repo.git"); - remoteDataConfiguration.setType("git"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_REPO_URL, "", ""); + remoteDataConfiguration.getCredentials().get().setUser(null); // set user to null /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> gitInputValidatorToTest.validate(context)); @@ -132,16 +153,7 @@ void validate_throws_exception_when_credentials_are_empty() { @Test void validate_throws_exception_when_no_username_found() { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setPassword("password"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("https://example.com/my-repo.git"); - remoteDataConfiguration.setType("git"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_REPO_URL, null, "pwd1"); /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> gitInputValidatorToTest.validate(context)); @@ -153,16 +165,7 @@ void validate_throws_exception_when_no_username_found() { @Test void validate_throws_exception_when_no_password_found() { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("https://example.com/my-repo.git"); - remoteDataConfiguration.setType("git"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_REPO_URL, "example-name", null); /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> gitInputValidatorToTest.validate(context)); @@ -175,56 +178,27 @@ void validate_throws_exception_when_no_password_found() { @Test void validate_successful_when_user_credentials_are_configured_correctly() throws IOException { /* prepare */ - File tempDir = Files.createTempDirectory("upload-folder").toFile(); - tempDir.deleteOnExit(); - String filename = "test"; - writer.save(new File(tempDir, filename), "some text", true); - - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); - PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - user.setPassword("ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("https://example.com/my-repo.git"); - remoteDataConfiguration.setType("git"); - context.setRemoteDataConfiguration(remoteDataConfiguration); - - /* execute + test */ - assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); - } - - @Test - void validate_successful_when_no_credentials_are_configured() throws IOException { /* prepare */ - File tempDir = Files.createTempDirectory("upload-folder").toFile(); - tempDir.deleteOnExit(); - String filename = "test"; - writer.save(new File(tempDir, filename), "some text", true); - - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); - PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("https://example.com/my-repo.git"); - remoteDataConfiguration.setType("git"); + initRemoteDataWithCredentials(VALID_REPO_URL, VALID_USERNAME, VALID_PWD); context.setRemoteDataConfiguration(remoteDataConfiguration); /* execute + test */ assertDoesNotThrow(() -> gitInputValidatorToTest.validate(context)); + } + private void initRemoteDataWithOutCredentials(String location) { + remoteDataConfiguration.setLocation(location); } - private PrepareWrapperContext createContextEmptyConfig() { - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn("test-upload-folder"); - return new PrepareWrapperContext(createFromJSON("{}"), environment); + private void initRemoteDataWithCredentials(String location, String username, String pwd) { + remoteDataConfiguration.setLocation(location); + SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); + SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); + user.setName(username); + user.setPassword(pwd); + + credentials.setUser(user); + remoteDataConfiguration.setCredentials(credentials); } } \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGitTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModuleTest.java similarity index 72% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGitTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModuleTest.java index fb5f02ad3..d8ad96515 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/PrepareWrapperModuleGitTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitPrepareWrapperModuleTest.java @@ -1,8 +1,9 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.git; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; +import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; @@ -14,6 +15,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; import org.springframework.test.util.ReflectionTestUtils; import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialConfiguration; @@ -21,63 +25,65 @@ import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; import com.mercedesbenz.sechub.test.TestFileWriter; +import com.mercedesbenz.sechub.wrapper.prepare.InputValidatorExitcode; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.InputValidatorExitcode; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; import com.mercedesbenz.sechub.wrapper.prepare.upload.FileNameSupport; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; -class PrepareWrapperModuleGitTest { +class GitPrepareWrapperModuleTest { - private PrepareWrapperModuleGit moduleToTest; - private WrapperGit git; + private GitPrepareWrapperModule moduleToTest; + private GitWrapper gitWrapper; private TestFileWriter writer; - private GitInputValidator gitInputValidator; + private GitPrepareInputValidator gitPrepareInputValidator; private FileNameSupport filesSupport; private final Path gitDownloadFolder = Path.of(GitContext.DOWNLOAD_DIRECTORY_NAME); private final Path testRepo = Path.of("test-repo"); @BeforeEach void beforeEach() { - moduleToTest = new PrepareWrapperModuleGit(); + moduleToTest = new GitPrepareWrapperModule(); writer = new TestFileWriter(); - gitInputValidator = mock(GitInputValidator.class); - git = mock(WrapperGit.class); + gitPrepareInputValidator = mock(GitPrepareInputValidator.class); + gitWrapper = mock(GitWrapper.class); filesSupport = mock(FileNameSupport.class); PDSLogSanitizer pdsLogSanitizer = mock(PDSLogSanitizer.class); PrepareWrapperUploadService uploadService = mock(PrepareWrapperUploadService.class); - ReflectionTestUtils.setField(moduleToTest, "pdsPrepareModuleGitEnabled", true); + ReflectionTestUtils.setField(moduleToTest, "enabled", true); moduleToTest.uploadService = uploadService; moduleToTest.filesSupport = filesSupport; - moduleToTest.git = git; - moduleToTest.gitInputValidator = gitInputValidator; + moduleToTest.gitWrapper = gitWrapper; + moduleToTest.gitPrepareInputValidator = gitPrepareInputValidator; moduleToTest.pdsLogSanitizer = pdsLogSanitizer; } @Test - void when_inputValidator_throws_InputValidatorException_prepare_return_false() throws Exception { + void when_inputValidator_throws_InputValidatorException_it_is_thrown_by_module_as_well() throws Exception { /* prepare */ PrepareWrapperContext context = createContext(); - doThrow(new PrepareWrapperInputValidatorException("test", InputValidatorExitcode.LOCATION_NOT_MATCHING_PATTERN)).when(gitInputValidator) - .validate(context); - /* execute */ - boolean result = moduleToTest.prepare(context); + /* @formatter:off */ + PrepareWrapperInputValidatorException exception = new PrepareWrapperInputValidatorException("test", InputValidatorExitcode.LOCATION_NOT_MATCHING_PATTERN); + doThrow(exception). + when(gitPrepareInputValidator).validate(context); + /* @formatter:on */ + + /* execute + test */ + assertThrows(PrepareWrapperInputValidatorException.class, () -> moduleToTest.prepare(context)); - /* test */ - assertFalse(result); } @Test - void when_inputValidator_throws_exception_prepare_throws_exception() throws PrepareWrapperInputValidatorException { + void when_inputValidator_throws_exception_prepare_rethrows_such_exception() throws PrepareWrapperInputValidatorException { /* prepare */ PrepareWrapperContext context = createContext(); - doThrow(new IllegalStateException("test")).when(gitInputValidator).validate(context); + doThrow(new IllegalStateException("test")).when(gitPrepareInputValidator).validate(context); /* execute + test */ assertThrows(IllegalStateException.class, () -> moduleToTest.prepare(context)); @@ -104,22 +110,31 @@ void prepare_successful_with_user_credentials_configured() throws IOException { SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - user.setPassword("ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"); + + String testUsername = "my-example-name"; + String testPassword = "ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"; + + user.setName(testUsername); + user.setPassword(testPassword); credentials.setUser(user); remoteDataConfiguration.setCredentials(credentials); remoteDataConfiguration.setLocation("my-example-location"); remoteDataConfiguration.setType("git"); context.setRemoteDataConfiguration(remoteDataConfiguration); - ReflectionTestUtils.setField(moduleToTest, "pdsPrepareModuleGitEnabled", true); + moduleToTest.enabled = true; /* execute */ - boolean result = moduleToTest.prepare(context); + moduleToTest.prepare(context); /* test */ - assertTrue(result); - verify(git).downloadRemoteData(any(GitContext.class)); + ArgumentCaptor gitContextCaptor = ArgumentCaptor.forClass(GitContext.class); + verify(gitWrapper).downloadRemoteData(gitContextCaptor.capture()); + + GitContext gitContext = gitContextCaptor.getValue(); + assertEquals("my-example-location", gitContext.getLocation()); + assertEquals("my-example-name", gitContext.getUnsealedUsername()); + assertEquals("ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf", gitContext.getUnsealedPassword()); } @Test @@ -149,11 +164,12 @@ void prepare_successful_when_no_credentials_are_configured() throws IOException moduleToTest.prepare(context); /* test */ - verify(git).downloadRemoteData(any(GitContext.class)); + verify(gitWrapper).downloadRemoteData(any(GitContext.class)); } - @Test - void prepare_returns_false_when_modul_is_disabled() throws IOException { + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void prepare_module_is_enabled_by_parameter_pdsPrepareModuleGitEnabled(boolean param) throws IOException { /* prepare */ PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); when(environment.getPdsJobWorkspaceLocation()).thenReturn("temp"); @@ -164,13 +180,13 @@ void prepare_returns_false_when_modul_is_disabled() throws IOException { remoteDataConfiguration.setType("docker"); context.setRemoteDataConfiguration(remoteDataConfiguration); - ReflectionTestUtils.setField(moduleToTest, "pdsPrepareModuleGitEnabled", false); + moduleToTest.enabled = param; /* execute */ - boolean result = moduleToTest.prepare(context); + boolean result = moduleToTest.isEnabled(); /* test */ - assertFalse(result); + assertEquals(result, param); } @Test diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGitTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapperTest.java similarity index 72% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGitTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapperTest.java index 5718a0c86..81d009cca 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/WrapperGitTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/git/GitWrapperTest.java @@ -1,39 +1,32 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.git; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_PASSWORD; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_USERNAME; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; import java.util.concurrent.TimeUnit; -import javax.crypto.SealedObject; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; import com.mercedesbenz.sechub.commons.pds.PDSProcessAdapterFactory; import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; -class WrapperGitTest { +class GitWrapperTest { - private WrapperGit gitToTest; + private GitWrapper wrapperToTest; private PDSProcessAdapterFactory processAdapterFactory; private JGitAdapter jGitAdapter; @BeforeEach void beforeEach() throws IOException, InterruptedException { - gitToTest = new WrapperGit(); + wrapperToTest = new GitWrapper(); processAdapterFactory = mock(PDSProcessAdapterFactory.class); ProcessAdapter processAdapter = mock(ProcessAdapter.class); jGitAdapter = mock(JGitAdapter.class); @@ -41,8 +34,8 @@ void beforeEach() throws IOException, InterruptedException { when(processAdapter.waitFor(any(Long.class), any(TimeUnit.class))).thenReturn(true); doNothing().when(jGitAdapter).clone(any()); - gitToTest.processAdapterFactory = processAdapterFactory; - gitToTest.jGitAdapter = jGitAdapter; + wrapperToTest.processAdapterFactory = processAdapterFactory; + wrapperToTest.jGitAdapter = jGitAdapter; } @ParameterizedTest @@ -50,17 +43,14 @@ void beforeEach() throws IOException, InterruptedException { void when_cloneRepository_is_executed_the_processAdapterFactory_starts_JGit_clone(String location) throws IOException { /* prepare */ Path tempDir = Files.createTempDirectory("test"); - Map credentialMap = new HashMap<>(); - credentialMap.put(PDS_PREPARE_CREDENTIAL_USERNAME, CryptoAccess.CRYPTO_STRING.seal("user")); - credentialMap.put(PDS_PREPARE_CREDENTIAL_PASSWORD, CryptoAccess.CRYPTO_STRING.seal("password")); GitContext gitContext = new GitContext(); gitContext.setCloneWithoutHistory(true); gitContext.setLocation(location); - gitContext.setCredentialMap(credentialMap); - gitContext.setupRequiredToolDirectories(tempDir); + gitContext.setSealedCredentials("user", "password"); + gitContext.init(tempDir); /* execute */ - gitToTest.downloadRemoteData(gitContext); + wrapperToTest.downloadRemoteData(gitContext); /* test */ verify(jGitAdapter, times(1)).clone(gitContext); @@ -74,7 +64,7 @@ void when_JGit_clone_throws_exception_RuntimeException_is_thrown(String location doThrow(runtimeException).when(jGitAdapter).clone(any()); /* execute */ - RuntimeException exception = assertThrows(RuntimeException.class, () -> gitToTest.downloadRemoteData(any())); + RuntimeException exception = assertThrows(RuntimeException.class, () -> wrapperToTest.downloadRemoteData(any())); /* test */ assertTrue(exception.getMessage().contains("Error while cloning from repository: " + location)); @@ -86,7 +76,7 @@ void when_cleanGitDirectory_is_executed_the_processAdapterFactory_starts_one_pro String directory = "test-upload-folder"; /* execute */ - gitToTest.cleanUploadDirectory(Path.of(directory)); + wrapperToTest.cleanUploadDirectory(Path.of(directory)); /* test */ verify(processAdapterFactory, times(1)).startProcess(any()); @@ -100,7 +90,7 @@ void when_cleanGitDirectory_throws_exception_IOException_is_thrown() throws IOEx String directory = "test-upload-folder"; /* execute */ - Exception exception = assertThrows(Exception.class, () -> gitToTest.cleanUploadDirectory(Path.of(directory))); + Exception exception = assertThrows(Exception.class, () -> wrapperToTest.cleanUploadDirectory(Path.of(directory))); /* test */ assertTrue(exception.getMessage().contains("Error while cleaning git directory: test-upload-folder")); diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidatorTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidatorTest.java index 15fd67530..9e06e8a29 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidatorTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoInputValidatorTest.java @@ -1,74 +1,90 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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.commons.model.SecHubRemoteCredentialConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer; -import com.mercedesbenz.sechub.test.TestFileWriter; -import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperUsageException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperUsageException; class SkopeoInputValidatorTest { - private SkopeoInputValidator validatorToTest; - private TestFileWriter writer; + private static final String VALID_PWD = "ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"; + private static final String VALID_DOCKER_URL = "my-example-location"; + private static final String VALID_USERNAME = "my-example-name"; + private SkopeoPrepareInputValidator validatorToTest; + private PrepareWrapperContext context; + private SecHubRemoteDataConfiguration remoteDataConfiguration; @BeforeEach void beforeEach() { - writer = new TestFileWriter(); - validatorToTest = new SkopeoInputValidator(); + validatorToTest = new SkopeoPrepareInputValidator(); - validatorToTest.pdsLogSanitizer = mock(PDSLogSanitizer.class); + validatorToTest.logSanitizer = mock(PDSLogSanitizer.class); + + context = mock(PrepareWrapperContext.class); + remoteDataConfiguration = new SecHubRemoteDataConfiguration(); + when(context.getRemoteDataConfiguration()).thenReturn(remoteDataConfiguration); } @ParameterizedTest @ValueSource(strings = { "ubuntu:22.04", "ubuntu", "docker://ubuntu:22.04", "docker://ubuntu", "oci:busybox_ocilayout:latest", "https://hub.docker.com", "docker://docker.io/library/busybox:latest", "ubuntu@sha256:26c68657ccce2cb0a31b330cb0be2b5e108d467f641c62e13ab40cbec258c68d", "ghcr.io/owner/repo:tag" }) - void validateLocation_returns_true_for_valid_docker_urls(String location) { + void validate_throws_no_exception_for_valid_docker_urls(String dockerUrl) { + /* prepare */ + initRemoteDataWithOutCredentials(dockerUrl); + /* execute + test */ - assertDoesNotThrow(() -> validatorToTest.validateLocation(location)); + assertDoesNotThrow(() -> validatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "invalid-registry ubuntu:22.04", "docker://registry/ubuntu:invalid tag", "docker://ubuntu:tag$maliciousCode", "docker://ubuntu:tag|maliciousCode", "my-registry/oci:busybox_ocilayout;latest", }) - void validateLocation_throws_IllegalArgumentException_for_invalid_docker_urls(String location) { + void validate_throws_usage_exception_for_invalid_docker_urls(String dockerUrl) { + /* prepare */ + initRemoteDataWithOutCredentials(dockerUrl); + /* execute + test */ - assertThrows(PrepareWrapperUsageException.class, () -> validatorToTest.validateLocation(location)); + assertThrows(PrepareWrapperUsageException.class, () -> validatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "username", "username123", "username_123", "username-123", "username-123_456", "username1234567890123456789003890123456", "user_user_user" }) - void validateUsername_returns_true_for_valid_usernames(String username) { + void validate_does_not_throw_exception_for_valid_usernames(String username) { + + /* prepare */ + initRemoteDataWithCredentials(VALID_DOCKER_URL, username, VALID_PWD); + /* execute + test */ - assertDoesNotThrow(() -> validatorToTest.validateUsername(username)); + assertDoesNotThrow(() -> validatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "user name", "username?", "username!", "username>", "username<", "username'", "username\"", "username;", "username&", "username|", "username`", "username$", "username{", "username}" }) - void validateUsername_throws_exception_for_invalid_usernames(String username) { + void validate_throws_exception_for_invalid_usernames(String username) { + /* prepare */ + initRemoteDataWithCredentials(VALID_DOCKER_URL, username, VALID_PWD); + /* execute */ - PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, - () -> validatorToTest.validateUsername(username)); + PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, () -> validatorToTest.validate(context)); /* test */ assertEquals("Defined username must match the docker pattern.", exception.getMessage()); @@ -77,18 +93,23 @@ void validateUsername_throws_exception_for_invalid_usernames(String username) { @ParameterizedTest @ValueSource(strings = { "password", "password123", "password_123", "password-123", "password-123_456", "password1234567890123456789003890123456", "dXNlckBleGFtcGxlLmNvbTpzZWNyZXQexample", "Z2hjcl9wczpzc2VjcmV0example" }) - void validatePassword_returns_true_for_valid_passwords(String password) { + void validate_does_not_throw_exception_for_valid_passwords(String password) { + /* prepare */ + initRemoteDataWithCredentials(VALID_DOCKER_URL, VALID_USERNAME, password); + /* execute + test */ - assertDoesNotThrow(() -> validatorToTest.validatePassword(password)); + assertDoesNotThrow(() -> validatorToTest.validate(context)); } @ParameterizedTest @ValueSource(strings = { "password?", "password!", "password>", "password<", "password'", "password\"", "password;", "password&", "password|", "password`", "password$", "password{", "password}", "password;echo 'malicious'" }) - void validatePassword_throws_exception_for_invalid_passwords(String password) { + void validate_does_throw_exception_for_invalid_passwords(String password) { + /* prepare */ + initRemoteDataWithCredentials(VALID_DOCKER_URL, VALID_USERNAME, password); + /* execute */ - PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, - () -> validatorToTest.validatePassword(password)); + PrepareWrapperInputValidatorException exception = assertThrows(PrepareWrapperInputValidatorException.class, () -> validatorToTest.validate(context)); /* test */ assertEquals("Defined password must match the docker Api token pattern.", exception.getMessage()); @@ -97,13 +118,8 @@ void validatePassword_throws_exception_for_invalid_passwords(String password) { @Test void validate_throws_exception_when_credentials_are_empty() { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_DOCKER_URL, VALID_USERNAME, VALID_PWD); + remoteDataConfiguration.getCredentials().get().setUser(null); // this makes it invalid... /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> validatorToTest.validate(context)); @@ -112,19 +128,12 @@ void validate_throws_exception_when_credentials_are_empty() { assertEquals("Defined credentials must contain credential user and can not be empty.", exception.getMessage()); } - @Test - void validate_throws_exception_when_no_username_found() { + @ParameterizedTest + @EmptySource + @NullSource + void validate_throws_exception_when_no_username_found(String username) { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setPassword("my-example-password"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_DOCKER_URL, username, VALID_PWD); /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> validatorToTest.validate(context)); @@ -133,19 +142,12 @@ void validate_throws_exception_when_no_username_found() { assertTrue(exception.getMessage().contains("Defined username must not be null or empty.")); } - @Test - void validate_throws_exception_when_no_password_found() { + @ParameterizedTest + @EmptySource + @NullSource + void validate_throws_exception_when_no_password_found(String pwd) { /* prepare */ - PrepareWrapperContext context = createContextEmptyConfig(); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataWithCredentials(VALID_DOCKER_URL, VALID_USERNAME, pwd); /* execute */ PrepareWrapperUsageException exception = assertThrows(PrepareWrapperUsageException.class, () -> validatorToTest.validate(context)); @@ -156,57 +158,38 @@ void validate_throws_exception_when_no_password_found() { } @Test - void validate_successful_when_user_credentials_are_configured_correctly() throws IOException { + void validate_does_not_throw_exception_when_user_credentials_are_configured_correctly() throws IOException { /* prepare */ - File tempDir = Files.createTempDirectory("upload-folder").toFile(); - tempDir.deleteOnExit(); - String filename = "testimage.tar"; - writer.save(new File(tempDir, filename), "some text", true); - - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); - PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - user.setPassword("ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("my-example-location"); + initRemoteDataWithCredentials(VALID_DOCKER_URL, VALID_USERNAME, VALID_PWD); remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); /* execute + test */ assertDoesNotThrow(() -> validatorToTest.validate(context)); } @Test - void validate_successful_when_no_credentials_are_configured() throws IOException { + void validate_does_not_throw_exception_when_no_credentials_are_configured() throws IOException { /* prepare */ - File tempDir = Files.createTempDirectory("upload-folder").toFile(); - tempDir.deleteOnExit(); - String filename = "testimage.tar"; - writer.save(new File(tempDir, filename), "some text", true); - - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); - PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("my-example-location"); + initRemoteDataWithOutCredentials(VALID_DOCKER_URL); remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); /* execute + test */ assertDoesNotThrow(() -> validatorToTest.validate(context)); } - private PrepareWrapperContext createContextEmptyConfig() { - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn("test-upload-folder"); - return new PrepareWrapperContext(createFromJSON("{}"), environment); + private void initRemoteDataWithOutCredentials(String location) { + remoteDataConfiguration.setLocation(location); + } + + private void initRemoteDataWithCredentials(String location, String username, String pwd) { + remoteDataConfiguration.setLocation(location); + SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); + SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); + user.setName(username); + user.setPassword(pwd); + + credentials.setUser(user); + remoteDataConfiguration.setCredentials(credentials); } } diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeoTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModuleTest.java similarity index 54% rename from sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeoTest.java rename to sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModuleTest.java index 4dd73502c..52e5694ca 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/PrepareWrapperModuleSkopeoTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoPrepareWrapperModuleTest.java @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; +import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; @@ -14,67 +14,102 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.test.util.ReflectionTestUtils; import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubRemoteCredentialUserData; import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; import com.mercedesbenz.sechub.test.TestFileWriter; +import com.mercedesbenz.sechub.wrapper.prepare.InputValidatorExitcode; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperInputValidatorException; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.InputValidatorExitcode; -import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareWrapperInputValidatorException; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; import com.mercedesbenz.sechub.wrapper.prepare.upload.FileNameSupport; import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadService; -class PrepareWrapperModuleSkopeoTest { +class SkopeoPrepareWrapperModuleTest { - private PrepareWrapperModuleSkopeo moduleToTest; - private SkopeoInputValidator skopeoInputValidator; - private WrapperSkopeo skopeo; + private SkopeoPrepareWrapperModule moduleToTest; + private SkopeoPrepareInputValidator inputValidator; + private SkopeoWrapper skopeoWrapper; private TestFileWriter writer; private FileNameSupport fileNameSupport; - private final Path skopeoDownloadFolder = Path.of(SkopeoContext.DOWNLOAD_DIRECTORY_NAME); + /* FIXME Albert Tregnaghi, 2024-06-06: this should be improved: */ + private final Path skopeoDownloadFolder = Path.of(SkopeoWrapperConstants.DOWNLOAD_DIRECTORY_NAME); @BeforeEach void beforeEach() { - moduleToTest = new PrepareWrapperModuleSkopeo(); - skopeoInputValidator = mock(SkopeoInputValidator.class); + moduleToTest = new SkopeoPrepareWrapperModule(); + inputValidator = mock(SkopeoPrepareInputValidator.class); writer = new TestFileWriter(); - skopeo = mock(WrapperSkopeo.class); + skopeoWrapper = mock(SkopeoWrapper.class); fileNameSupport = mock(FileNameSupport.class); PrepareWrapperUploadService uploadService = mock(PrepareWrapperUploadService.class); - ReflectionTestUtils.setField(moduleToTest, "pdsPrepareModuleSkopeoEnabled", true); + ReflectionTestUtils.setField(moduleToTest, "enabled", true); - moduleToTest.skopeoInputValidator = skopeoInputValidator; - moduleToTest.skopeo = skopeo; + moduleToTest.inputValidator = inputValidator; + moduleToTest.skopeoWrapper = skopeoWrapper; moduleToTest.filesSupport = fileNameSupport; moduleToTest.uploadService = uploadService; } @Test - void when_inputValidator_throws_InputValidatorException_prepare_return_false() throws IOException, PrepareWrapperInputValidatorException { + void when_inputValidator_throws_InputValidatorException_prepare_rethrows_it() throws IOException, PrepareWrapperInputValidatorException { /* prepare */ PrepareWrapperContext context = createContext(); - doThrow(new PrepareWrapperInputValidatorException("test", InputValidatorExitcode.LOCATION_NOT_MATCHING_PATTERN)).when(skopeoInputValidator) - .validate(context); + + /* @formatter:off */ + doThrow(new PrepareWrapperInputValidatorException("test", InputValidatorExitcode.LOCATION_NOT_MATCHING_PATTERN)). + when(inputValidator).validate(context); + /* @formatter:on */ + + /* execute + test */ + assertThrows(PrepareWrapperInputValidatorException.class, () -> moduleToTest.prepare(context)); + + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void module_isResponsible_returns_result_from_input_validator_is_accepted(boolean accepting) throws IOException { + /* prepare */ + PrepareWrapperContext context = createContext(); + + when(inputValidator.isAccepting(context)).thenReturn(accepting); + + /* execute */ + boolean result = moduleToTest.isResponsibleToPrepare(context); + + /* test */ + assertEquals(accepting, result); + + } + + @ParameterizedTest + @ValueSource(booleans = { true, false }) + void module_isEnabled_returns_result_from_field(boolean enabled) throws IOException { + /* prepare */ + moduleToTest.enabled = enabled; /* execute */ - boolean result = moduleToTest.prepare(context); + boolean result = moduleToTest.isEnabled(); /* test */ - assertFalse(result); + assertEquals(enabled, result); + } @Test void when_inputvalidator_throws_exception_prepare_throws_exception() throws PrepareWrapperInputValidatorException { /* prepare */ PrepareWrapperContext context = createContext(); - doThrow(new IllegalStateException("test")).when(skopeoInputValidator).validate(context); + doThrow(new IllegalStateException("test")).when(inputValidator).validate(context); /* execute + test */ assertThrows(IllegalStateException.class, () -> moduleToTest.prepare(context)); + verify(inputValidator).validate(context); // validator was called } @Test @@ -89,18 +124,10 @@ void prepare_successful_when_user_credentials_are_configured_correctly() throws PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); + PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); - SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); - user.setName("my-example-name"); - user.setPassword("ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf"); - credentials.setUser(user); - remoteDataConfiguration.setCredentials(credentials); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataConfiguration("my-example-location", "my-example-name", "ghp_exampleAPITOKEN8ffne3l6g9f393r8fbcsf", context); when(fileNameSupport.getTarFilesFromDirectory(downloadDirectory)).thenReturn(List.of(testFile)); @@ -108,59 +135,58 @@ void prepare_successful_when_user_credentials_are_configured_correctly() throws moduleToTest.prepare(context); /* test */ - verify(skopeo).download(any(SkopeoContext.class)); - verify(skopeo).cleanUploadDirectory(tempDir.toPath().resolve(skopeoDownloadFolder)); + verify(inputValidator).validate(context); // validator was called + verify(skopeoWrapper).download(any(SkopeoContext.class)); + verify(skopeoWrapper).cleanUploadDirectory(tempDir.toPath().resolve(skopeoDownloadFolder)); } - @Test - void prepare_successful_when_no_credentials_are_configured() throws IOException { - /* prepare */ - File tempDir = Files.createTempDirectory("upload-folder").toFile(); - tempDir.deleteOnExit(); - - Path testFile = Path.of("testimage.tar"); - Path downloadDirectory = tempDir.toPath().resolve(skopeoDownloadFolder); - writer.save(downloadDirectory.resolve(testFile).toFile(), "some text", true); - - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); - PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); + private void initRemoteDataConfigurationAnonymous(String location, PrepareWrapperContext context) { + initRemoteDataConfiguration(location, null, null, context); + } + private void initRemoteDataConfiguration(String location, String username, String password, PrepareWrapperContext context) { SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); context.setRemoteDataConfiguration(remoteDataConfiguration); - when(fileNameSupport.getTarFilesFromDirectory(downloadDirectory)).thenReturn(List.of(testFile)); - - /* execute */ - moduleToTest.prepare(context); + remoteDataConfiguration.setType("docker"); + remoteDataConfiguration.setLocation(location); - /* test */ - verify(skopeo).download(any(SkopeoContext.class)); - verify(skopeo).cleanUploadDirectory(tempDir.toPath().resolve(skopeoDownloadFolder)); + if (username == null && password == null) { + return; + } + SecHubRemoteCredentialConfiguration credentials = new SecHubRemoteCredentialConfiguration(); + SecHubRemoteCredentialUserData user = new SecHubRemoteCredentialUserData(); + user.setName(username); + user.setPassword(password); + credentials.setUser(user); + remoteDataConfiguration.setCredentials(credentials); } @Test - void prepare_returns_false_when_modul_is_disabled() throws IOException { + void prepare_does_validate_download_and_cleanup_docker_image_when_no_credentials_configured() throws IOException { /* prepare */ + File tempDir = Files.createTempDirectory("upload-folder").toFile(); + tempDir.deleteOnExit(); + + Path downloadDirectory = tempDir.toPath().resolve(skopeoDownloadFolder); + Path testFile = downloadDirectory.resolve("testimage.tar"); + writer.save(testFile.toFile(), "some text", true); PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - when(environment.getPdsJobWorkspaceLocation()).thenReturn("temp"); + when(environment.getPdsJobWorkspaceLocation()).thenReturn(tempDir.toString()); PrepareWrapperContext context = new PrepareWrapperContext(createFromJSON("{}"), environment); - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("my-example-location"); - remoteDataConfiguration.setType("docker"); - context.setRemoteDataConfiguration(remoteDataConfiguration); + initRemoteDataConfigurationAnonymous("my-example-locatin", context); - ReflectionTestUtils.setField(moduleToTest, "pdsPrepareModuleSkopeoEnabled", false); + when(fileNameSupport.getTarFilesFromDirectory(downloadDirectory)).thenReturn(List.of(testFile)); /* execute */ - boolean result = moduleToTest.prepare(context); + moduleToTest.prepare(context); /* test */ - assertFalse(result); + verify(inputValidator).validate(context); // validator was called + verify(skopeoWrapper).download(any(SkopeoContext.class)); + verify(skopeoWrapper).cleanUploadDirectory(tempDir.toPath().resolve(skopeoDownloadFolder)); } private PrepareWrapperContext createContext() { diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperTest.java new file mode 100644 index 000000000..caef34e68 --- /dev/null +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/SkopeoWrapperTest.java @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: MIT +package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; + +import com.mercedesbenz.sechub.commons.pds.PDSProcessAdapterFactory; +import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; +import com.mercedesbenz.sechub.test.TestUtil; + +class SkopeoWrapperTest { + + private SkopeoWrapper wrapperToTest; + private PDSProcessAdapterFactory processAdapterFactory; + private Path workingDirectory; + + @BeforeEach + void beforeEach() throws IOException, InterruptedException { + wrapperToTest = new SkopeoWrapper(); + workingDirectory = TestUtil.createTempDirectoryInBuildFolder("skopeo-wrapper-test"); + + processAdapterFactory = mock(PDSProcessAdapterFactory.class); + + ProcessAdapter processAdapter = mock(ProcessAdapter.class); + when(processAdapterFactory.startProcess(any())).thenReturn(processAdapter); + when(processAdapter.waitFor(any(Long.class), any(TimeUnit.class))).thenReturn(true); + + wrapperToTest.processAdapterFactory = processAdapterFactory; + } + + @Test + void when_download_is_executed_download_process_is_executed() throws IOException { + /* prepare */ + String location = "docker://ubuntu:22.04"; + + SkopeoContext context = new SkopeoContext(); + context.setLocation(location); + context.init(workingDirectory); + + /* execute */ + wrapperToTest.download(context); + + /* test */ + ArgumentCaptor pbCaptor = ArgumentCaptor.forClass(ProcessBuilder.class); + verify(processAdapterFactory, times(1)).startProcess(pbCaptor.capture()); + assertProcessBuilderCalledWithParametersForSkopeoDownload(context, location, pbCaptor.getValue(), false); + } + + @Test + void when_download_is_executed_with_credentials_download_and_login_process_are_executed() throws IOException { + /* prepare */ + String location = "docker://ubuntu:22.04"; + String username = "username1"; + String password = "password1"; + + SkopeoContext context = new SkopeoContext(); + context.setLocation(location); + context.init(workingDirectory); + context.setSealedCredentials(username, password); + + /* execute */ + wrapperToTest.download(context); + + /* test */ + ArgumentCaptor pbCaptor = ArgumentCaptor.forClass(ProcessBuilder.class); + verify(processAdapterFactory, times(2)).startProcess(pbCaptor.capture()); + List processBuilders = pbCaptor.getAllValues(); + Iterator pbIt = processBuilders.iterator(); + + assertProcessBuilderCalledWithParametersForLogin(context, "ubuntu:22.04", username, password, pbIt.next()); + assertProcessBuilderCalledWithParametersForSkopeoDownload(context, location, pbIt.next(), true); + } + + @Test + void when_process_throws_exception_then_download_throws_exception() throws IOException { + /* prepare */ + String location = "docker://ubuntu:22.04"; + SkopeoContext context = new SkopeoContext(); + context.setLocation(location); + context.init(workingDirectory); + when(processAdapterFactory.startProcess(any())).thenThrow(new IOException()); + + /* execute */ + IOException exception = assertThrows(IOException.class, () -> wrapperToTest.download(context)); + + /* test */ + assertEquals("Error while download with Skopeo from: " + location, exception.getMessage()); + + } + + @Test + void when_cleanUploadDirectory_is_executed_clean_process_is_executed() throws IOException { + /* execute */ + assertDoesNotThrow(() -> wrapperToTest.cleanUploadDirectory(workingDirectory)); + + /* test */ + verify(processAdapterFactory, times(1)).startProcess(any()); + } + + private void assertProcessBuilderCalledWithParametersForLogin(SkopeoContext context, String location, String user, String password, + ProcessBuilder calledProcessBuilder) { + + List commandList = calledProcessBuilder.command(); + + // skopeo, login, ubuntu:22.04, --username, username1, --password, password1, + // --authfile, authentication.json] + List expectedCommands = new ArrayList<>(); + expectedCommands.add("skopeo"); + expectedCommands.add("login"); + expectedCommands.add(location); + expectedCommands.add("--username"); + expectedCommands.add(user); + expectedCommands.add("--password"); + expectedCommands.add(password); + expectedCommands.add("--authfile"); + expectedCommands.add("authentication.json"); + + assertCommandListAsExpected(commandList, expectedCommands); + } + + private void assertProcessBuilderCalledWithParametersForSkopeoDownload(SkopeoContext context, String location, ProcessBuilder calledProcessBuilder, + boolean authorized) { + + List commandList = calledProcessBuilder.command(); + + List expectedCommands = new ArrayList<>(); + expectedCommands.add("skopeo"); + expectedCommands.add("copy"); + expectedCommands.add(location); + expectedCommands.add("docker-archive:" + context.getDownloadTarFile().toString()); + if (authorized) { + expectedCommands.add("--authfile"); + expectedCommands.add("authentication.json"); + } + + assertCommandListAsExpected(commandList, expectedCommands); + } + + private void assertCommandListAsExpected(List commandList, List expectedCommands) { + if (expectedCommands.size() != commandList.size()) { + assertEquals(expectedCommands.toString(), commandList.toString()); + } + int pos = 0; + for (String expectedCommand : expectedCommands) { + String command = commandList.get(pos++); + if (!command.equals(expectedCommand)) { + assertEquals(expectedCommand, command, "Command differs!"); + } + + } + } + +} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeoTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeoTest.java deleted file mode 100644 index c709bdcf0..000000000 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/modules/skopeo/WrapperSkopeoTest.java +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.modules.skopeo; - -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_PASSWORD; -import static com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironmentVariables.PDS_PREPARE_CREDENTIAL_USERNAME; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.crypto.SealedObject; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import com.mercedesbenz.sechub.commons.core.security.CryptoAccess; -import com.mercedesbenz.sechub.commons.pds.PDSProcessAdapterFactory; -import com.mercedesbenz.sechub.commons.pds.ProcessAdapter; - -class WrapperSkopeoTest { - - private WrapperSkopeo wrapperToTest; - private PDSProcessAdapterFactory processAdapterFactory; - private final Path skopeoDownloadPath = Path.of(SkopeoContext.DOWNLOAD_DIRECTORY_NAME); - - @BeforeEach - void beforeEach() throws IOException, InterruptedException { - wrapperToTest = new WrapperSkopeo(); - processAdapterFactory = mock(PDSProcessAdapterFactory.class); - ProcessAdapter processAdapter = mock(ProcessAdapter.class); - when(processAdapterFactory.startProcess(any())).thenReturn(processAdapter); - when(processAdapter.waitFor(any(Long.class), any(TimeUnit.class))).thenReturn(true); - - wrapperToTest.processAdapterFactory = processAdapterFactory; - } - - @Test - void when_download_is_executed_download_process_is_executed() throws IOException { - /* prepare */ - SkopeoContext context = new SkopeoContext(); - context.setLocation("docker://ubuntu:22.04"); - context.setupRequiredToolDirectories(skopeoDownloadPath); - - /* execute */ - assertDoesNotThrow(() -> wrapperToTest.download(context)); - - /* test */ - verify(processAdapterFactory, times(1)).startProcess(any()); - } - - @Test - void when_download_is_executed_with_credentials_download_and_login_process_are_executed() throws IOException { - /* prepare */ - Map credentialMap = new HashMap(); - credentialMap.put(PDS_PREPARE_CREDENTIAL_USERNAME, CryptoAccess.CRYPTO_STRING.seal("username")); - credentialMap.put(PDS_PREPARE_CREDENTIAL_PASSWORD, CryptoAccess.CRYPTO_STRING.seal("password")); - SkopeoContext context = new SkopeoContext(); - context.setLocation("docker://ubuntu:22.04"); - context.setupRequiredToolDirectories(skopeoDownloadPath); - context.setCredentialMap(credentialMap); - - /* execute */ - assertDoesNotThrow(() -> wrapperToTest.download(context)); - - /* test */ - verify(processAdapterFactory, times(2)).startProcess(any()); - } - - @Test - void when_process_throws_exception_then_download_throws_exception() throws IOException { - /* prepare */ - String location = "docker://ubuntu:22.04"; - SkopeoContext context = new SkopeoContext(); - context.setLocation(location); - context.setupRequiredToolDirectories(skopeoDownloadPath); - when(processAdapterFactory.startProcess(any())).thenThrow(new IOException()); - - /* execute */ - IOException exception = assertThrows(IOException.class, () -> wrapperToTest.download(context)); - - /* test */ - assertEquals("Error while download with Skopeo from: " + location, exception.getMessage()); - - } - - @Test - void when_cleanUploadDirectory_is_executed_clean_process_is_executed() throws IOException { - /* execute */ - assertDoesNotThrow(() -> wrapperToTest.cleanUploadDirectory(skopeoDownloadPath)); - - /* test */ - verify(processAdapterFactory, times(1)).startProcess(any()); - } - -} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationServiceTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationServiceTest.java deleted file mode 100644 index c4bc457df..000000000 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/prepare/PrepareWrapperPreparationServiceTest.java +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -package com.mercedesbenz.sechub.wrapper.prepare.prepare; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.io.IOException; -import java.util.ArrayList; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import com.mercedesbenz.sechub.adapter.AdapterExecutionResult; -import com.mercedesbenz.sechub.commons.model.SecHubRemoteDataConfiguration; -import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.git.PrepareWrapperModuleGit; - -class PrepareWrapperPreparationServiceTest { - - private PrepareWrapperPreparationService serviceToTest; - private PrepareWrapperContext context; - - @BeforeEach - void beforeEach() { - context = mock(PrepareWrapperContext.class); - PrepareWrapperEnvironment environment = mock(PrepareWrapperEnvironment.class); - PrepareWrapperContextFactory factory = mock(PrepareWrapperContextFactory.class); - when(factory.create(environment)).thenReturn(context); - - serviceToTest = new PrepareWrapperPreparationService(); - serviceToTest.environment = environment; - serviceToTest.factory = factory; - serviceToTest.modules = new ArrayList<>(); - } - - @Test - void when_no_remote_data_was_configured_return_preparation_success_with_warn_message() throws IOException { - /* execute */ - AdapterExecutionResult result = serviceToTest.startPreparation(); - - /* test */ - assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); - assertEquals(1, result.getProductMessages().size()); - assertEquals("No Remote Configuration found.", result.getProductMessages().get(0).getText()); - } - - @Test - void when_remote_data_was_configured_but_no_module_executed_return_preparation_failed_with_message() throws IOException { - /* prepare */ - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("my-example_location"); - remoteDataConfiguration.setType("git"); - when(context.getRemoteDataConfiguration()).thenReturn(remoteDataConfiguration); - - /* execute */ - AdapterExecutionResult result = serviceToTest.startPreparation(); - - /* test */ - assertEquals("SECHUB_PREPARE_RESULT;status=FAILED", result.getProductResult()); - assertEquals(1, result.getProductMessages().size()); - assertEquals("No module was able to prepare the defined remote data.", result.getProductMessages().get(0).getText()); - } - - @Test - void when_remote_data_was_configured_and_git_module_added_return_preparation_success_without_message() throws IOException { - /* prepare */ - PrepareWrapperModuleGit gitModule = mock(PrepareWrapperModuleGit.class); - when(gitModule.prepare(context)).thenReturn(true); - serviceToTest.modules.add(gitModule); - - SecHubRemoteDataConfiguration remoteDataConfiguration = new SecHubRemoteDataConfiguration(); - remoteDataConfiguration.setLocation("my-example_location"); - remoteDataConfiguration.setType("git"); - when(context.getRemoteDataConfiguration()).thenReturn(remoteDataConfiguration); - - /* execute */ - AdapterExecutionResult result = serviceToTest.startPreparation(); - - /* test */ - assertEquals("SECHUB_PREPARE_RESULT;status=OK", result.getProductResult()); - assertEquals(0, result.getProductMessages().size()); - - verify(gitModule).prepare(context); - } -} \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreatorTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreatorTest.java index 80e4a209c..181f4fd55 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreatorTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperArchiveCreatorTest.java @@ -1,10 +1,9 @@ package com.mercedesbenz.sechub.wrapper.prepare.upload; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; +import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.io.File; import java.io.IOException; @@ -20,9 +19,10 @@ import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.test.TestFileReader; import com.mercedesbenz.sechub.test.TestFileWriter; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; class PrepareWrapperArchiveCreatorTest { @@ -63,16 +63,16 @@ void createArchive_creates_archive_for_binary() throws IOException { when(context.getSecHubConfiguration()).thenReturn(model); when(context.getEnvironment()).thenReturn(environment); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(tempDir.toPath().resolve(testDownload)); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(tempDir.toPath().resolve(testDownload)); List pathList = new ArrayList<>(); pathList.add(testDownload.resolve(testTarFilename)); when(fileNameSupport.getTarFilesFromDirectory(any())).thenReturn(pathList); /* execute */ - assertDoesNotThrow(() -> creatorToTest.create(context, toolContext)); + assertDoesNotThrow(() -> creatorToTest.create(context, abstractToolContext)); /* test */ assertTrue(new File(uploadDirectory + "/binaries.tar").exists()); @@ -102,12 +102,12 @@ void createArchive_creates_archive_for_source() throws IOException { pathList.add(testRepoName.getFileName()); when(fileNameSupport.getRepositoriesFromDirectory(any())).thenReturn(pathList); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(testDownload); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testDownload); /* execute */ - assertDoesNotThrow(() -> creatorToTest.create(context, toolContext)); + assertDoesNotThrow(() -> creatorToTest.create(context, abstractToolContext)); /* test */ assertTrue(new File(uploadDirectory + "/sourcecode.zip").exists()); diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadServiceTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadServiceTest.java index 503ac7791..9540eb427 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadServiceTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperFileUploadServiceTest.java @@ -2,6 +2,7 @@ import static com.mercedesbenz.sechub.commons.core.CommonConstants.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupportTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupportTest.java index a911c2cb0..8ae663cc5 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupportTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperSechubConfigurationSupportTest.java @@ -1,6 +1,6 @@ package com.mercedesbenz.sechub.wrapper.prepare.upload; -import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.createFromJSON; +import static com.mercedesbenz.sechub.commons.model.SecHubScanConfiguration.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -14,12 +14,18 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.mercedesbenz.sechub.commons.model.*; +import com.mercedesbenz.sechub.commons.model.JSONConverter; +import com.mercedesbenz.sechub.commons.model.SecHubBinaryDataConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; +import com.mercedesbenz.sechub.commons.model.SecHubDataConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubFileSystemConfiguration; +import com.mercedesbenz.sechub.commons.model.SecHubSourceDataConfiguration; import com.mercedesbenz.sechub.test.TestFileReader; import com.mercedesbenz.sechub.test.TestFileWriter; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; class PrepareWrapperSechubConfigurationSupportTest { @@ -39,14 +45,14 @@ void replaceRemoteDataWithFilesystem_throws_IllegalArgumentException_when_SecHub PrepareWrapperContext context = mock(PrepareWrapperContext.class); when(context.getSecHubConfiguration()).thenReturn(null); - ToolContext toolContext = mock(ToolContext.class); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); Path testPath = Path.of("path"); - when(toolContext.getUploadDirectory()).thenReturn(testPath); - when(toolContext.getToolDownloadDirectory()).thenReturn(testPath); + when(abstractToolContext.getUploadDirectory()).thenReturn(testPath); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testPath); /* execute */ IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, - () -> supportToTest.replaceRemoteDataWithFilesystem(context, toolContext)); + () -> supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext)); /* test */ assertEquals("SecHubConfigurationModel cannot be null", exception.getMessage()); @@ -62,13 +68,13 @@ void replaceRemoteDataWithFilesystem_returns_SecHubConfigurationModel_when_SecHu model.setData(data); when(context.getSecHubConfiguration()).thenReturn(model); - ToolContext toolContext = mock(ToolContext.class); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); Path testPath = Path.of("path"); - when(toolContext.getUploadDirectory()).thenReturn(testPath); - when(toolContext.getToolDownloadDirectory()).thenReturn(testPath); + when(abstractToolContext.getUploadDirectory()).thenReturn(testPath); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testPath); /* execute */ - SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext); /* test */ assertEquals(model, result); @@ -94,12 +100,12 @@ void replaceRemoteDataWithFilesystem_returns_SecHubConfigurationModel_when_SecHu when(context.getSecHubConfiguration()).thenReturn(model); when(context.getEnvironment()).thenReturn(environment); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(testDownload); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testDownload); /* execute */ - SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext); /* test */ assertNotNull(result); @@ -137,12 +143,12 @@ void replaceRemoteDataWithFilesystem_returns_SecHubConfigurationModel_when_SecHu when(context.getSecHubConfiguration()).thenReturn(model); when(context.getEnvironment()).thenReturn(environment); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(testDownload); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testDownload); /* execute */ - SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext); /* test */ assertNotNull(result); @@ -192,12 +198,12 @@ void replaceRemoteDataWithFilesystem_returns_expected_SecHubConfigurationModel_f data.getBinaries().add(binary); expectedModel.setData(data); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(testDownload); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testDownload); /* execute */ - SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext); /* test */ String stringResult = JSONConverter.get().toJSON(result); @@ -237,12 +243,12 @@ void replaceRemoteDataWithFilesystem_returns_expected_SecHubConfigurationModel_f data.getSources().add(source); expectedModel.setData(data); - ToolContext toolContext = mock(ToolContext.class); - when(toolContext.getUploadDirectory()).thenReturn(uploadDirectory); - when(toolContext.getToolDownloadDirectory()).thenReturn(testDownload); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); + when(abstractToolContext.getUploadDirectory()).thenReturn(uploadDirectory); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testDownload); /* execute */ - SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, toolContext); + SecHubConfigurationModel result = supportToTest.replaceRemoteDataWithFilesystem(context, abstractToolContext); /* test */ String stringResult = JSONConverter.get().toJSON(result); diff --git a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadServiceTest.java b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadServiceTest.java index 3281be73b..69db952e9 100644 --- a/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadServiceTest.java +++ b/sechub-wrapper-prepare/src/test/java/com/mercedesbenz/sechub/wrapper/prepare/upload/PrepareWrapperUploadServiceTest.java @@ -1,7 +1,7 @@ package com.mercedesbenz.sechub.wrapper.prepare.upload; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.nio.file.Path; @@ -17,9 +17,10 @@ import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModel; import com.mercedesbenz.sechub.commons.model.SecHubDataConfiguration; import com.mercedesbenz.sechub.commons.model.SecHubSourceDataConfiguration; +import com.mercedesbenz.sechub.wrapper.prepare.PrepareWrapperContext; import com.mercedesbenz.sechub.wrapper.prepare.cli.PrepareWrapperEnvironment; -import com.mercedesbenz.sechub.wrapper.prepare.modules.ToolContext; -import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.AbstractPrepareToolContext; +import com.mercedesbenz.sechub.wrapper.prepare.modules.PrepareToolContext; class PrepareWrapperUploadServiceTest { @@ -54,19 +55,19 @@ void upload_throws_exception_when_data_is_not_configured() { when(context.getEnvironment().getSechubJobUUID()).thenReturn(uuid.toString()); when(context.getEnvironment().getSechubJobUUID()).thenReturn(uuid.toString()); - ToolContext toolContext = mock(ToolContext.class); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); Path testPath = Path.of("path"); - when(toolContext.getUploadDirectory()).thenReturn(testPath); - when(toolContext.getToolDownloadDirectory()).thenReturn(testPath); + when(abstractToolContext.getUploadDirectory()).thenReturn(testPath); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testPath); SecHubConfigurationModel model = mock(SecHubConfigurationModel.class); - when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, toolContext)).thenReturn(model); + when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, abstractToolContext)).thenReturn(model); when(model.getProjectId()).thenReturn("projectId"); when(context.getSecHubConfiguration()).thenReturn(model); /* execute */ - IllegalStateException exception = assertThrows(IllegalStateException.class, () -> uploadServiceToTest.upload(context, toolContext)); + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> uploadServiceToTest.upload(context, abstractToolContext)); /* test */ assertEquals("SecHubConfigurationModel data is not configured.", exception.getMessage()); @@ -89,18 +90,18 @@ void upload_calls_uploadService_when_sources_are_not_empty() throws Exception { when(context.getSecHubConfiguration()).thenReturn(model); - ToolContext toolContext = mock(ToolContext.class); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); Path testPath = Path.of("path"); - when(toolContext.getUploadDirectory()).thenReturn(testPath); - when(toolContext.getToolDownloadDirectory()).thenReturn(testPath); + when(abstractToolContext.getUploadDirectory()).thenReturn(testPath); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testPath); - when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, toolContext)).thenReturn(model); + when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, abstractToolContext)).thenReturn(model); List list = mock(List.class); when(dataConfiguration.getSources()).thenReturn(list); /* execute */ - uploadServiceToTest.upload(context, toolContext); + uploadServiceToTest.upload(context, abstractToolContext); /* test */ verify(fileUploadService).uploadFile(any(), any(), any(), any()); @@ -123,18 +124,18 @@ void upload_calls_uploadService_when_binaries_are_not_empty() throws Exception { when(context.getSecHubConfiguration()).thenReturn(model); - ToolContext toolContext = mock(ToolContext.class); + PrepareToolContext abstractToolContext = mock(AbstractPrepareToolContext.class); Path testPath = Path.of("path"); - when(toolContext.getUploadDirectory()).thenReturn(testPath); - when(toolContext.getToolDownloadDirectory()).thenReturn(testPath); + when(abstractToolContext.getUploadDirectory()).thenReturn(testPath); + when(abstractToolContext.getToolDownloadDirectory()).thenReturn(testPath); - when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, toolContext)).thenReturn(model); + when(sechubConfigurationSupport.replaceRemoteDataWithFilesystem(context, abstractToolContext)).thenReturn(model); List list = mock(List.class); when(dataConfiguration.getBinaries()).thenReturn(list); /* execute */ - uploadServiceToTest.upload(context, toolContext); + uploadServiceToTest.upload(context, abstractToolContext); /* test */ verify(fileUploadService).uploadFile(any(), any(), any(), any()); diff --git a/sechub-wrapper-prepare/src/test/resources/application-test-fail.properties b/sechub-wrapper-prepare/src/test/resources/application-test-fail.properties deleted file mode 100644 index 3a479c22c..000000000 --- a/sechub-wrapper-prepare/src/test/resources/application-test-fail.properties +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-License-Identifier: MIT -# --------------- -# common setup -# --------------- -sechub.job.uuid=665dc4e8-d2de-4d2f-a3a3-4c447630b229 - -pds.scan.configuration={"projectId":"project1","data": {"binaries": [{"name": "remote_example_name","remote": {"location": "https://not-any.repo/","type": "not-git"}}]},"codeScan": {"use": ["remote_example_name"]}} -pds.job.user.messages.folder=./build/pds-prepare/tmp/messages -pds.prepare.auto.cleanup.git.folder=true -pds.job.workspace.location=/tmp/pds-prepare/workspace -pds.prepare.module.git.enabled=true -pds.prepare.module.skopeo.enabled=true -pds.config.product.timeout.minutes=30 -pds.storage.sharedvolume.upload.dir=temp \ No newline at end of file diff --git a/sechub-wrapper-prepare/src/test/resources/init-testdata-prepare-wrapper-spring-boot.properties b/sechub-wrapper-prepare/src/test/resources/init-testdata-prepare-wrapper-spring-boot.properties new file mode 100644 index 000000000..a82817511 --- /dev/null +++ b/sechub-wrapper-prepare/src/test/resources/init-testdata-prepare-wrapper-spring-boot.properties @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: MIT +# --------------- +# common setup +# --------------- +pds.prepare.auto.cleanup.git.folder=true +pds.prepare.module.git.enabled=true +pds.prepare.module.skopeo.enabled=true + +pds.config.product.timeout.minutes=30 +pds.storage.sharedvolume.upload.dir=temp \ No newline at end of file