Skip to content

Commit 0f099c6

Browse files
committed
Adding fixes after disposable UPS functionality
LMCROSSITXSADEPLOY-2301
1 parent ae8c16d commit 0f099c6

File tree

20 files changed

+115
-187
lines changed

20 files changed

+115
-187
lines changed

multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/security/encryption/AesEncryptionUtil.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ public class AesEncryptionUtil {
2121

2222
public static byte[] encrypt(String plainText, byte[] encryptionKey) {
2323
try {
24-
if (plainText == null) {
25-
plainText = "";
26-
}
2724
byte[] gcmInitialisationVector = new byte[Constants.INITIALISATION_VECTOR_LENGTH];
2825
new SecureRandom().nextBytes(gcmInitialisationVector);
2926

@@ -67,7 +64,7 @@ private static Cipher setUpCipherObject(byte[] encryptionKey, byte[] gcmInitiali
6764
Cipher cipherObject = Cipher.getInstance(Constants.CIPHER_TRANSFORMATION_NAME, BouncyCastleFipsProvider.PROVIDER_NAME);
6865
SecretKeySpec secretKeySpec = new SecretKeySpec(encryptionKey, Constants.ENCRYPTION_DECRYPTION_ALGORITHM_NAME);
6966
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(Constants.GCM_AUTHENTICATION_TAG_LENGTH, gcmInitialisationVector);
70-
67+
7168
cipherObject.init(cipherMode, secretKeySpec, gcmParameterSpec);
7269

7370
return cipherObject;

multiapps-controller-core/src/test/java/org/cloudfoundry/multiapps/controller/core/security/encryption/AesEncryptionUtilTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
public class AesEncryptionUtilTest {
2121

2222
private static final byte[] KEY_FOR_256_32_BYTES = "abcdefghijklmnopqrstuvwxyz123456".getBytes(StandardCharsets.UTF_8);
23+
private static final byte[] SECOND_KEY_FOR_256_32_BYTES = "0123456789abcdef0123456789ABCDEF".getBytes(StandardCharsets.UTF_8);
2324

2425
@BeforeAll
2526
static void addBouncyCastleProvider() throws Exception {
@@ -87,8 +88,7 @@ void testEncryptDecryptFlowWhenWrongEncryptionKey() {
8788
String plainText = "top secret";
8889
byte[] encrypted = AesEncryptionUtil.encrypt(plainText, KEY_FOR_256_32_BYTES);
8990

90-
byte[] differentValidKey = "0123456789abcdef0123456789ABCDEF".getBytes(StandardCharsets.UTF_8);
91-
assertThrows(SLException.class, () -> AesEncryptionUtil.decrypt(encrypted, differentValidKey));
91+
assertThrows(SLException.class, () -> AesEncryptionUtil.decrypt(encrypted, SECOND_KEY_FOR_256_32_BYTES));
9292
}
9393

9494
@Test

multiapps-controller-process/src/main/java/module-info.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
requires flowable.variable.service.api;
3737
requires jakarta.annotation;
3838
requires jakarta.persistence;
39-
requires java.annotation;
4039
requires java.sql;
4140
requires jakarta.xml.bind;
4241
requires jakarta.inject;
@@ -52,23 +51,18 @@
5251
requires org.cloudfoundry.multiapps.controller.persistence;
5352
requires org.cloudfoundry.multiapps.mta;
5453
requires org.joda.time;
55-
requires org.mybatis;
5654
requires org.slf4j;
5755
requires spring.beans;
5856
requires spring.context;
5957
requires spring.core;
6058
requires spring.security.oauth2.core;
6159
requires spring.web;
62-
requires tools.jackson.databind;
6360
requires reactor.netty;
6461
requires io.netty.handler;
6562
requires io.netty.transport;
6663

6764
requires static java.compiler;
6865
requires static org.immutables.value;
6966
requires org.cloudfoundry.multiapps.controller.shutdown.client;
70-
requires org.checkerframework.checker.qual;
71-
requires s3;
72-
requires org.eclipse.persistence.jpa;
7367

7468
}

multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Constants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class Constants {
3535
public static final String DOUBLE_APPENDED_STRING = "%s%s";
3636
public static final String TRIPLE_APPENDED_STRING = "%s%s%s";
3737
public static final String SECURE_EXTENSION_DESCRIPTOR_ID = "__mta.secure";
38+
public static final String STRING_SEPARATOR = "-";
3839

3940
public static final Long UNSET_LAST_LOG_TIMESTAMP_MS = 0L;
4041
public static final int LOG_STALLED_TASK_MINUTE_INTERVAL = 5;

multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/Messages.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public class Messages {
8484
public static final String SERVICE_INSTANCE_0_TAGS_UPDATE_FAILED_ERROR_1 = "Service instance: \"{0}\" tags update failed, error: \"{1}\"";
8585
public static final String COULD_NOT_RETRIEVE_USER_PROVIDED_SERVICE_INSTANCE_ENCRYPTION_RELATED = "Could not retrieve service instance (user provided service instance for encryption/decryption related)!";
8686
public static final String COULD_NOT_RETRIEVE_CREDENTIALS_FROM_USER_PROVIDED_SERVICE_INSTANCE_ENCRYPTION_RELATED = "Could not retrieve credentials from service instance (user provided service instance for encryption/decryption related)!";
87-
public static final String JSON_TRANSFORMATION_FAILED_FOR_VARIABLE_0 = "Secret token JSON transformation failed for variable \"{0}\":";
87+
public static final String JSON_TRANSFORMATION_FAILED_FOR_VARIABLE_0 = "Secret token JSON transformation failed for variable \"{0}\": \"{1}\"";
8888
public static final String SECRET_VALUE_NOT_FOUND_FOR_TOKEN_0_PID_1_VARIABLE_2 = "Secret value not found for token \"{0}\" (process instance id=\"{1}\", variable=\"{2}\")";
8989
public static final String INVALID_ENCRYPTION_KEY_LENGTH = "Length of the encryption key is invalid - it must be 32 characters long!";
9090
public static final String MISSING_MTA_ID_IN_ENCRYPTION_KEY_RESOLVER = "Missing mtaId in encryption key resolver! Cannot continue from here!";
@@ -801,8 +801,8 @@ public class Messages {
801801

802802
public static final String SECURE_EXTENSION_DESCRIPTOR_CONSTRUCTED_AND_APPLIED_FROM_ENVIRONMENT_VARIABLES = "\n\"SECURE EXTENSION DESCRIPTOR CONSTRUCTED AND APPLIED FROM ENVIRONMENT VARIABLES\"";
803803
public static final String DISPOSABLE_USER_PROVIDED_SERVICE_0_DELETED = "Disposable user-provided service \"{0}\" deleted";
804-
public static final String USING_DISPOSABLE_USER_PROVIDED_SERVICE_0_ = "Using disposable user-provided service \"{0}\"";
805-
public static final String USING_DEFAULT_USER_PROVIDED_SERVICE_0_ = "Using default user-provided service \"{0}\"";
804+
public static final String USING_DISPOSABLE_USER_PROVIDED_SERVICE_0 = "Using disposable user-provided service \"{0}\"";
805+
public static final String USING_DEFAULT_USER_PROVIDED_SERVICE_0 = "Using default user-provided service \"{0}\"";
806806
public static final String TOTAL_SIZE_OF_ALL_RESOLVED_CONTENT_0 = "Total size for all resolved content {0}";
807807
public static final String STARTED_SHUTTING_DOWN_APPLICATION_WITH_ID_AND_INDEX = "Started shutting down application with ID: \"{0}\" and index: \"{1}\"";
808808
public static final String SHUT_DOWN_APPLICATION_WITH_ID_AND_INDEX_FINISHED_SUCCESSFULLY = "Shut down application with ID: \"{0}\" and index: \"{1}\" finished successfully";

multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/security/SecretParametersCollector.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@
2828
import org.cloudfoundry.multiapps.mta.model.Resource;
2929
import org.cloudfoundry.multiapps.mta.model.ResourceType;
3030
import org.cloudfoundry.multiapps.mta.model.Visitor;
31-
import org.springframework.stereotype.Component;
3231

33-
@Component
3432
public class SecretParametersCollector extends Visitor {
3533

3634
private final Set<String> secretParameters = new HashSet<>();
@@ -63,15 +61,16 @@ private void addInNestedParameters(Map.Entry<String, Collection<String>> element
6361
continue;
6462
}
6563

66-
shouldBeAddedInNestedParameters(secretParameters, nestedParameters, value, currentParameterName);
64+
determineWhetherToAddInNestedParameters(nestedParameters, value, currentParameterName);
6765
}
6866
}
6967

70-
private void shouldBeAddedInNestedParameters(Set<String> secretParameters, Set<String> nestedParameters, String value,
71-
String currentParameterName) {
68+
private void determineWhetherToAddInNestedParameters(Set<String> nestedParameters, String value,
69+
String currentParameterName) {
7270
for (String secretParameter : secretParameters) {
7371
if (!secretParameter.isEmpty() && value.contains(secretParameter)) {
7472
nestedParameters.add(currentParameterName);
73+
break;
7574
}
7675
}
7776
}

multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/security/SecretTokenSerializer.java

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,16 @@
2323
import org.cloudfoundry.multiapps.controller.process.security.util.SecretTokenUtil;
2424
import org.cloudfoundry.multiapps.controller.process.variables.Serializer;
2525
import org.flowable.common.engine.api.variable.VariableContainer;
26-
import org.slf4j.Logger;
27-
import org.slf4j.LoggerFactory;
2826

2927
public class SecretTokenSerializer<T> implements Serializer<T> {
3028

31-
private static final Logger LOGGER = LoggerFactory.getLogger(SecretTokenSerializer.class);
32-
3329
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
3430

3531
private final Serializer<T> serializer;
3632

3733
private final SecretTokenStore secretTokenStore;
3834

39-
private final Set<String> secretValues;
35+
private final Set<String> secretValueNames;
4036

4137
private final String processInstanceId;
4238

@@ -47,7 +43,7 @@ public SecretTokenSerializer(Serializer<T> serializer, SecretTokenStore secretTo
4743
String variableName) {
4844
this.serializer = serializer;
4945
this.secretTokenStore = secretTokenStore;
50-
this.secretValues = secretValues;
46+
this.secretValueNames = secretValues;
5147
this.processInstanceId = processInstanceId;
5248
this.variableName = variableName;
5349
}
@@ -140,19 +136,21 @@ private Object handleBytes(byte[] bytesArray, boolean censor) {
140136

141137
private Object handleList(List<Object> list, boolean censor) {
142138
return list.stream()
143-
.map(element -> {
144-
if (element instanceof String) {
145-
String transformedJson = transformJson((String) element, censor);
146-
return getResultFromTransformedJson(transformedJson, element, false);
147-
} else if (element instanceof byte[]) {
148-
String transformedJson = transformJson(new String((byte[]) element), censor);
149-
return getResultFromTransformedJson(transformedJson, element, true);
150-
}
151-
return element;
152-
})
139+
.map(element -> transformListElement(element, censor))
153140
.collect(Collectors.toList());
154141
}
155142

143+
private Object transformListElement(Object element, boolean censor) {
144+
if (element instanceof String) {
145+
String transformedJson = transformJson((String) element, censor);
146+
return getResultFromTransformedJson(transformedJson, element, false);
147+
} else if (element instanceof byte[]) {
148+
String transformedJson = transformJson(new String((byte[]) element), censor);
149+
return getResultFromTransformedJson(transformedJson, element, true);
150+
}
151+
return element;
152+
}
153+
156154
private Object getResultFromTransformedJson(String transformedJson, Object element, boolean isElementInstanceOfByte) {
157155
if (transformedJson != null) {
158156
if (!isElementInstanceOfByte) {
@@ -166,43 +164,28 @@ private Object getResultFromTransformedJson(String transformedJson, Object eleme
166164
}
167165

168166
private String transformJson(String candidate, boolean censor) {
169-
if (!isValid(candidate)) {
170-
return null;
171-
}
172-
173167
try {
174168
JsonNode rootNode = OBJECT_MAPPER.readTree(candidate);
175169
AtomicBoolean changed = new AtomicBoolean();
176-
JsonNode output = processJsonValue(rootNode, secretValues, censor, changed);
170+
JsonNode output = processJsonValue(rootNode, secretValueNames, censor, changed);
177171

178172
if (changed.get()) {
179173
return OBJECT_MAPPER.writeValueAsString(output);
180174
}
181175
return null;
182-
} catch (Exception e) {
183-
LOGGER.info("transformJson failed for var {} (more info = {}): {}: {}", variableName, candidate, e.getClass()
184-
.getSimpleName(),
185-
e.getMessage());
186-
throw new SLException(MessageFormat.format(Messages.JSON_TRANSFORMATION_FAILED_FOR_VARIABLE_0, variableName), e);
187-
}
188-
}
189-
190-
public boolean isValid(String json) {
191-
try {
192-
OBJECT_MAPPER.readTree(json);
193176
} catch (JacksonException e) {
194-
return false;
177+
throw new SLException(MessageFormat.format(Messages.JSON_TRANSFORMATION_FAILED_FOR_VARIABLE_0, variableName, e.getMessage()),
178+
e);
195179
}
196-
return true;
197180
}
198181

199-
private JsonNode processJsonValue(JsonNode currentNode, Set<String> keys, boolean censor, AtomicBoolean changed) {
182+
private JsonNode processJsonValue(JsonNode currentNode, Set<String> secretValueNames, boolean censor, AtomicBoolean changed) {
200183
if (currentNode.isObject()) {
201-
return processObjectNode(currentNode, keys, censor, changed);
184+
return processObjectNode(currentNode, secretValueNames, censor, changed);
202185
}
203186

204187
if (currentNode.isArray()) {
205-
return processArrayNode(currentNode, keys, censor, changed);
188+
return processArrayNode(currentNode, secretValueNames, censor, changed);
206189
}
207190

208191
if (currentNode.isTextual()) {
@@ -212,7 +195,7 @@ private JsonNode processJsonValue(JsonNode currentNode, Set<String> keys, boolea
212195
return currentNode;
213196
}
214197

215-
private JsonNode processObjectNode(JsonNode currentNode, Set<String> keys, boolean censor, AtomicBoolean changed) {
198+
private JsonNode processObjectNode(JsonNode currentNode, Set<String> secretValueNames, boolean censor, AtomicBoolean changed) {
216199
ObjectNode objectNode = currentNode.deepCopy();
217200

218201
List<String> fields = new ArrayList<>();
@@ -221,36 +204,40 @@ private JsonNode processObjectNode(JsonNode currentNode, Set<String> keys, boole
221204
while (fieldsIterator.hasNext()) {
222205
fields.add(fieldsIterator.next());
223206
}
207+
processObjectNodeFields(fields, objectNode, changed, censor);
224208

209+
return objectNode;
210+
}
211+
212+
private void processObjectNodeFields(List<String> fields, ObjectNode objectNode, AtomicBoolean changed, boolean censor) {
225213
for (String currentField : fields) {
226214
JsonNode childNode = objectNode.get(currentField);
227-
JsonNode processedNode = processJsonValue(childNode, keys, censor, changed);
215+
JsonNode processedNode = processJsonValue(childNode, secretValueNames, censor, changed);
228216

229-
boolean isCurrentKeySecretValue = keys.contains(currentField);
230-
determineWhetherToCensorOrUncensor(childNode, processedNode, objectNode, currentField, censor, isCurrentKeySecretValue,
231-
changed);
217+
boolean isCurrentKeySecretValue = secretValueNames.contains(currentField);
218+
determineWhetherToEncodeOrDecode(childNode, processedNode, objectNode, currentField, censor, isCurrentKeySecretValue,
219+
changed);
232220
}
233-
return objectNode;
234221
}
235222

236-
private void determineWhetherToCensorOrUncensor(JsonNode childNode, JsonNode processedNode, ObjectNode objectNode, String currentField,
237-
boolean censor, boolean isCurrentKeySecretValue, AtomicBoolean changed) {
223+
private void determineWhetherToEncodeOrDecode(JsonNode childNode, JsonNode processedNode, ObjectNode objectNode, String currentField,
224+
boolean censor, boolean isCurrentKeySecretValue, AtomicBoolean changed) {
238225
if (isCurrentKeySecretValue && childNode.isValueNode()) {
239226
String currentValue = convertChildNodeToText(childNode);
240227
if (censor) {
241-
censorValue(objectNode, currentValue, currentField, changed);
228+
encodeValue(objectNode, currentValue, currentField, changed);
242229
} else {
243-
uncensorValue(objectNode, currentValue, currentField, changed, processedNode);
230+
decodeValue(objectNode, currentValue, currentField, changed, processedNode);
244231
}
245232
} else {
246233
objectNode.set(currentField, processedNode);
247234
}
248235
}
249236

250-
private JsonNode processArrayNode(JsonNode currentNode, Set<String> keys, boolean censor, AtomicBoolean changed) {
237+
private JsonNode processArrayNode(JsonNode currentNode, Set<String> secretValueNames, boolean censor, AtomicBoolean changed) {
251238
ArrayNode arrayNode = currentNode.deepCopy();
252239
for (int i = 0; i < arrayNode.size(); i++) {
253-
arrayNode.set(i, processJsonValue(arrayNode.get(i), keys, censor, changed));
240+
arrayNode.set(i, processJsonValue(arrayNode.get(i), secretValueNames, censor, changed));
254241
}
255242
return arrayNode;
256243
}
@@ -265,7 +252,7 @@ private JsonNode processTextualNode(JsonNode currentNode, boolean censor, Atomic
265252
return currentNode;
266253
}
267254

268-
private void censorValue(ObjectNode objectNode, String currentValue, String currentField, AtomicBoolean changed) {
255+
private void encodeValue(ObjectNode objectNode, String currentValue, String currentField, AtomicBoolean changed) {
269256
if (SecretTokenUtil.isSecretToken(currentValue) || isPlaceholder(currentValue)) {
270257
objectNode.put(currentField, currentValue);
271258
} else {
@@ -274,8 +261,8 @@ private void censorValue(ObjectNode objectNode, String currentValue, String curr
274261
}
275262
}
276263

277-
private void uncensorValue(ObjectNode objectNode, String currentValue, String currentField, AtomicBoolean changed,
278-
JsonNode processedNode) {
264+
private void decodeValue(ObjectNode objectNode, String currentValue, String currentField, AtomicBoolean changed,
265+
JsonNode processedNode) {
279266
if (SecretTokenUtil.isSecretToken(currentValue)) {
280267
String detokenizedValue = detokenize(currentValue);
281268
JsonNode jsonConverted = forceToInteger(detokenizedValue);

0 commit comments

Comments
 (0)