Skip to content

Commit d68e2a1

Browse files
committed
framework-jobs: fix password obfuscation for job result
Fixes #13387 Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent a3970bb commit d68e2a1

2 files changed

Lines changed: 43 additions & 15 deletions

File tree

framework/jobs/src/main/java/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import java.util.concurrent.RejectedExecutionException;
3232
import java.util.concurrent.ScheduledExecutorService;
3333
import java.util.concurrent.TimeUnit;
34+
import java.util.regex.Matcher;
35+
import java.util.regex.Pattern;
3436

3537
import javax.inject.Inject;
3638
import javax.naming.ConfigurationException;
@@ -114,6 +116,8 @@
114116
import org.apache.logging.log4j.ThreadContext;
115117

116118
public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, ClusterManagerListener, Configurable {
119+
private static final Pattern PASSWORD_FIELD_PATTERN = Pattern.compile("\\\"password\\\":\\\"([^\\\"]*)\\\"+");
120+
117121
// Advanced
118122
public static final ConfigKey<Long> JobExpireMinutes = new ConfigKey<Long>("Advanced", Long.class, "job.expire.minutes", "1440",
119123
"Time (in minutes) for async-jobs to be kept in system", true, ConfigKey.Scope.Global);
@@ -517,22 +521,26 @@ public AsyncJob queryJob(final long jobId, final boolean updatePollTime) {
517521
}
518522

519523
public String obfuscatePassword(String result, boolean hidePassword) {
520-
if (hidePassword) {
521-
String pattern = "\"password\":";
522-
if (result != null) {
523-
if (result.contains(pattern)) {
524-
String[] resp = result.split(pattern);
525-
String psswd = resp[1].toString().split(",")[0];
526-
if (psswd.endsWith("}")) {
527-
psswd = psswd.substring(0, psswd.length() - 1);
528-
result = resp[0] + pattern + psswd.replace(psswd.substring(2, psswd.length() - 1), "*****") + "}," + resp[1].split(",", 2)[1];
529-
} else {
530-
result = resp[0] + pattern + psswd.replace(psswd.substring(2, psswd.length() - 1), "*****") + "," + resp[1].split(",", 2)[1];
531-
}
532-
}
533-
}
524+
if (!hidePassword || StringUtils.isBlank(result)) {
525+
return result;
526+
}
527+
528+
Matcher matcher = PASSWORD_FIELD_PATTERN.matcher(result);
529+
StringBuilder obfuscatedResult = new StringBuilder();
530+
while (matcher.find()) {
531+
String password = matcher.group(1);
532+
String replacement = "\"password\":\"" + obfuscatePasswordValue(password) + "\"";
533+
matcher.appendReplacement(obfuscatedResult, Matcher.quoteReplacement(replacement));
534+
}
535+
matcher.appendTail(obfuscatedResult);
536+
return obfuscatedResult.toString();
537+
}
538+
539+
private String obfuscatePasswordValue(String password) {
540+
if (StringUtils.isEmpty(password)) {
541+
return password;
534542
}
535-
return result;
543+
return password.charAt(0) + "*****";
536544
}
537545

538546
private void scheduleExecution(final AsyncJobVO job) {

framework/jobs/src/test/java/org/apache/cloudstack/framework/jobs/AsyncJobManagerTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717
package org.apache.cloudstack.framework.jobs;
1818

1919
import org.apache.cloudstack.framework.jobs.impl.AsyncJobManagerImpl;
20+
import org.apache.commons.lang3.StringUtils;
2021
import org.junit.Assert;
2122
import org.junit.Test;
2223
import org.junit.runner.RunWith;
2324
import org.mockito.Spy;
2425
import org.mockito.junit.MockitoJUnitRunner;
2526

27+
import com.cloud.utils.HumanReadableJson;
28+
2629
@RunWith (MockitoJUnitRunner.class)
2730
public class AsyncJobManagerTest {
2831

@@ -37,6 +40,12 @@ public class AsyncJobManagerTest {
3740
String inputNoBraces = "\"password\":\"password\"\",\"action\":\"OFF\"";
3841
String expectedNoBraces = "\"password\":\"p*****\",\"action\":\"OFF\"";
3942

43+
String realUserVmResponseWithPasswordInput = "{\"id\":\"f75b0990-5801-4b78-bcb0-58a503afa49c\",\"name\":\"pw-vm\"," +
44+
"\"displayname\":\"pw-vm\",\"account\":\"admin\",\"password\":\"67wSK5\",\"instancename\":\"i-2-17-VM\"," +
45+
"\"details\":{\"password\":\"3WTVryPJZJwMZGcJJ+OOYf84+uixk/1FraomPG9N6/Uvng\\u003d\\u003d\"," +
46+
"\"Message.ReservedCapacityFreed.Flag\":\"true\",\"rootDiskController\":\"osdefault\"}," +
47+
"\"arch\":\"x86_64\",\"jobid\":\"c13865d3-61ec-4269-979a-3d799181d5fe\",\"jobstatus\":0}";
48+
4049
@Test
4150
public void obfuscatePasswordTest() {
4251
String result = asyncJobManager.obfuscatePassword(input, true);
@@ -79,4 +88,15 @@ public void obfuscatePasswordTestHidePasswordNoPassword() {
7988
Assert.assertEquals(noPassword, result);
8089
}
8190

91+
@Test
92+
public void obfuscatePasswordTestHidePasswordRealInput() {
93+
String result = asyncJobManager.obfuscatePassword(realUserVmResponseWithPasswordInput, true);
94+
95+
Assert.assertNotNull(result);
96+
Assert.assertFalse(result.contains("\"password\":\"3WTVryPJZJwMZGcJJ+OOYf84+uixk\""));
97+
String jsonObject = HumanReadableJson.getHumanReadableBytesJson(result);
98+
Assert.assertTrue(StringUtils.isNotEmpty(jsonObject));
99+
Assert.assertTrue(jsonObject.contains("\"password\":\"3*****\""));
100+
}
101+
82102
}

0 commit comments

Comments
 (0)