Skip to content

Commit

Permalink
Merge branch 'develop' into feature-3026-pds-prepare-upload-service
Browse files Browse the repository at this point in the history
  • Loading branch information
lorriborri committed May 24, 2024
2 parents e8ea8e6 + f2ffc93 commit 4d2082f
Show file tree
Hide file tree
Showing 55 changed files with 2,312 additions and 672 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,17 @@ public enum SecHubConfigurationModelValidationError {

METADATA_LABEL_KEY_CONTAINS_ILLEGAL_CHARACTERS("Meta data label key contains illegal characters."),

;
REMOTE_DATA_CONFIGURATION_ONLY_FOR_ONE_SOURCE_OR_BINARY("Remote data configuration is only allowed for ONE source or for ONE binary."),

REMOTE_DATA_MIXED_WITH_FILESYSTEM_NOT_ALLOWED("Remote data configuration is not allowed to be mixed with filesystem."),

REMOTE_DATA_CONFIGURATION_LOCATION_NOT_DEFINED("Remote data configuration location is not defined."),

REMOTE_DATA_CONFIGURATION_USER_NOT_DEFINED("Remote data configuration credentials: no user is defined."),

REMOTE_DATA_CONFIGURATION_USER_NAME_NOT_DEFINED("Remote data configuration credentials: user name is not defined."),

REMOTE_DATA_CONFIGURATION_USER_PASSWORD_NOT_DEFINED("Remote data configuration credentials: user password is not defined.");

private String defaultMessage;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ private void handleScanConfigurations(InternalValidationContext context) {
private void handleLicenseScanConfiguration(InternalValidationContext context) {
Optional<SecHubLicenseScanConfiguration> licenseScanOpt = context.model.getLicenseScan();

if (!licenseScanOpt.isPresent()) {
if (licenseScanOpt.isEmpty()) {
return;
}
SecHubDataConfigurationUsageByName licenseScan = licenseScanOpt.get();
Expand All @@ -232,7 +232,7 @@ private void handleLicenseScanConfiguration(InternalValidationContext context) {
private void handleSecretScanConfiguration(InternalValidationContext context) {
Optional<SecHubSecretScanConfiguration> secretScanOpt = context.model.getSecretScan();

if (!secretScanOpt.isPresent()) {
if (secretScanOpt.isEmpty()) {
return;
}
SecHubDataConfigurationUsageByName secretScan = secretScanOpt.get();
Expand All @@ -246,7 +246,7 @@ private void handleSecretScanConfiguration(InternalValidationContext context) {

private void handleCodeScanConfiguration(InternalValidationContext context) {
Optional<SecHubCodeScanConfiguration> codeScanOpt = context.model.getCodeScan();
if (!codeScanOpt.isPresent()) {
if (codeScanOpt.isEmpty()) {
return;
}
SecHubDataConfigurationUsageByName codeScan = codeScanOpt.get();
Expand All @@ -266,7 +266,7 @@ private void handleUsages(InternalValidationContext context, SecHubDataConfigura

private void handleWebScanConfiguration(InternalValidationContext context) {
Optional<SecHubWebScanConfiguration> webScanOpt = context.model.getWebScan();
if (!webScanOpt.isPresent()) {
if (webScanOpt.isEmpty()) {
return;
}

Expand Down Expand Up @@ -308,7 +308,7 @@ private void handleIncludesAndExcludes(InternalValidationContext context, SecHub

private void handleApi(InternalValidationContext context, SecHubWebScanConfiguration webScan) {
Optional<SecHubWebScanApiConfiguration> apiOpt = webScan.getApi();
if (!apiOpt.isPresent()) {
if (apiOpt.isEmpty()) {
return;
}

Expand All @@ -318,7 +318,7 @@ private void handleApi(InternalValidationContext context, SecHubWebScanConfigura

private void handleHTTPHeaders(InternalValidationContext context, SecHubWebScanConfiguration webScan) {
Optional<List<HTTPHeaderConfiguration>> optHttpHeaders = webScan.getHeaders();
if (!optHttpHeaders.isPresent()) {
if (optHttpHeaders.isEmpty()) {
return;
}
String targetUrl = webScan.getUrl().toString();
Expand Down Expand Up @@ -495,7 +495,7 @@ private String createUrlWithoutWildCards(String url) {

private void handleInfraScanConfiguration(InternalValidationContext context) {
Optional<SecHubInfrastructureScanConfiguration> infraScanOpt = context.model.getInfraScan();
if (!infraScanOpt.isPresent()) {
if (infraScanOpt.isEmpty()) {
return;
}
SecHubInfrastructureScanConfiguration infraScan = infraScanOpt.get();
Expand All @@ -507,7 +507,7 @@ private void handleInfraScanConfiguration(InternalValidationContext context) {

private void handleDataConfiguration(InternalValidationContext context) {
Optional<SecHubDataConfiguration> dataOpt = context.model.getData();
if (!dataOpt.isPresent()) {
if (dataOpt.isEmpty()) {
return;
}

Expand All @@ -516,6 +516,11 @@ private void handleDataConfiguration(InternalValidationContext context) {
validateNameUniqueAndNotNull(context, data.getSources());
validateNameUniqueAndNotNull(context, data.getBinaries());

List<SecHubDataConfigurationObject> sourcesAndBinaries = new ArrayList<SecHubDataConfigurationObject>();
sourcesAndBinaries.addAll(data.getSources());
sourcesAndBinaries.addAll(data.getBinaries());

validateRemoteDataConfiguration(context, sourcesAndBinaries);
}

private void validateNameUniqueAndNotNull(InternalValidationContext context, Collection<? extends SecHubDataConfigurationObject> configurationObjects) {
Expand Down Expand Up @@ -552,6 +557,98 @@ private void validateNameUniqueAndNotNull(InternalValidationContext context, Col

}

private void validateRemoteDataConfiguration(InternalValidationContext context, Collection<? extends SecHubDataConfigurationObject> sourcesAndBinaries) {

SecHubConfigurationModelValidationResult result = context.result;

validateOnlyOneRemoteSourceOrBinary(sourcesAndBinaries, result);
validateRemoteAndFileSystemAreNotMixed(sourcesAndBinaries, result);
validate(sourcesAndBinaries, result);
}

private void validateOnlyOneRemoteSourceOrBinary(Collection<? extends SecHubDataConfigurationObject> sourcesAndBinaries,
SecHubConfigurationModelValidationResult result) {
for (SecHubDataConfigurationObject sourceOrBinary : sourcesAndBinaries) {
Optional<SecHubRemoteDataConfiguration> optRemoteData = sourceOrBinary.getRemote();

if (optRemoteData.isEmpty()) {
// no remote data is configured
continue;
}

// When using a remote data section it is only possible to define ONE binary or
// ONE source definition.
// Means also: It is only possible to define ONE remote data section.
boolean onlyOneBinaryOrOneSource = sourcesAndBinaries.size() == 1;
if (!onlyOneBinaryOrOneSource) {
result.addError(REMOTE_DATA_CONFIGURATION_ONLY_FOR_ONE_SOURCE_OR_BINARY);
break;
}
}
}

private void validateRemoteAndFileSystemAreNotMixed(Collection<? extends SecHubDataConfigurationObject> sourcesAndBinaries,
SecHubConfigurationModelValidationResult result) {
boolean containsFileSystem = false;
boolean containsRemote = false;

for (SecHubDataConfigurationObject sourceOrBinary : sourcesAndBinaries) {
containsRemote = containsRemote || sourceOrBinary.getRemote().isPresent();
if (sourceOrBinary instanceof SecHubFileSystemContainer) {
containsFileSystem = containsFileSystem || ((SecHubFileSystemContainer) sourceOrBinary).getFileSystem().isPresent();
}
}
if (containsFileSystem && containsRemote) {
result.addError(REMOTE_DATA_MIXED_WITH_FILESYSTEM_NOT_ALLOWED);
}
}

private void validate(Collection<? extends SecHubDataConfigurationObject> sourcesAndBinaries, SecHubConfigurationModelValidationResult result) {
for (SecHubDataConfigurationObject sourceOrBinary : sourcesAndBinaries) {
Optional<SecHubRemoteDataConfiguration> optRemoteData = sourceOrBinary.getRemote();

if (optRemoteData.isEmpty()) {
// no remote data is configured
continue;
}

String uniqueName = sourceOrBinary.getUniqueName();
SecHubRemoteDataConfiguration remoteData = optRemoteData.get();

if (remoteData.getLocation() == null || remoteData.getLocation().isBlank()) {
result.addError(REMOTE_DATA_CONFIGURATION_LOCATION_NOT_DEFINED, "Remote data location is not defined for " + uniqueName);
}

validateRemoteDataCredentials(result, remoteData, uniqueName);
}
}

private void validateRemoteDataCredentials(SecHubConfigurationModelValidationResult result, SecHubRemoteDataConfiguration remoteData, String uniqueName) {
if (remoteData.getCredentials().isEmpty()) {
// credentials don't need to be defined for public accessible remote data
return;
}
SecHubRemoteCredentialConfiguration remoteCredential = remoteData.getCredentials().get();
if (remoteCredential.getUser().isEmpty()) {
result.addError(REMOTE_DATA_CONFIGURATION_USER_NOT_DEFINED, "Remote data configuration credentials: no user is defined for " + uniqueName);

} else {
SecHubRemoteCredentialUserData user = remoteCredential.getUser().get();

String name = user.getName();
if (name == null || name.isBlank()) {
result.addError(REMOTE_DATA_CONFIGURATION_USER_NAME_NOT_DEFINED,
"Remote data configuration credentials: user name is not defined for " + uniqueName);
}

String password = user.getPassword();
if (password == null || password.isBlank()) {
result.addError(REMOTE_DATA_CONFIGURATION_USER_PASSWORD_NOT_DEFINED,
"Remote data configuration credentials: user password is not defined for " + uniqueName);
}
}
}

private boolean hasAtLeastOneScanConfiguration(InternalValidationContext context) {
boolean atLeastOne = false;
SecHubConfigurationModel model = context.model;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
package com.mercedesbenz.sechub.commons.model;

import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonProperty;

public interface SecHubDataConfigurationObject {
Expand All @@ -16,6 +18,8 @@ public interface SecHubDataConfigurationObject {
* <code>null</code>
*/
@JsonProperty("name")
public String getUniqueName();
String getUniqueName();

Optional<SecHubRemoteDataConfiguration> getRemote();

}
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,127 @@ void when_sechub_config_has_exactly_maximum_size_allowed_error_SECHUB_CONFIGURAT
assertHasNotError(result, SECHUB_CONFIGURATION_TOO_LARGE);
}

@ParameterizedTest
@ValueSource(strings = { "src/test/resources/sechub_remote_data_config_binary_code_scan_example.json",
"src/test/resources/sechub_remote_data_config_source_code_scan_example.json" })
void when_remote_sechub_configuration_is_valid_no_errors_are_reported(String file) {
String json = TestFileReader.loadTextFile(file);
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertHasNoErrors(result);
}

@Test
void when_multiple_remote_configurations_are_configured_error_REMOTE_DATA_CONFIGURATION_ONLY_FOR_ONE_SOURCE_OR_BINARY() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_multi_config.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_ONLY_FOR_ONE_SOURCE_OR_BINARY);
}

@Test
void when_remote_configuration_location_is_not_defined_error_REMOTE_DATA_CONFIGURATION_LOCATION_NOT_DEFINED() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_missing_location.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_LOCATION_NOT_DEFINED);
}

@Test
void when_remote_configuration_has_empty_credentials_error_REMOTE_DATA_CONFIGURATION_USER_NOT_DEFINED() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_credentials_empty.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_USER_NOT_DEFINED);
}

@Test
void when_remote_configuration_credential_user_has_no_username_error_REMOTE_DATA_CONFIGURATION_USER_NAME_NOT_DEFINED() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_user_credential_missing_username.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_USER_NAME_NOT_DEFINED);
}

@Test
void when_remote_configuration_credential_user_has_no_password_error_REMOTE_DATA_CONFIGURATION_USER_PASSWORD_NOT_DEFINED() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_user_credential_missing_password.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_USER_PASSWORD_NOT_DEFINED);
}

@Test
void when_remote_configuration_is_mixed_with_filesystem_REMOTE_REMOTE_DATA_MIXED_WITH_FILESYSTEM_NOT_ALLOWED() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_config_with_filesystem.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_MIXED_WITH_FILESYSTEM_NOT_ALLOWED);
}

@Test
void when_remote_data_is_configured_for_binaries_and_sources_error() {
/* prepare */
String json = TestFileReader.loadTextFile("src/test/resources/sechub_remote_data_config_invalid_source_and_binaries.json");
SecHubScanConfiguration sechubConfiguration = SecHubScanConfiguration.createFromJSON(json);
modelSupportCollectedScanTypes.add(ScanType.CODE_SCAN);

/* execute */
SecHubConfigurationModelValidationResult result = validatorToTest.validate(sechubConfiguration);

/* test */
assertTrue(result.hasErrors());
assertHasError(result, REMOTE_DATA_CONFIGURATION_ONLY_FOR_ONE_SOURCE_OR_BINARY);

}

private SecHubConfigurationModel createSecHubConfigModelWithExactly8193Characters() {
// 128*64 = 8192, so we take 127 because of the overhead of the JSON model:
// {"apiVersion":""} = 17 characters so we need to add 48 characters afterwards
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"apiVersion": "1.0",
"data": {
"sources": [
{
"name": "filesystem_example_1",
"fileSystem" : {
"folders" : [ "myProject/src" ]
}
},
{
"name": "remote_example_name",
"remote": {
"location": "remote_example_location",
"type": "git",
"credentials": {
"user": {
"name": "my-example-user",
"password": "my-example-password"
}
}
}
},
{
"name": "filesystem_example",
"fileSystem" : {
"folders" : [ "myProject/build" ]
}
}
]
},
"codeScan": {
"use": [
"remote_example_name"
]
}
}

0 comments on commit 4d2082f

Please sign in to comment.