Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PDS prepare upload remote data to shared storage #3131

Merged
merged 29 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c98952d
Added upload classes and archive support for prepare #3026
lorriborri May 14, 2024
6e5f747
moved git download into folder #3026
lorriborri May 15, 2024
8b6c45a
Added checksum for upload files
lorriborri May 16, 2024
74f6c0c
Added test for UploadService #3026
lorriborri May 21, 2024
00a4ff3
Added unit tests for upload #3026
lorriborri May 22, 2024
e8ea8e6
Refactored PDSStorageConstants #3026
lorriborri May 24, 2024
4d2082f
Merge branch 'develop' into feature-3026-pds-prepare-upload-service
lorriborri May 24, 2024
43a6c11
Added change requests #3026
lorriborri May 24, 2024
d2b7d1c
Added change requests #3026
lorriborri May 27, 2024
e1eb1e2
Moved LogSanitizer in pds-commons-core #3026
lorriborri May 27, 2024
75ac56e
Added UploadException and LogSanitazier #3026
lorriborri May 28, 2024
55187d0
Added UsageException for wrong configurations and download fails #3026
lorriborri May 28, 2024
51e2555
Initial integration test #3026
lorriborri May 29, 2024
26da4f6
Added PDS_SORAGE environment variables to be adde to the envrionment …
lorriborri May 29, 2024
6054e12
Added integrationtest #3026
lorriborri May 31, 2024
129e07c
Added change requests #3026
lorriborri May 31, 2024
86034e2
Merge branch 'develop' into feature-3026-pds-prepare-upload-service
lorriborri May 31, 2024
c0d27f6
Removed unnecessary ENV #3026
lorriborri May 31, 2024
8561617
Refactoring + changes #3026
de-jcup Jun 3, 2024
ba0f3ab
Reduced log output and speed up integration tests #3197, #3198
de-jcup Jun 7, 2024
2dd0cb7
Fixed storage problem and enhanced integration tests #3026
de-jcup Jun 7, 2024
083b221
Refactoring and bugfixes #3026
de-jcup Jun 10, 2024
6b535c4
Skopeo call changes #3026
de-jcup Jun 10, 2024
63ce627
Changed directory cleanup from process to plain java #3026
de-jcup Jun 10, 2024
30e7e64
Changed git prepare module cleanup behavior and documentatino #3026
de-jcup Jun 11, 2024
a4ac055
Merge branch 'develop' into feature-3026-pds-prepare-upload-service
de-jcup Jun 11, 2024
87d2b9c
Review changes #3026
de-jcup Jun 12, 2024
2e87924
Merge branch 'develop' into feature-3026-pds-prepare-upload-service
de-jcup Jun 13, 2024
a1b1809
Review changes #3026
de-jcup Jun 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.pds;
package com.mercedesbenz.sechub.pds.commons.core;

import java.util.regex.Pattern;

import org.springframework.stereotype.Component;
public class PDSLogSanitizer {

/**
* This log sanitizer component handles -
* https://cwe.mitre.org/data/definitions/93.html -
* https://cwe.mitre.org/data/definitions/117.html
*
* @author Albert Tregnaghi
*
*/
@Component
public class LogSanitizer {
/**
* This log sanitizer component handles -
* https://cwe.mitre.org/data/definitions/93.html -
* https://cwe.mitre.org/data/definitions/117.html
*
* @author Albert Tregnaghi
*
*/

private static final Pattern FORGERY_PATTERN = Pattern.compile("[\t\n\r]");

Expand Down Expand Up @@ -64,5 +61,4 @@ public String sanitize(String maybeContaminated, int maxLength, boolean handleLo
}
return result;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.mercedesbenz.sechub.pds.commons.core.config;

public class PDSStorageConstants {

/* shared volume */
public static final String PDS_STORAGE_SHAREDVOLUME_UPLOAD_DIR = "pds.storage.sharedvolume.upload.dir";

/* s3 */
public static final String PDS_STORAGE_S3_ACCESSKEY = "pds.storage.s3.accesskey";

public static final String PDS_STORAGE_S3_SECRETKEY = "pds.storage.s3.secretkey";

public static final String PDS_STORAGE_S3_BUCKETNAME = "pds.storage.s3.bucketname";

public static final String PDS_STORAGE_S3_ENDPOINT = "pds.storage.s3.endpoint";

public static final String PDS_STORAGE_S3_TIMEOUT_CONNECTION_MILLISECONDS = "pds.storage.s3.timeout.connection.milliseconds";

public static final String PDS_STORAGE_S3_TIMEOUT_SOCKET_MILLISECONDS = "pds.storage.s3.timeout.socket.milliseconds";

public static final String PDS_STORAGE_S3_TIMEOUT_REQUEST_MILLISECONDS = "pds.storage.s3.timeout.request.milliseconds";

public static final String PDS_STORAGE_S3_TIMEOUT_EXECUTION_MILLISECONDS = "pds.storage.s3.timeout.execution.milliseconds";

public static final String PDS_STORAGE_S3_CONNECTION_MAX_POOLSIZE = "pds.storage.s3.connection.max.poolsize";

public static final String PDS_STORAGE_S3_CONNECTION_TTL_MILLISECONDS = "pds.storage.s3.connection.ttl.milliseconds";

public static final String PDS_STORAGE_S3_CONNECTION_IDLE_MAX_MILLISECONDS = "pds.storage.s3.connection.idle.max.milliseconds";

public static final String PDS_STORAGE_S3_CONNECTION_IDLE_VALIDATE_MILLISECONDS = "pds.storage.s3.connection.idle.validate.milliseconds";

public static final String PDS_STORAGE_S3_SIGNER_OVERRIDE = "pds.storage.s3.signer.override";

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.mercedesbenz.sechub.commons.model.CodeScanPathCollector;
import com.mercedesbenz.sechub.commons.model.SecHubConfigurationModelSupport;
import com.mercedesbenz.sechub.commons.model.SecHubDataConfigurationTypeListParser;
import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer;

/**
* This factory creates some "plain old java" objects and inject them into
Expand Down Expand Up @@ -64,4 +65,9 @@ TextFileReader createTextFileReader() {
SecHubConfigurationModelSupport createSecHubConfigurationModelSupport() {
return new SecHubConfigurationModelSupport();
}

@Bean
PDSLogSanitizer createLogSanitizer() {
return new PDSLogSanitizer();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.mercedesbenz.sechub.pds.LogSanitizer;
import com.mercedesbenz.sechub.pds.PDSNotAcceptableException;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupConfig;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupConfig.CleanupTime;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupDaysCalculator;
import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer;
import com.mercedesbenz.sechub.pds.usecase.PDSStep;
import com.mercedesbenz.sechub.pds.usecase.UseCaseAdminFetchesAutoCleanupConfiguration;
import com.mercedesbenz.sechub.pds.usecase.UseCaseAdminUpdatesAutoCleanupConfiguration;
Expand All @@ -26,7 +26,7 @@ public class PDSConfigService {
private static final Logger LOG = LoggerFactory.getLogger(PDSConfigService.class);

@Autowired
LogSanitizer logSanitizer;
PDSLogSanitizer PDSLogSanitizer;
lorriborri marked this conversation as resolved.
Show resolved Hide resolved

@Autowired
PDSConfigRepository repository;
Expand All @@ -49,7 +49,7 @@ public void updateAutoCleanupConfiguration(PDSAutoCleanupConfig configuration) {

String configurationAsJson = configuration.toJSON();

LOG.info("Admin updates auto cleanup configuration to: {}", logSanitizer.sanitize(configurationAsJson, 8192));
LOG.info("Admin updates auto cleanup configuration to: {}", PDSLogSanitizer.sanitize(configurationAsJson, 8192));

PDSConfig config = getOrCreateConfig();
config.autoCleanupConfiguration = configurationAsJson;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
import com.mercedesbenz.sechub.commons.core.security.CheckSumSupport.CheckSumValidationResult;
import com.mercedesbenz.sechub.commons.model.SecHubRuntimeException;
import com.mercedesbenz.sechub.commons.pds.data.PDSJobStatusState;
import com.mercedesbenz.sechub.pds.LogSanitizer;
import com.mercedesbenz.sechub.pds.PDSBadRequestException;
import com.mercedesbenz.sechub.pds.UploadSizeConfiguration;
import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer;
import com.mercedesbenz.sechub.pds.security.PDSRoleConstants;
import com.mercedesbenz.sechub.pds.storage.PDSMultiStorageService;
import com.mercedesbenz.sechub.pds.usecase.PDSStep;
Expand Down Expand Up @@ -71,7 +71,7 @@ public class PDSFileUploadJobService {
UploadSizeConfiguration configuration;

@Autowired
LogSanitizer logSanitizer;
PDSLogSanitizer PDSLogSanitizer;
lorriborri marked this conversation as resolved.
Show resolved Hide resolved

@Autowired
PDSServletFileUploadFactory servletFileUploadFactory;
Expand Down Expand Up @@ -222,7 +222,7 @@ private void startUpload(UUID jobUUID, HttpServletRequest request, String fileNa
fileDefinedByUser = true;
break;
default:
LOG.warn("Given field '{}' is not supported while uploading job data to project {}, {}", logSanitizer.sanitize(fieldName, 30), jobUUID);
LOG.warn("Given field '{}' is not supported while uploading job data to project {}, {}", PDSLogSanitizer.sanitize(fieldName, 30), jobUUID);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.pds.storage;

import static com.mercedesbenz.sechub.pds.commons.core.config.PDSStorageConstants.*;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

Expand All @@ -11,62 +13,63 @@
public class PDSS3PropertiesSetup implements S3Setup {

private static final String UNDEFINED = "undefined";

@PDSMustBeDocumented(value = "Defines the access key for used s3 bucket", scope = "storage", secret = true)
@Value("${pds.storage.s3.accesskey:" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
@Value("${" + PDS_STORAGE_S3_ACCESSKEY + ":" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
private String accessKey;

@PDSMustBeDocumented(value = "Defines the secret key for used s3 bucket", scope = "storage", secret = true)
@Value("${pds.storage.s3.secretkey:" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
@Value("${" + PDS_STORAGE_S3_SECRETKEY + ":" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
private String secretKey;

@PDSMustBeDocumented(value = "Defines the s3 bucket name", scope = "storage")
@Value("${pds.storage.s3.bucketname:" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
@Value("${" + PDS_STORAGE_S3_BUCKETNAME + ":" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
private String bucketName;

@PDSMustBeDocumented(value = "Defines the s3 endpoint - e.g. https://play.min.io", scope = "storage")
@Value("${pds.storage.s3.endpoint:" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
@Value("${" + PDS_STORAGE_S3_ENDPOINT + ":" + UNDEFINED + "}") // we use undefined here. Will be used in isValid
private String endpoint;

/* timeout */

@PDSMustBeDocumented(value = "S3 client timeout (in milliseconds) for creating new connections.", scope = "storage")
@Value("${pds.storage.s3.timeout.connection.milliseconds:" + S3Setup.DEFAULT_CONNECTION_TIMEOUT + "}")
@Value("${" + PDS_STORAGE_S3_TIMEOUT_CONNECTION_MILLISECONDS + ":" + S3Setup.DEFAULT_CONNECTION_TIMEOUT + "}")
private int connectionTimeoutInMilliseconds;

@PDSMustBeDocumented(value = "S3 client timeout (in milliseconds) for reading from a connected socket.", scope = "storage")
@Value("${pds.storage.s3.timeout.socket.milliseconds:" + S3Setup.DEFAULT_SOCKET_TIMEOUT + "}")
@Value("${" + PDS_STORAGE_S3_TIMEOUT_SOCKET_MILLISECONDS + ":" + S3Setup.DEFAULT_SOCKET_TIMEOUT + "}")
private int socketTimeoutInMilliseconds;

@PDSMustBeDocumented(value = "S3 client timeout (in milliseconds) for a request. 0 means it is disabled.", scope = "storage")
@Value("${pds.storage.s3.timeout.request.milliseconds:" + S3Setup.DEFAULT_REQUEST_TIMEOUT + "}")
@Value("${" + PDS_STORAGE_S3_TIMEOUT_REQUEST_MILLISECONDS + ":" + S3Setup.DEFAULT_REQUEST_TIMEOUT + "}")
private int requestTimeoutInMilliseconds;

@PDSMustBeDocumented(value = "S3 client timeout (in milliseconds) for execution. 0 means it is disabled.", scope = "storage")
@Value("${pds.storage.s3.timeout.execution.milliseconds:" + S3Setup.DEFAULT_CLIENT_EXECUTION_TIMEOUT + "}")
@Value("${" + PDS_STORAGE_S3_TIMEOUT_EXECUTION_MILLISECONDS + ":" + S3Setup.DEFAULT_CLIENT_EXECUTION_TIMEOUT + "}")
private int clientExecutionTimeoutInMilliseconds;

/* connections */

@PDSMustBeDocumented(value = "S3 client max connection pool size.", scope = "storage")
@Value("${pds.storage.s3.connection.max.poolsize:" + S3Setup.DEFAULT_MAX_CONNECTIONS + "}")
@Value("${" + PDS_STORAGE_S3_CONNECTION_MAX_POOLSIZE + ":" + S3Setup.DEFAULT_MAX_CONNECTIONS + "}")
private int maximumAllowedConnections;

@PDSMustBeDocumented(value = "S3 client expiration time (in milliseconds) for a connection in the connection pool. -1 means deactivated", scope = "storage")
@Value("${pds.storage.s3.connection.ttl.milliseconds:" + S3Setup.DEFAULT_CONNECTION_TTL + "}")
@Value("${" + PDS_STORAGE_S3_CONNECTION_TTL_MILLISECONDS + ":" + S3Setup.DEFAULT_CONNECTION_TTL + "}")
private long connectionTTLInMilliseconds;

@PDSMustBeDocumented(value = "S3 client maximum idle time (in milliseconds) for a connection in the connection pool.", scope = "storage")
@Value("${pds.storage.s3.connection.idle.max.milliseconds:" + S3Setup.DEFAULT_CONNECTION_MAX_IDLE_MILLIS + "}")
@Value("${" + PDS_STORAGE_S3_CONNECTION_IDLE_MAX_MILLISECONDS + ":" + S3Setup.DEFAULT_CONNECTION_MAX_IDLE_MILLIS + "}")
private long connectionMaxIdleInMilliseconds;

@PDSMustBeDocumented(value = "S3 client time (in milliseconds) a connection can be idle in the connection pool before it must be validated that it's still open.", scope = "storage")
@Value("${pds.storage.s3.connection.idle.validate.milliseconds:" + S3Setup.DEFAULT_VALIDATE_AFTER_INACTIVITY_MILLIS + "}")
@Value("${" + PDS_STORAGE_S3_CONNECTION_IDLE_VALIDATE_MILLISECONDS + ":" + S3Setup.DEFAULT_VALIDATE_AFTER_INACTIVITY_MILLIS + "}")
private int validateAfterInactivityInMilliseconds;

/* signer */

@PDSMustBeDocumented(value = "Can be used to override the default name of the signature algorithm used to sign requests.", scope = "storage")
@Value("${pds.storage.s3.signer.override:" + S3Setup.DEFAULT_SIGNER_OVERRIDE + "}")
@Value("${" + PDS_STORAGE_S3_SIGNER_OVERRIDE + ":" + S3Setup.DEFAULT_SIGNER_OVERRIDE + "}")
private String signerOverride;

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.pds.storage;

import static com.mercedesbenz.sechub.pds.commons.core.config.PDSStorageConstants.PDS_STORAGE_SHAREDVOLUME_UPLOAD_DIR;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

Expand All @@ -15,7 +17,7 @@ public class PDSSharedVolumePropertiesSetup extends AbstractSharedVolumeProperti
* server side will be used
*/
@PDSMustBeDocumented(value = "Defines the root path for shared volume uploads - e.g. for sourcecode.zip etc. When using keyword *temp* as path, this will create a temporary directory (for testing).", scope = "storage")
@Value("${pds.storage.sharedvolume.upload.dir:" + UNDEFINED_UPLOAD_DIR + "}") // we use undefined here. Will be used in #isValid()
@Value("${" + PDS_STORAGE_SHAREDVOLUME_UPLOAD_DIR + ":" + UNDEFINED_UPLOAD_DIR + "}") // we use undefined here. Will be used in #isValid()
private String configuredUploadDir;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.ArgumentCaptor;

import com.mercedesbenz.sechub.pds.LogSanitizer;
import com.mercedesbenz.sechub.pds.PDSNotAcceptableException;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupConfig;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupConfig.CleanupTime;
import com.mercedesbenz.sechub.pds.autocleanup.PDSAutoCleanupDaysCalculator;
import com.mercedesbenz.sechub.pds.commons.core.PDSLogSanitizer;
import com.mercedesbenz.sechub.sharedkernel.CountableInDaysTimeUnit;

class PDSConfigServiceTest {
Expand All @@ -27,7 +27,7 @@ class PDSConfigServiceTest {
private PDSConfigRepository repository;
private PDSConfigTransactionService transactionService;
private PDSAutoCleanupDaysCalculator calculator;
private LogSanitizer logSanitizer;
private PDSLogSanitizer PDSLogSanitizer;
lorriborri marked this conversation as resolved.
Show resolved Hide resolved

@BeforeEach
void beforeEach() {
Expand All @@ -36,12 +36,12 @@ void beforeEach() {
repository = mock(PDSConfigRepository.class);
transactionService = mock(PDSConfigTransactionService.class);
calculator = mock(PDSAutoCleanupDaysCalculator.class);
logSanitizer = mock(LogSanitizer.class);
PDSLogSanitizer = mock(PDSLogSanitizer.class);

serviceToTest.repository = repository;
serviceToTest.transactionService = transactionService;
serviceToTest.calculator = calculator;
serviceToTest.logSanitizer = logSanitizer;
serviceToTest.PDSLogSanitizer = PDSLogSanitizer;
}

@Test
Expand Down
5 changes: 5 additions & 0 deletions sechub-wrapper-prepare/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ dependencies {
implementation project(':sechub-commons-model')
implementation project(':sechub-commons-core')
implementation project(':sechub-commons-pds')
implementation project(':sechub-commons-archive')
implementation project(':sechub-adapter')
implementation project(':sechub-storage-core')
implementation project(':sechub-storage-sharedvolume-spring')
implementation project(':sechub-storage-s3-aws')
implementation project(':sechub-pds-commons-core')

implementation spring_boot_dependency.logback_classic

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
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.PrepareWrapperStorageService;
import com.mercedesbenz.sechub.wrapper.prepare.prepare.PrepareWrapperResultStorageService;
import com.mercedesbenz.sechub.wrapper.prepare.upload.PrepareWrapperUploadException;

@Component
public class PrepareWrapperCLI implements CommandLineRunner {
Expand All @@ -27,25 +29,37 @@ public class PrepareWrapperCLI implements CommandLineRunner {
PrepareWrapperPreparationService preparationService;

@Autowired
PrepareWrapperStorageService storageService;
PrepareWrapperResultStorageService storageService;

@Override
public void run(String... args) {
LOG.debug("Prepare wrapper starting");
LOG.debug("Prepare wrapper is starting.");
AdapterExecutionResult result;

try {
result = preparationService.startPreparation();

} catch (PrepareWrapperUploadException e) {
LOG.error("Preparation of remote data has failed. Could not upload data to shared storage. ExitCode: {}", e.getExitCode(), e);
result = getAdapterExecutionResultFailed("Could not prepare remote data, because of an internal storage error.");

} catch (PrepareWrapperUsageException e) {
/* Usage exception messages will be added to sechub messages */
LOG.error("Preparation of remote data has failed, because of wrong usage. ExitCode: {}", e.getExitCode(), e);
result = getAdapterExecutionResultFailed(e.getMessage());

} catch (Exception e) {
result = getAdapterExecutionResultFailed(e);
LOG.error("Preparation of remote data has failed.", e);
result = getAdapterExecutionResultFailed("Could not prepare remote data, because of an internal error.");
}

storeResultOrFail(result);
}

private static AdapterExecutionResult getAdapterExecutionResultFailed(Exception e) {
private static AdapterExecutionResult getAdapterExecutionResultFailed(String message) {
PrepareResult prepareResult = new PrepareResult(PrepareStatus.FAILED);
Collection<SecHubMessage> messages = new ArrayList<>();
messages.add(new SecHubMessage(SecHubMessageType.ERROR, e.getMessage()));
messages.add(new SecHubMessage(SecHubMessageType.ERROR, message));
return new AdapterExecutionResult(prepareResult.toString(), messages);
}

Expand Down
Loading
Loading