From 5bae18270ec37f5b1b0e1205ca8493e87f1a9508 Mon Sep 17 00:00:00 2001 From: "chenyoulong20g@ict.ac.cn" Date: Sat, 8 Nov 2025 10:30:11 +0800 Subject: [PATCH 1/9] fix that log sensitive infomation in cmd of script --- ...bvirtUpdateHostPasswordCommandWrapper.java | 3 +- ...itrixUpdateHostPasswordCommandWrapper.java | 5 +- .../java/com/cloud/utils/script/Script.java | 216 +++++++++++++++--- .../com/cloud/utils/script/ScriptTest.java | 30 +++ 4 files changed, 214 insertions(+), 40 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUpdateHostPasswordCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUpdateHostPasswordCommandWrapper.java index b8fe0ded716..80c723b5a6e 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUpdateHostPasswordCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtUpdateHostPasswordCommandWrapper.java @@ -37,7 +37,8 @@ public final class LibvirtUpdateHostPasswordCommandWrapper extends CommandWrappe final String newPassword = command.getNewPassword(); final Script script = libvirtUtilitiesHelper.buildScript(libvirtComputingResource.getUpdateHostPasswdPath()); - script.add(username, newPassword); + script.add(username); + script.addSensitive(newPassword); final String result = script.execute(); if (result != null) { diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixUpdateHostPasswordCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixUpdateHostPasswordCommandWrapper.java index 1acc292b450..178121a9b48 100644 --- a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixUpdateHostPasswordCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixUpdateHostPasswordCommandWrapper.java @@ -45,9 +45,10 @@ public final class CitrixUpdateHostPasswordCommandWrapper extends CommandWrapper Pair result; try { - logger.debug("Executing command in Host: " + cmdLine); + logger.debug("Executing command in Host: " + xenServerUtilitiesHelper.buildCommandLine(SCRIPT_CMD_PATH, + VRScripts.UPDATE_HOST_PASSWD, username, "******")); final String hostPassword = citrixResourceBase.getPwdFromQueue(); - result = xenServerUtilitiesHelper.executeSshWrapper(hostIp, 22, username, null, hostPassword, cmdLine.toString()); + result = xenServerUtilitiesHelper.executeSshWrapper(hostIp, 22, username, null, hostPassword, cmdLine); } catch (final Exception e) { return new Answer(command, false, e.getMessage()); } diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 6c62c910648..f43d67d0764 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -30,8 +30,10 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Properties; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -66,8 +68,10 @@ public class Script implements Callable { private boolean _passwordCommand = false; private boolean avoidLoggingCommand = false; + private final Set sensitiveArgIndices = new HashSet<>(); - private static final ScheduledExecutorService s_executors = Executors.newScheduledThreadPool(10, new NamedThreadFactory("Script")); + private static final ScheduledExecutorService s_executors = Executors.newScheduledThreadPool(10, + new NamedThreadFactory("Script")); String _workDir; ArrayList _command; @@ -143,6 +147,11 @@ public class Script implements Callable { _command.add(param); } + public void addSensitive(String param) { + _command.add(param); + sensitiveArgIndices.add(_command.size() - 1); + } + public Script set(String name, String value) { _command.add(name); _command.add(value); @@ -161,7 +170,7 @@ public class Script implements Callable { if (sanitizeViCmdParameter(cmd, builder) || sanitizeRbdFileFormatCmdParameter(cmd, builder)) { continue; } - if (obscureParam) { + if (obscureParam || sensitiveArgIndices.contains(i)) { builder.append("******").append(" "); obscureParam = false; } else { @@ -238,12 +247,16 @@ public class Script implements Callable { public String execute(OutputInterpreter interpreter) { String[] command = _command.toArray(new String[_command.size()]); String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && !avoidLoggingCommand) { + if (_logger.isDebugEnabled() && !avoidLoggingCommand && sensitiveArgIndices.isEmpty()) { _logger.debug(String.format("Executing command [%s].", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); } try { - _logger.trace(String.format("Creating process for command [%s].", commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format("Creating process for command [%s].", commandLine)); + } else { + _logger.trace("Creating process for command with sensitive arguments."); + } ProcessBuilder pb = new ProcessBuilder(command); pb.redirectErrorStream(true); if (_workDir != null) @@ -261,48 +274,126 @@ public class Script implements Callable { _thread = Thread.currentThread(); ScheduledFuture future = null; if (_timeout > 0) { - _logger.trace(String.format("Scheduling the execution of command [%s] with a timeout of [%s] milliseconds.", commandLine, _timeout)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format( + "Scheduling the execution of command [%s] with a timeout of [%s] milliseconds.", + commandLine, _timeout)); + } else { + _logger.trace(String.format( + "Scheduling the execution of command with sensitive arguments with a timeout of [%s] milliseconds.", + _timeout)); + } future = s_executors.schedule(this, _timeout, TimeUnit.MILLISECONDS); } long processPid = _process.pid(); Task task = null; if (interpreter != null && interpreter.drain()) { - _logger.trace(String.format("Executing interpreting task of process [%s] for command [%s].", processPid, commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format("Executing interpreting task of process [%s] for command [%s].", + processPid, commandLine)); + } else { + _logger.trace(String.format( + "Executing interpreting task of process [%s] for command with sensitive arguments.", + processPid)); + } task = new Task(interpreter, ir); s_executors.execute(task); } while (true) { - _logger.trace(String.format("Attempting process [%s] execution for command [%s] with timeout [%s].", processPid, commandLine, _timeout)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format("Attempting process [%s] execution for command [%s] with timeout [%s].", + processPid, commandLine, _timeout)); + } else { + _logger.trace(String.format( + "Attempting process [%s] execution for command with sensitive arguments with timeout [%s].", + processPid, _timeout)); + } try { if (_process.waitFor(_timeout, TimeUnit.MILLISECONDS)) { - _logger.trace(String.format("Process [%s] execution for command [%s] completed within timeout period [%s].", processPid, commandLine, - _timeout)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format( + "Process [%s] execution for command [%s] completed within timeout period [%s].", + processPid, commandLine, + _timeout)); + } else { + _logger.trace(String.format( + "Process [%s] execution for command with sensitive arguments completed within timeout period [%s].", + processPid, + _timeout)); + } if (_process.exitValue() == 0) { - _logger.debug(String.format("Successfully executed process [%s] for command [%s].", processPid, commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.debug(String.format("Successfully executed process [%s] for command [%s].", + processPid, commandLine)); + } else { + _logger.debug(String.format( + "Successfully executed process [%s] for command with sensitive arguments.", + processPid)); + } if (interpreter != null) { if (interpreter.drain()) { - _logger.trace(String.format("Returning task result of process [%s] for command [%s].", processPid, commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace( + String.format("Returning task result of process [%s] for command [%s].", + processPid, commandLine)); + } else { + _logger.trace(String.format( + "Returning task result of process [%s] for command with sensitive arguments.", + processPid)); + } return task.getResult(); } - _logger.trace(String.format("Returning interpretation of process [%s] for command [%s].", processPid, commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace( + String.format("Returning interpretation of process [%s] for command [%s].", + processPid, commandLine)); + } else { + _logger.trace(String.format( + "Returning interpretation of process [%s] for command with sensitive arguments.", + processPid)); + } return interpreter.interpret(ir); } else { // null return exitValue apparently - _logger.trace(String.format("Process [%s] for command [%s] exited with value [%s].", processPid, commandLine, - _process.exitValue())); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format("Process [%s] for command [%s] exited with value [%s].", + processPid, commandLine, + _process.exitValue())); + } else { + _logger.trace(String.format( + "Process [%s] for command with sensitive arguments exited with value [%s].", + processPid, + _process.exitValue())); + } return String.valueOf(_process.exitValue()); } } else { - _logger.warn(String.format("Execution of process [%s] for command [%s] failed.", processPid, commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Execution of process [%s] for command [%s] failed.", + processPid, commandLine)); + } else { + _logger.warn(String.format( + "Execution of process [%s] for command with sensitive arguments failed.", + processPid)); + } break; } } } catch (InterruptedException e) { if (!_isTimeOut) { - _logger.debug(String.format("Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command " - + "[%s].", e.getMessage(), processPid, commandLine), e); + if (sensitiveArgIndices.isEmpty()) { + _logger.debug(String.format( + "Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command " + + "[%s].", + e.getMessage(), processPid, commandLine), e); + } else { + _logger.debug(String.format( + "Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command " + + "with sensitive arguments.", + e.getMessage(), processPid), e); + } continue; } } finally { @@ -315,18 +406,33 @@ public class Script implements Callable { TimedOutLogger log = new TimedOutLogger(_process); Task timedoutTask = new Task(log, ir); - _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, commandLine)); - timedoutTask.run(); - if (!_passwordCommand) { - _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, commandLine, timedoutTask.getResult())); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, + commandLine)); } else { - _logger.warn(String.format("Process [%s] for command [%s] timed out.", processPid, commandLine)); + _logger.trace(String.format( + "Running timed out task of process [%s] for command with sensitive arguments.", + processPid)); + } + timedoutTask.run(); + if (!_passwordCommand && sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, + commandLine, timedoutTask.getResult())); + } else { + _logger.warn( + String.format("Process [%s] for command with sensitive arguments timed out.", processPid)); } return ERR_TIMEOUT; } - _logger.debug(String.format("Exit value of process [%s] for command [%s] is [%s].", processPid, commandLine, _process.exitValue())); + if (sensitiveArgIndices.isEmpty()) { + _logger.debug(String.format("Exit value of process [%s] for command [%s] is [%s].", processPid, + commandLine, _process.exitValue())); + } else { + _logger.debug(String.format("Exit value of process [%s] for command with sensitive arguments is [%s].", + processPid, _process.exitValue())); + } BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()), 128); @@ -337,19 +443,49 @@ public class Script implements Callable { error = String.valueOf(_process.exitValue()); } - _logger.warn(String.format("Process [%s] for command [%s] encountered the error: [%s].", processPid, commandLine, error)); + if (sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Process [%s] for command [%s] encountered the error: [%s].", processPid, + commandLine, error)); + } else { + _logger.warn( + String.format("Process [%s] for command with sensitive arguments encountered the error: [%s].", + processPid, error)); + } return error; } catch (SecurityException ex) { - _logger.warn(String.format("Exception [%s] occurred. This may be due to an attempt of executing command [%s] as non root.", ex.getMessage(), commandLine), - ex); + if (sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format( + "Exception [%s] occurred. This may be due to an attempt of executing command [%s] as non root.", + ex.getMessage(), commandLine), + ex); + } else { + _logger.warn(String.format( + "Exception [%s] occurred. This may be due to an attempt of executing command with sensitive data as non root.", + ex.getMessage()), + ex); + } return stackTraceAsString(ex); } catch (Exception ex) { - _logger.warn(String.format("Exception [%s] occurred when attempting to run command [%s].", ex.getMessage(), commandLine), ex); + if (sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Exception [%s] occurred when attempting to run command [%s].", + ex.getMessage(), commandLine), ex); + } else { + _logger.warn( + String.format("Exception [%s] occurred when attempting to run a command with sensitive data.", + ex.getMessage()), + ex); + } return stackTraceAsString(ex); } finally { if (_process != null) { - _logger.trace(String.format("Destroying process [%s] for command [%s].", _process.pid(), commandLine)); + if (sensitiveArgIndices.isEmpty()) { + _logger.trace( + String.format("Destroying process [%s] for command [%s].", _process.pid(), commandLine)); + } else { + _logger.trace(String.format("Destroying process [%s] for a command with sensitive data.", + _process.pid())); + } IOUtils.closeQuietly(_process.getErrorStream()); IOUtils.closeQuietly(_process.getOutputStream()); IOUtils.closeQuietly(_process.getInputStream()); @@ -361,8 +497,9 @@ public class Script implements Callable { public String executeIgnoreExitValue(OutputInterpreter interpreter, int exitValue) { String[] command = _command.toArray(new String[_command.size()]); - if (_logger.isDebugEnabled()) { - _logger.debug(String.format("Executing: %s", buildCommandLine(command).split(KeyStoreUtils.KS_FILENAME)[0])); + if (_logger.isDebugEnabled() && sensitiveArgIndices.isEmpty()) { + _logger.debug( + String.format("Executing: %s", buildCommandLine(command).split(KeyStoreUtils.KS_FILENAME)[0])); } try { @@ -437,10 +574,11 @@ public class Script implements Callable { Task timedoutTask = new Task(log, ir); timedoutTask.run(); - if (!_passwordCommand) { - _logger.warn(String.format("Timed out: %s. Output is: %s", buildCommandLine(command), timedoutTask.getResult())); + if (!_passwordCommand && sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Timed out: %s. Output is: %s", buildCommandLine(command), + timedoutTask.getResult())); } else { - _logger.warn(String.format("Timed out: %s", buildCommandLine(command))); + _logger.warn(String.format("Timed out: %s", "command with sensitive data")); } return ERR_TIMEOUT; @@ -465,7 +603,11 @@ public class Script implements Callable { _logger.warn("Security Exception....not running as root?", ex); return stackTraceAsString(ex); } catch (Exception ex) { - _logger.warn(String.format("Exception: %s", buildCommandLine(command)), ex); + if (sensitiveArgIndices.isEmpty()) { + _logger.warn(String.format("Exception: %s", buildCommandLine(command)), ex); + } else { + _logger.warn("Exception on command with sensitive data.", ex); + } return stackTraceAsString(ex); } finally { if (_process != null) { @@ -514,9 +656,9 @@ public class Script implements Callable { } catch (Exception ex) { result = stackTraceAsString(ex); } finally { - done = true; - notifyAll(); - IOUtils.closeQuietly(reader); + done = true; + notifyAll(); + IOUtils.closeQuietly(reader); } } } diff --git a/utils/src/test/java/com/cloud/utils/script/ScriptTest.java b/utils/src/test/java/com/cloud/utils/script/ScriptTest.java index cc6047959da..a52f3840bea 100644 --- a/utils/src/test/java/com/cloud/utils/script/ScriptTest.java +++ b/utils/src/test/java/com/cloud/utils/script/ScriptTest.java @@ -78,4 +78,34 @@ public class ScriptTest { String result = Script.getExecutableAbsolutePath("ls"); Assert.assertTrue(List.of("/usr/bin/ls", "/bin/ls").contains(result)); } + + @Test + public void testBuildCommandLineWithSensitiveData() { + Script script = new Script("test.sh"); + script.add("normal-arg"); + script.addSensitive("sensitive-arg"); + String commandLine = script.toString(); + Assert.assertEquals("test.sh normal-arg ****** ", commandLine); + } + + @Test + public void testBuildCommandLineWithMultipleSensitiveData() { + Script script = new Script("test.sh"); + script.add("normal-arg"); + script.addSensitive("sensitive-arg1"); + script.add("another-normal-arg"); + script.addSensitive("sensitive-arg2"); + String commandLine = script.toString(); + Assert.assertEquals("test.sh normal-arg ****** another-normal-arg ****** ", commandLine); + } + + @Test + public void testBuildCommandLineWithLegacyPasswordOption() { + Script script = new Script("test.sh"); + script.add("-y"); + script.add("legacy-password"); + String commandLine = script.toString(); + Assert.assertEquals("test.sh -y ****** ", commandLine); + } + } From f9a05f51a4994b437a2a22e00d1e75787ee4778c Mon Sep 17 00:00:00 2001 From: YoulongChen <30854794+YLChen-007@users.noreply.github.com> Date: Sat, 8 Nov 2025 10:38:46 +0800 Subject: [PATCH 2/9] Remove unnecessary line break in Script.java --- utils/src/main/java/com/cloud/utils/script/Script.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index f43d67d0764..c2c50f15f1a 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -70,8 +70,7 @@ public class Script implements Callable { private boolean avoidLoggingCommand = false; private final Set sensitiveArgIndices = new HashSet<>(); - private static final ScheduledExecutorService s_executors = Executors.newScheduledThreadPool(10, - new NamedThreadFactory("Script")); + private static final ScheduledExecutorService s_executors = Executors.newScheduledThreadPool(10, new NamedThreadFactory("Script")); String _workDir; ArrayList _command; From 7dc5b2b0d50fde9414730f7a281041ea268ed585 Mon Sep 17 00:00:00 2001 From: YoulongChen <30854794+YLChen-007@users.noreply.github.com> Date: Tue, 11 Nov 2025 17:30:43 +0800 Subject: [PATCH 3/9] Update utils/src/main/java/com/cloud/utils/script/Script.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- utils/src/main/java/com/cloud/utils/script/Script.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index c2c50f15f1a..71e33184535 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -246,7 +246,7 @@ public class Script implements Callable { public String execute(OutputInterpreter interpreter) { String[] command = _command.toArray(new String[_command.size()]); String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && !avoidLoggingCommand && sensitiveArgIndices.isEmpty()) { + if (_logger.isDebugEnabled() && !avoidLoggingCommand) { _logger.debug(String.format("Executing command [%s].", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); } From d15379b729585745f86c84c1fa18923a8fabc063 Mon Sep 17 00:00:00 2001 From: "chenyoulong20g@ict.ac.cn" Date: Tue, 11 Nov 2025 18:09:20 +0800 Subject: [PATCH 4/9] Refactor logging in Script class to simplify handling of sensitive arguments --- .../java/com/cloud/utils/script/Script.java | 216 +++++------------- 1 file changed, 52 insertions(+), 164 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index f43d67d0764..de15d60e831 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -247,16 +247,12 @@ public class Script implements Callable { public String execute(OutputInterpreter interpreter) { String[] command = _command.toArray(new String[_command.size()]); String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && !avoidLoggingCommand && sensitiveArgIndices.isEmpty()) { + if (_logger.isDebugEnabled() && !avoidLoggingCommand) { _logger.debug(String.format("Executing command [%s].", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); } try { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format("Creating process for command [%s].", commandLine)); - } else { - _logger.trace("Creating process for command with sensitive arguments."); - } + _logger.trace(String.format("Creating process for command [%s].", commandLine)); ProcessBuilder pb = new ProcessBuilder(command); pb.redirectErrorStream(true); if (_workDir != null) @@ -274,126 +270,62 @@ public class Script implements Callable { _thread = Thread.currentThread(); ScheduledFuture future = null; if (_timeout > 0) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format( - "Scheduling the execution of command [%s] with a timeout of [%s] milliseconds.", - commandLine, _timeout)); - } else { - _logger.trace(String.format( - "Scheduling the execution of command with sensitive arguments with a timeout of [%s] milliseconds.", - _timeout)); - } + _logger.trace(String.format( + "Scheduling the execution of command [%s] with a timeout of [%s] milliseconds.", + commandLine, _timeout)); future = s_executors.schedule(this, _timeout, TimeUnit.MILLISECONDS); } long processPid = _process.pid(); Task task = null; if (interpreter != null && interpreter.drain()) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format("Executing interpreting task of process [%s] for command [%s].", - processPid, commandLine)); - } else { - _logger.trace(String.format( - "Executing interpreting task of process [%s] for command with sensitive arguments.", - processPid)); - } + _logger.trace(String.format("Executing interpreting task of process [%s] for command [%s].", + processPid, commandLine)); task = new Task(interpreter, ir); s_executors.execute(task); } while (true) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format("Attempting process [%s] execution for command [%s] with timeout [%s].", - processPid, commandLine, _timeout)); - } else { - _logger.trace(String.format( - "Attempting process [%s] execution for command with sensitive arguments with timeout [%s].", - processPid, _timeout)); - } + _logger.trace(String.format("Attempting process [%s] execution for command [%s] with timeout [%s].", + processPid, commandLine, _timeout)); try { if (_process.waitFor(_timeout, TimeUnit.MILLISECONDS)) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format( - "Process [%s] execution for command [%s] completed within timeout period [%s].", - processPid, commandLine, - _timeout)); - } else { - _logger.trace(String.format( - "Process [%s] execution for command with sensitive arguments completed within timeout period [%s].", - processPid, - _timeout)); - } + _logger.trace(String.format( + "Process [%s] execution for command [%s] completed within timeout period [%s].", + processPid, commandLine, + _timeout)); if (_process.exitValue() == 0) { - if (sensitiveArgIndices.isEmpty()) { - _logger.debug(String.format("Successfully executed process [%s] for command [%s].", - processPid, commandLine)); - } else { - _logger.debug(String.format( - "Successfully executed process [%s] for command with sensitive arguments.", - processPid)); - } + _logger.debug(String.format("Successfully executed process [%s] for command [%s].", + processPid, commandLine)); if (interpreter != null) { if (interpreter.drain()) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace( - String.format("Returning task result of process [%s] for command [%s].", - processPid, commandLine)); - } else { - _logger.trace(String.format( - "Returning task result of process [%s] for command with sensitive arguments.", - processPid)); - } + _logger.trace( + String.format("Returning task result of process [%s] for command [%s].", + processPid, commandLine)); return task.getResult(); } - if (sensitiveArgIndices.isEmpty()) { - _logger.trace( - String.format("Returning interpretation of process [%s] for command [%s].", - processPid, commandLine)); - } else { - _logger.trace(String.format( - "Returning interpretation of process [%s] for command with sensitive arguments.", - processPid)); - } + _logger.trace( + String.format("Returning interpretation of process [%s] for command [%s].", + processPid, commandLine)); return interpreter.interpret(ir); } else { // null return exitValue apparently - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format("Process [%s] for command [%s] exited with value [%s].", - processPid, commandLine, - _process.exitValue())); - } else { - _logger.trace(String.format( - "Process [%s] for command with sensitive arguments exited with value [%s].", - processPid, - _process.exitValue())); - } + _logger.trace(String.format("Process [%s] for command [%s] exited with value [%s].", + processPid, commandLine, + _process.exitValue())); return String.valueOf(_process.exitValue()); } } else { - if (sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format("Execution of process [%s] for command [%s] failed.", - processPid, commandLine)); - } else { - _logger.warn(String.format( - "Execution of process [%s] for command with sensitive arguments failed.", - processPid)); - } + _logger.warn(String.format("Execution of process [%s] for command [%s] failed.", + processPid, commandLine)); break; } } } catch (InterruptedException e) { if (!_isTimeOut) { - if (sensitiveArgIndices.isEmpty()) { - _logger.debug(String.format( - "Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command " - + "[%s].", - e.getMessage(), processPid, commandLine), e); - } else { - _logger.debug(String.format( - "Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command " - + "with sensitive arguments.", - e.getMessage(), processPid), e); - } + _logger.debug(String.format( + "Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command [%s].", + e.getMessage(), processPid, commandLine), e); continue; } } finally { @@ -406,33 +338,21 @@ public class Script implements Callable { TimedOutLogger log = new TimedOutLogger(_process); Task timedoutTask = new Task(log, ir); - if (sensitiveArgIndices.isEmpty()) { - _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, - commandLine)); - } else { - _logger.trace(String.format( - "Running timed out task of process [%s] for command with sensitive arguments.", - processPid)); - } + _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, + commandLine)); timedoutTask.run(); - if (!_passwordCommand && sensitiveArgIndices.isEmpty()) { + if (_passwordCommand) { + _logger.warn(String.format("Process [%s] for command [%s] timed out.", processPid, commandLine)); + } else { _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, commandLine, timedoutTask.getResult())); - } else { - _logger.warn( - String.format("Process [%s] for command with sensitive arguments timed out.", processPid)); } return ERR_TIMEOUT; } - if (sensitiveArgIndices.isEmpty()) { - _logger.debug(String.format("Exit value of process [%s] for command [%s] is [%s].", processPid, - commandLine, _process.exitValue())); - } else { - _logger.debug(String.format("Exit value of process [%s] for command with sensitive arguments is [%s].", - processPid, _process.exitValue())); - } + _logger.debug(String.format("Exit value of process [%s] for command [%s] is [%s].", processPid, + commandLine, _process.exitValue())); BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()), 128); @@ -443,49 +363,24 @@ public class Script implements Callable { error = String.valueOf(_process.exitValue()); } - if (sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format("Process [%s] for command [%s] encountered the error: [%s].", processPid, - commandLine, error)); - } else { - _logger.warn( - String.format("Process [%s] for command with sensitive arguments encountered the error: [%s].", - processPid, error)); - } + _logger.warn(String.format("Process [%s] for command [%s] encountered the error: [%s].", processPid, + commandLine, error)); return error; } catch (SecurityException ex) { - if (sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format( - "Exception [%s] occurred. This may be due to an attempt of executing command [%s] as non root.", - ex.getMessage(), commandLine), - ex); - } else { - _logger.warn(String.format( - "Exception [%s] occurred. This may be due to an attempt of executing command with sensitive data as non root.", - ex.getMessage()), - ex); - } + _logger.warn(String.format( + "Exception [%s] occurred. This may be due to an attempt of executing command [%s] as non root.", + ex.getMessage(), commandLine), + ex); return stackTraceAsString(ex); } catch (Exception ex) { - if (sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format("Exception [%s] occurred when attempting to run command [%s].", - ex.getMessage(), commandLine), ex); - } else { - _logger.warn( - String.format("Exception [%s] occurred when attempting to run a command with sensitive data.", - ex.getMessage()), - ex); - } + _logger.warn(String.format("Exception [%s] occurred when attempting to run command [%s].", + ex.getMessage(), commandLine), ex); return stackTraceAsString(ex); } finally { if (_process != null) { - if (sensitiveArgIndices.isEmpty()) { - _logger.trace( - String.format("Destroying process [%s] for command [%s].", _process.pid(), commandLine)); - } else { - _logger.trace(String.format("Destroying process [%s] for a command with sensitive data.", - _process.pid())); - } + _logger.trace( + String.format("Destroying process [%s] for command [%s].", _process.pid(), commandLine)); IOUtils.closeQuietly(_process.getErrorStream()); IOUtils.closeQuietly(_process.getOutputStream()); IOUtils.closeQuietly(_process.getInputStream()); @@ -496,10 +391,11 @@ public class Script implements Callable { public String executeIgnoreExitValue(OutputInterpreter interpreter, int exitValue) { String[] command = _command.toArray(new String[_command.size()]); + String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && sensitiveArgIndices.isEmpty()) { + if (_logger.isDebugEnabled() && !avoidLoggingCommand) { _logger.debug( - String.format("Executing: %s", buildCommandLine(command).split(KeyStoreUtils.KS_FILENAME)[0])); + String.format("Executing: %s", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); } try { @@ -510,7 +406,7 @@ public class Script implements Callable { _process = pb.start(); if (_process == null) { - _logger.warn(String.format("Unable to execute: %s", buildCommandLine(command))); + _logger.warn(String.format("Unable to execute: %s", commandLine)); return String.format("Unable to execute the command: %s", command[0]); } @@ -574,12 +470,8 @@ public class Script implements Callable { Task timedoutTask = new Task(log, ir); timedoutTask.run(); - if (!_passwordCommand && sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format("Timed out: %s. Output is: %s", buildCommandLine(command), + _logger.warn(String.format("Timed out: %s. Output is: %s", commandLine, timedoutTask.getResult())); - } else { - _logger.warn(String.format("Timed out: %s", "command with sensitive data")); - } return ERR_TIMEOUT; } @@ -603,11 +495,7 @@ public class Script implements Callable { _logger.warn("Security Exception....not running as root?", ex); return stackTraceAsString(ex); } catch (Exception ex) { - if (sensitiveArgIndices.isEmpty()) { - _logger.warn(String.format("Exception: %s", buildCommandLine(command)), ex); - } else { - _logger.warn("Exception on command with sensitive data.", ex); - } + _logger.warn(String.format("Exception: %s", commandLine), ex); return stackTraceAsString(ex); } finally { if (_process != null) { From 64a6547cf3345e7b1eaa97b843fa4631ccc7fa5c Mon Sep 17 00:00:00 2001 From: "chenyoulong20g@ict.ac.cn" Date: Tue, 11 Nov 2025 18:12:29 +0800 Subject: [PATCH 5/9] Improve command logging in Script class to include full command line when debugging --- utils/src/main/java/com/cloud/utils/script/Script.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 3d9dd93c898..de11254b2c4 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -246,8 +246,8 @@ public class Script implements Callable { public String execute(OutputInterpreter interpreter) { String[] command = _command.toArray(new String[_command.size()]); String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && !avoidLoggingCommand) { - _logger.debug(String.format("Executing command [%s].", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); + if (_logger.isDebugEnabled() ) { + _logger.debug(String.format("Executing command [%s].", commandLine)); } try { From a617571ba9c608225abdee80596c150920753b7e Mon Sep 17 00:00:00 2001 From: "chenyoulong20g@ict.ac.cn" Date: Wed, 12 Nov 2025 10:55:41 +0800 Subject: [PATCH 6/9] Remove unused _passwordCommand flag from Script class to simplify code --- utils/src/main/java/com/cloud/utils/script/Script.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index de11254b2c4..59b2d40a02e 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -66,7 +66,6 @@ public class Script implements Callable { private static final int DEFAULT_TIMEOUT = 3600 * 1000; /* 1 hour */ private volatile boolean _isTimeOut = false; - private boolean _passwordCommand = false; private boolean avoidLoggingCommand = false; private final Set sensitiveArgIndices = new HashSet<>(); @@ -178,7 +177,6 @@ public class Script implements Callable { if ("-y".equals(cmd) || "-z".equals(cmd)) { obscureParam = true; - _passwordCommand = true; } } return builder.toString(); @@ -340,12 +338,8 @@ public class Script implements Callable { _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, commandLine)); timedoutTask.run(); - if (_passwordCommand) { - _logger.warn(String.format("Process [%s] for command [%s] timed out.", processPid, commandLine)); - } else { - _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, + _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, commandLine, timedoutTask.getResult())); - } return ERR_TIMEOUT; } From 2468400bf8e1835fcf594a55e0d0258c67c9ac47 Mon Sep 17 00:00:00 2001 From: YoulongChen <30854794+YLChen-007@users.noreply.github.com> Date: Wed, 12 Nov 2025 10:56:57 +0800 Subject: [PATCH 7/9] Update utils/src/main/java/com/cloud/utils/script/Script.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- utils/src/main/java/com/cloud/utils/script/Script.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 59b2d40a02e..59e08381d6c 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -386,9 +386,8 @@ public class Script implements Callable { String[] command = _command.toArray(new String[_command.size()]); String commandLine = buildCommandLine(command); - if (_logger.isDebugEnabled() && !avoidLoggingCommand) { - _logger.debug( - String.format("Executing: %s", commandLine.split(KeyStoreUtils.KS_FILENAME)[0])); + if (_logger.isDebugEnabled()) { + _logger.debug(String.format("Executing: %s", commandLine)); } try { From 45a66f0f5c756702347031e4a9dea5b0c994e66c Mon Sep 17 00:00:00 2001 From: YoulongChen <30854794+YLChen-007@users.noreply.github.com> Date: Wed, 12 Nov 2025 20:23:44 +0800 Subject: [PATCH 8/9] Remove unused import for KeyStoreUtils --- utils/src/main/java/com/cloud/utils/script/Script.java | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 59e08381d6c..2e126af7f64 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -44,7 +44,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; -import org.apache.cloudstack.utils.security.KeyStoreUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; From c6ee04f1464a03705817975c47c39cd99d52cfa5 Mon Sep 17 00:00:00 2001 From: dahn Date: Thu, 22 Jan 2026 15:32:19 +0100 Subject: [PATCH 9/9] Update utils/src/main/java/com/cloud/utils/script/Script.java --- utils/src/main/java/com/cloud/utils/script/Script.java | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/src/main/java/com/cloud/utils/script/Script.java b/utils/src/main/java/com/cloud/utils/script/Script.java index 9b8f1081ff7..09c58dce9a8 100644 --- a/utils/src/main/java/com/cloud/utils/script/Script.java +++ b/utils/src/main/java/com/cloud/utils/script/Script.java @@ -45,6 +45,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; +import org.apache.commons.collections.CollectionUtils; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;