Skip to content

Commit 60bd351

Browse files
committed
Introduce PDSSafeProcessEnvironmentAccess #4209
- the new environment access handles null keys and null values and skips put operation in these cases + does log warnings - improved PDSKeyToEnvConverter + existing test
1 parent a7f7ed2 commit 60bd351

File tree

5 files changed

+250
-58
lines changed

5 files changed

+250
-58
lines changed

sechub-pds/src/main/java/com/mercedesbenz/sechub/pds/execution/PDSExecutionEnvironmentService.java

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import java.util.ArrayList;
77
import java.util.List;
88
import java.util.Map;
9-
import java.util.Map.Entry;
109
import java.util.Set;
1110
import java.util.UUID;
1211

@@ -70,7 +69,7 @@ public void initProcessBuilderEnvironmentMap(UUID pdsJobUUID, PDSJobConfiguratio
7069

7170
private void calculateAndSetupEnvironment(UUID pdsJobUUID, PDSJobConfiguration config, ProcessBuilder builder, PDSProductSetup productSetup) {
7271
/* now init environment map */
73-
Map<String, String> environment = initCleanEnvironment(productSetup, builder);
72+
PDSSafeProcessEnvironmentAccess environment = initCleanEnvironment(productSetup, builder);
7473

7574
addPdsJobRelatedVariables(pdsJobUUID, environment);
7675
addPdsExecutorJobParameters(productSetup, config, environment);
@@ -81,55 +80,57 @@ private void calculateAndSetupEnvironment(UUID pdsJobUUID, PDSJobConfiguration c
8180
LOG.debug("Initialized environment variables for script of pds job: {} with: {}", pdsJobUUID, environment);
8281
}
8382

84-
private Map<String, String> initCleanEnvironment(PDSProductSetup productSetup, ProcessBuilder builder) {
83+
private PDSSafeProcessEnvironmentAccess initCleanEnvironment(PDSProductSetup productSetup, ProcessBuilder builder) {
8584
Map<String, String> environment = builder.environment();
8685

8786
Set<String> pdsScriptEnvWhitelist = productSetup.getEnvWhitelist();
8887
LOG.debug("PDS script environment variable white list: '{}'", pdsScriptEnvWhitelist);
8988

9089
environmentCleaner.clean(environment, pdsScriptEnvWhitelist);
9190

92-
return environment;
91+
PDSSafeProcessEnvironmentAccess result = new PDSSafeProcessEnvironmentAccess(builder.environment());
92+
93+
return result;
9394

9495
}
9596

96-
private void addPdsJobRelatedVariables(UUID pdsJobUUID, Map<String, String> map) {
97+
private void addPdsJobRelatedVariables(UUID pdsJobUUID, PDSSafeProcessEnvironmentAccess envAccess) {
9798
WorkspaceLocationData locationData = workspaceService.createLocationData(pdsJobUUID);
9899

99-
map.put(PDS_JOB_WORKSPACE_LOCATION, locationData.getWorkspaceLocation());
100-
map.put(PDS_JOB_RESULT_FILE, locationData.getResultFileLocation());
101-
map.put(PDS_JOB_USER_MESSAGES_FOLDER, locationData.getUserMessagesLocation());
102-
map.put(PDS_JOB_EVENTS_FOLDER, locationData.getEventsLocation());
103-
map.put(PDS_JOB_METADATA_FILE, locationData.getMetaDataFileLocation());
104-
map.put(PDS_JOB_UUID, pdsJobUUID.toString());
105-
map.put(PDS_JOB_SOURCECODE_ZIP_FILE, locationData.getSourceCodeZipFileLocation());
106-
map.put(PDS_JOB_BINARIES_TAR_FILE, locationData.getBinariesTarFileLocation());
100+
envAccess.put(PDS_JOB_WORKSPACE_LOCATION, locationData.getWorkspaceLocation());
101+
envAccess.put(PDS_JOB_RESULT_FILE, locationData.getResultFileLocation());
102+
envAccess.put(PDS_JOB_USER_MESSAGES_FOLDER, locationData.getUserMessagesLocation());
103+
envAccess.put(PDS_JOB_EVENTS_FOLDER, locationData.getEventsLocation());
104+
envAccess.put(PDS_JOB_METADATA_FILE, locationData.getMetaDataFileLocation());
105+
envAccess.put(PDS_JOB_UUID, pdsJobUUID.toString());
106+
envAccess.put(PDS_JOB_SOURCECODE_ZIP_FILE, locationData.getSourceCodeZipFileLocation());
107+
envAccess.put(PDS_JOB_BINARIES_TAR_FILE, locationData.getBinariesTarFileLocation());
107108

108109
String extractedAssetsLocation = locationData.getExtractedAssetsLocation();
109110

110-
map.put(PDS_JOB_EXTRACTED_ASSETS_FOLDER, extractedAssetsLocation);
111+
envAccess.put(PDS_JOB_EXTRACTED_ASSETS_FOLDER, extractedAssetsLocation);
111112

112113
String extractedSourcesLocation = locationData.getExtractedSourcesLocation();
113114

114-
map.put(PDS_JOB_SOURCECODE_UNZIPPED_FOLDER, extractedSourcesLocation);
115-
map.put(PDS_JOB_EXTRACTED_SOURCES_FOLDER, extractedSourcesLocation);
115+
envAccess.put(PDS_JOB_SOURCECODE_UNZIPPED_FOLDER, extractedSourcesLocation);
116+
envAccess.put(PDS_JOB_EXTRACTED_SOURCES_FOLDER, extractedSourcesLocation);
116117

117118
String extractedBinariesLocation = locationData.getExtractedBinariesLocation();
118-
map.put(PDS_JOB_EXTRACTED_BINARIES_FOLDER, extractedBinariesLocation);
119+
envAccess.put(PDS_JOB_EXTRACTED_BINARIES_FOLDER, extractedBinariesLocation);
119120

120-
map.put(PDS_JOB_HAS_EXTRACTED_SOURCES, "" + workspaceService.hasExtractedSources(pdsJobUUID));
121-
map.put(PDS_JOB_HAS_EXTRACTED_BINARIES, "" + workspaceService.hasExtractedBinaries(pdsJobUUID));
121+
envAccess.put(PDS_JOB_HAS_EXTRACTED_SOURCES, "" + workspaceService.hasExtractedSources(pdsJobUUID));
122+
envAccess.put(PDS_JOB_HAS_EXTRACTED_BINARIES, "" + workspaceService.hasExtractedBinaries(pdsJobUUID));
122123

123124
}
124125

125-
private void addPdsExecutorJobParameters(PDSProductSetup productSetup, PDSJobConfiguration config, Map<String, String> map) {
126+
private void addPdsExecutorJobParameters(PDSProductSetup productSetup, PDSJobConfiguration config, PDSSafeProcessEnvironmentAccess envAccess) {
126127

127128
List<PDSExecutionParameterEntry> jobParams = config.getParameters();
128129
for (PDSExecutionParameterEntry jobParam : jobParams) {
129-
addJobParamDataWhenAccepted(productSetup, jobParam, map);
130+
addJobParamDataWhenAccepted(productSetup, jobParam, envAccess);
130131
}
131132

132-
addDefaultsForMissingParameters(productSetup, map);
133+
addDefaultsForMissingParameters(productSetup, envAccess);
133134

134135
}
135136

@@ -138,50 +139,51 @@ private void addPdsExecutorJobParameters(PDSProductSetup productSetup, PDSJobCon
138139
* of process builder: This map does throw an exception in this case (index of
139140
* problems)
140141
*/
141-
private void replaceNullValuesWithEmptyStrings(Map<String, String> map) {
142+
private void replaceNullValuesWithEmptyStrings(PDSSafeProcessEnvironmentAccess envAccess) {
142143

143144
List<String> keysForEntriesWithNullValue = new ArrayList<>();
144145

145-
for (Entry<String, String> entry : map.entrySet()) {
146-
if (entry.getValue() == null) {
147-
keysForEntriesWithNullValue.add(entry.getKey());
146+
for (String key : envAccess.getKeys()) {
147+
String value = envAccess.get(key);
148+
if (value == null) {
149+
keysForEntriesWithNullValue.add(key);
148150
}
149151
}
150152

151153
for (String keyForEntryWithNullValue : keysForEntriesWithNullValue) {
152-
map.put(keyForEntryWithNullValue, "");
154+
envAccess.put(keyForEntryWithNullValue, "");
153155

154156
LOG.warn("Replaced null value for key: {} with empty string", keyForEntryWithNullValue);
155157
}
156158

157159
}
158160

159-
private void addDefaultsForMissingParameters(PDSProductSetup productSetup, Map<String, String> map) {
161+
private void addDefaultsForMissingParameters(PDSProductSetup productSetup, PDSSafeProcessEnvironmentAccess envAccess) {
160162
PDSProductParameterSetup parameters = productSetup.getParameters();
161163

162-
addDefaultsForMissingParametersInList(parameters.getMandatory(), map);
163-
addDefaultsForMissingParametersInList(parameters.getOptional(), map);
164+
addDefaultsForMissingParametersInList(parameters.getMandatory(), envAccess);
165+
addDefaultsForMissingParametersInList(parameters.getOptional(), envAccess);
164166
}
165167

166-
private void addDefaultsForMissingParametersInList(List<PDSProductParameterDefinition> parameterDefinitions, Map<String, String> map) {
168+
private void addDefaultsForMissingParametersInList(List<PDSProductParameterDefinition> parameterDefinitions, PDSSafeProcessEnvironmentAccess envAccess) {
167169

168170
for (PDSProductParameterDefinition parameterDefinition : parameterDefinitions) {
169171
if (!parameterDefinition.hasDefault()) {
170172
continue;
171173
}
172174
String envVariableName = converter.convertKeyToEnv(parameterDefinition.getKey());
173175

174-
String value = map.get(envVariableName);
176+
String value = envAccess.get(envVariableName);
175177

176178
if (value == null) {
177-
map.put(envVariableName, parameterDefinition.getDefault());
179+
envAccess.put(envVariableName, parameterDefinition.getDefault());
178180
}
179181
}
180182

181183
}
182184

183-
private void addSecHubJobUUIDAsEnvironmentEntry(PDSJobConfiguration config, Map<String, String> map) {
184-
map.put(PDSLauncherScriptEnvironmentConstants.SECHUB_JOB_UUID, fetchSecHubJobUUIDasString(config));
185+
private void addSecHubJobUUIDAsEnvironmentEntry(PDSJobConfiguration config, PDSSafeProcessEnvironmentAccess envAccess) {
186+
envAccess.put(PDSLauncherScriptEnvironmentConstants.SECHUB_JOB_UUID, fetchSecHubJobUUIDasString(config));
185187
}
186188

187189
private String fetchSecHubJobUUIDasString(PDSJobConfiguration pdsJobConfiguration) {
@@ -193,7 +195,7 @@ private String fetchSecHubJobUUIDasString(PDSJobConfiguration pdsJobConfiguratio
193195
return sechubJobUUID.toString();
194196
}
195197

196-
private void addJobParamDataWhenAccepted(PDSProductSetup productSetup, PDSExecutionParameterEntry jobParam, Map<String, String> map) {
198+
private void addJobParamDataWhenAccepted(PDSProductSetup productSetup, PDSExecutionParameterEntry jobParam, PDSSafeProcessEnvironmentAccess envAccess) {
197199
PDSProductParameterSetup params = productSetup.getParameters();
198200

199201
boolean acceptedParameter = false;
@@ -214,7 +216,7 @@ private void addJobParamDataWhenAccepted(PDSProductSetup productSetup, PDSExecut
214216

215217
if (acceptedParameter) {
216218
String envVariableName = converter.convertKeyToEnv(jobParam.getKey());
217-
map.put(envVariableName, jobParam.getValue());
219+
envAccess.put(envVariableName, jobParam.getValue());
218220
} else {
219221
if (wellknown) {
220222
LOG.debug("Wellknown parameter found - but not available inside script: {}", jobParam.getKey());

sechub-pds/src/main/java/com/mercedesbenz/sechub/pds/execution/PDSKeyToEnvConverter.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,33 @@
66
import org.springframework.stereotype.Component;
77

88
@Component
9+
/**
10+
* This class provides functionality to convert keys to environment variable
11+
* format. It replaces dots with underscores and converts the string to
12+
* uppercase. Additionally, it removes any hyphens from the key.
13+
*/
914
public class PDSKeyToEnvConverter {
1015

1116
private static final Pattern P = Pattern.compile("\\.");
1217

18+
/**
19+
* Converts the given key to an environment variable format. The conversion
20+
* process includes replacing dots with underscores, converting to uppercase,
21+
* and removing hyphens.
22+
*
23+
* @param key the key to be converted. If the key is <code>null</code>,
24+
* <code>null</code> is returned.
25+
* @return the converted key in environment variable format, or
26+
* <code>null</code> if the input key is <code>null</code>.
27+
*/
1328
public String convertKeyToEnv(String key) {
1429
if (key == null) {
1530
return null;
1631
}
17-
return P.matcher(key).replaceAll("_").toUpperCase();
32+
String result = P.matcher(key).replaceAll("_").toUpperCase();
33+
if (result.indexOf('-') != -1) {
34+
result = result.replaceAll("-", "");
35+
}
36+
return result;
1837
}
1938
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// SPDX-License-Identifier: MIT
2+
package com.mercedesbenz.sechub.pds.execution;
3+
4+
import static java.util.Objects.*;
5+
6+
import java.util.Map;
7+
import java.util.Set;
8+
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
/**
13+
* This class provides safe access to process environment variables.
14+
*/
15+
public class PDSSafeProcessEnvironmentAccess {
16+
17+
private static final Logger logger = LoggerFactory.getLogger(PDSSafeProcessEnvironmentAccess.class);
18+
19+
private Map<String, String> environment;
20+
21+
public PDSSafeProcessEnvironmentAccess(Map<String, String> environment) {
22+
this.environment = requireNonNull(environment, "Parameter 'environment' may not be null!");
23+
}
24+
25+
/**
26+
* Set environment value for given key.
27+
*
28+
* @param key the key for the environment map. Operation will be skipped, if
29+
* key is <code>null</code>
30+
* @param value the value for the environment map. Operation will be skipped, if
31+
* value is <code>null</code>
32+
*/
33+
public void put(String key, String value) {
34+
if (key == null) {
35+
logger.warn("null key detected, skip put operation");
36+
return;
37+
}
38+
if (value == null) {
39+
logger.warn("null value for key '" + key + "' detected, skip put operation");
40+
return;
41+
}
42+
environment.put(key, value);
43+
}
44+
45+
public Set<String> getKeys() {
46+
return environment.keySet();
47+
}
48+
49+
public String get(String key) {
50+
return environment.get(key);
51+
}
52+
53+
}
Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,48 @@
11
// SPDX-License-Identifier: MIT
22
package com.mercedesbenz.sechub.pds.execution;
33

4-
import static org.junit.Assert.*;
4+
import static org.assertj.core.api.Assertions.*;
55

6-
import org.junit.Before;
7-
import org.junit.Test;
6+
import java.util.stream.Stream;
7+
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.extension.ExtensionContext;
10+
import org.junit.jupiter.params.ParameterizedTest;
11+
import org.junit.jupiter.params.provider.Arguments;
12+
import org.junit.jupiter.params.provider.ArgumentsProvider;
13+
import org.junit.jupiter.params.provider.ArgumentsSource;
814

915
public class PDSKeyToEnvConverterTest {
1016

1117
private PDSKeyToEnvConverter converterToTest;
1218

13-
@Before
14-
public void before() throws Exception {
19+
@BeforeEach
20+
public void beforeEach() throws Exception {
1521
converterToTest = new PDSKeyToEnvConverter();
16-
}
17-
18-
@Test
19-
public void abc_DOT_def_DOT_ghi_is_converted_to_ABC_DEF_GHI() {
20-
assertEquals("ABC_DEF_GHI", converterToTest.convertKeyToEnv("abc.def.ghi"));
21-
}
2222

23-
@Test
24-
public void empty_keeps_empty() {
25-
assertEquals("", converterToTest.convertKeyToEnv(""));
2623
}
2724

28-
@Test
29-
public void null_keeps_null() {
30-
assertEquals(null, converterToTest.convertKeyToEnv(null));
25+
@ParameterizedTest
26+
@ArgumentsSource(ConverterArgumentsProvider.class)
27+
void convertKeyToEnv_converts_origin_to_expected_result(String origin, String expectedResult) {
28+
assertThat(converterToTest.convertKeyToEnv(origin)).isEqualTo(expectedResult);
3129
}
3230

33-
@Test
34-
public void abc_becomes_ABC() {
35-
assertEquals("ABC", converterToTest.convertKeyToEnv("abc"));
31+
private static class ConverterArgumentsProvider implements ArgumentsProvider {
32+
/* @formatter:off */
33+
@Override
34+
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
35+
return Stream.of(
36+
/* origin, expectedResult */
37+
Arguments.of("abc", "ABC"),
38+
Arguments.of("abc.def.ghi", "ABC_DEF_GHI"),
39+
Arguments.of("pds.config.filefilter.EXCLUDES", "PDS_CONFIG_FILEFILTER_EXCLUDES"),
40+
Arguments.of("pds.Config.Product.timeout.minutes", "PDS_CONFIG_PRODUCT_TIMEOUT_MINUTES"),
41+
Arguments.of("all-hypens.are.re-moved", "ALLHYPHENS_ARE_REMOVED"),
42+
Arguments.of(null, null),
43+
Arguments.of("", ""));
44+
}
45+
/* @formatter:on*/
3646
}
3747

3848
}

0 commit comments

Comments
 (0)