Skip to content

Conversation

@sudo87
Copy link
Collaborator

@sudo87 sudo87 commented Jan 12, 2026

Description

This PR fixes #10847

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

How did you try to break this feature and the system with this change?

@codecov
Copy link

codecov bot commented Jan 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 4.03%. Comparing base (0e6d2d9) to head (680ca79).
⚠️ Report is 10 commits behind head on 4.20.

Additional details and impacted files
@@            Coverage Diff            @@
##            4.20   #12404      +/-   ##
=========================================
+ Coverage   4.00%    4.03%   +0.02%     
=========================================
  Files        402      402              
  Lines      32688    32712      +24     
  Branches    5822     5831       +9     
=========================================
+ Hits        1309     1319      +10     
- Misses     31224    31238      +14     
  Partials     155      155              
Flag Coverage Δ
uitests 4.03% <ø> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@weizhouapache weizhouapache left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code lgtm

@abh1sar abh1sar added this to the 4.20.3 milestone Jan 12, 2026
Copy link
Collaborator

@abh1sar abh1sar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@abh1sar
Copy link
Collaborator

abh1sar commented Jan 12, 2026

@blueorangutan package

@blueorangutan
Copy link

@abh1sar a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

Comment on lines 160 to 162
if (logger.isDebugEnabled()) {
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (logger.isDebugEnabled()) {
logger.debug(String.format("VM [%s] with XML configuration [%s] will be migrated to host [%s].", vmName, xmlDesc, target));
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, maskSensitiveInfoInXML(xmlDesc), target);
}
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, () -> maskSensitiveInfoInXML(xmlDesc), target);

just a suggestion, (may apply below as well)

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clgtm, the isDebugEnabled are not strictly needed anymore.

public static String maskSensitiveInfoInXML(String xmlDesc) {
if (xmlDesc == null) return null;
// Mask VNC password in XML for logging
return xmlDesc.replaceAll("(graphics\\s+[^>]*type=['\"]vnc['\"][^>]*passwd=['\"])([^'\"]*)(['\"])",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can also just remove it, btw

Copy link
Collaborator Author

@sudo87 sudo87 Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wont it confuse admin whether vnc section is not part of the xml or not?

@blueorangutan
Copy link

Packaging result [SF]: ✔️ el8 ✔️ el9 ✔️ el10 ✔️ debian ✔️ suse15. SL-JID 16334

@abh1sar
Copy link
Collaborator

abh1sar commented Jan 12, 2026

@blueorangutan test

@blueorangutan
Copy link

@abh1sar a [SL] Trillian-Jenkins test job (ol8 mgmt + kvm-ol8) has been kicked to run smoke tests

@sudo87
Copy link
Collaborator Author

sudo87 commented Jan 12, 2026

Thanks @DaanHoogland for your review and suggestions. Let me know if my response makes sense:

  1. Per argument lambda is not supported, it will perform toString instead of evaluation. It wont work the way we expect:
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, () -> maskSensitiveInfoInXML(xmlDesc), target);
  1. logger.isDebugEnabled check is added to avoid maskSensitiveInfoInXML invocation. Which is not expensive operation but not required if debug is not enabled. We can definitely remove it.

@DaanHoogland
Copy link
Contributor

  1. Per argument lambda is not supported, it will perform toString instead of evaluation. It wont work the way we expect:
logger.debug("VM {} with XML configuration {} will be migrated to host {}.", vmName, () -> maskSensitiveInfoInXML(xmlDesc), target);

this is not how I read the documentation, but I haven’t tested it. it should lazily evaluate the lambda ony if debug is enabled.

  1. logger.isDebugEnabled check is added to avoid maskSensitiveInfoInXML invocation. Which is not expensive operation but not required if debug is not enabled. We can definitely remove it.

I do not care if point 1 is out of the way. It is just cleaner code. If you are right about point 1 we have a bigger issue.

I do not think either should stop this PR, but in general my experience is that follow-ups don’t happen,...

@blueorangutan
Copy link

[SF] Trillian test result (tid-15170)
Environment: kvm-ol8 (x2), zone: Advanced Networking with Mgmt server ol8
Total time taken: 52911 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr12404-t15170-kvm-ol8.zip
Smoke tests completed. 141 look OK, 0 have errors, 0 did not run
Only failed and skipped tests results shown below:

Test Result Time (s) Test File

@DaanHoogland DaanHoogland linked an issue Jan 14, 2026 that may be closed by this pull request
Copy link
Collaborator

@RosiKyu RosiKyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR successfully masks VNC passwords in most scenarios, but there is one missed log statement in the LibvirtMigrateCommandWrapper that still exposes the actual VNC password during all types of live migration.

Bug Summary

  • Affected log message: "Replaced the VNC IP address [...] with [...]"
  • Location: LibvirtMigrateCommandWrapper.java - replaceIpForVNCInDescFile method (or similar)

Impact: VNC password exposed in DEBUG level logs during any live migration operation

Confirmed in TC2, TC7, and TC8 across both migration directions and storage migration

Test Execution Summary

Test Case Description Result
TC1 VM Start - VNC Password Masking PASSED
TC2 Live Migration - VNC Password Masking PARTIAL
TC3 Console Access Regression PASSED
TC4 VM Stop/Start - VNC Password Masking PASSED
TC5 VM Reboot - VNC Password Masking PASSED
TC6 System VM - VNC Password Masking PASSED
TC7 Reverse Migration - VNC Password Masking PARTIAL
TC8 Storage Migration - VNC Password Masking PARTIAL

Detailed Test Report

Test Case 1: VM Start - VNC Password Masking

Objective Verify that the VNC password is masked (shown as *****) in the agent log when a VM is started.

Test Steps

  1. Deploy a new VM (or start a stopped VM) in the CloudStack environment
  2. SSH to the KVM host where the VM is running
  3. Search the agent log for VM start entries containing VNC graphics configuration:
grep -i "Starting.*:" /var/log/cloudstack/agent/agent.log | tail -5
  1. Search for VNC password entries in the log:
grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
  1. Verify no unmasked passwords exist:
grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Expected Result

  • The VNC password in the logged XML should be masked as passwd='*****'
  • No unmasked VNC passwords should appear in the agent log

Actual Result PASSED

  • The VNC password is correctly masked as passwd='*****'
  • No unmasked VNC passwords found in the log

Evidence

  • VM Start log entry found:
2026-01-18 16:57:28,843 DEBUG [resource.wrapper.LibvirtStartCommandWrapper] (AgentRequest-Handler-5:[]) (logid:) Starting r-4-VM : <domain type='kvm'>

VNC password masked (grep output):

[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
  • No unmasked passwords (empty result confirms fix):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Test Case 2: Live Migration - VNC Password Masking.

Objective Verify that the VNC password is masked (shown as *****) in the agent log when a VM is live migrated between KVM hosts.

Test Steps

  1. Identify a running user VM and the host it is currently on
  2. Live migrate the VM to another KVM host:
  3. After migration completes, SSH to the source host (where VM was before migration) and search for live migration log entries:
 grep -i "live migration" /var/log/cloudstack/agent/agent.log
  1. Search for VNC password entries:
grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
  1. Check for any unmasked passwords:
grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Expected Result

  • All VNC passwords in the logged XML should be masked as passwd='*****'
  • No unmasked VNC passwords should appear in any migration-related log entries

Actual Result PARTIALLY PASSED / BUG FOUND

  • The main migration XML configuration is correctly masked
  • However, the replaceIpForVNCInDescFile log message still exposes the actual VNC password

Evidence

  • Live migration entry (masked correctly):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -i "live migration" /var/log/cloudstack/agent/agent.log
2026-01-18 17:05:14,161 INFO  [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Starting live migration of instance i-2-3-VM to destination host qemu+tls://10.1.33.95/system having the final XML configuration: <domain type='kvm'>
  • VNC password entries (mixed results):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='*****'>
2026-01-18 17:05:14,129 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) 
  • Replaced the VNC IP address
[<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='*****'>
  • Unmasked password found (bug):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log
2026-01-18 17:05:14,129 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) 
  • Replaced the VNC IP address
[<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>

Bug Details

The replaceIpForVNCInDescFile method in LibvirtMigrateCommandWrapper.java logs the old and new XML snippets when replacing the VNC IP address, but this log statement is not using the maskSensitiveInfoInXML() function, causing the actual VNC password (UzAp0PQ9) to be exposed in the agent log.

Affected log message: "Replaced the VNC IP address [...] with [...]"

Test Case 3: Console Access Regression Test

Objective Verify that the VNC password masking in logs does not break the actual VM console access functionality.

Test Steps

  1. Open the CloudStack UI
  2. Navigate to the test VM (i-2-3-VM)
  3. Click on "View Console" button
  4. Verify the console window opens and displays the VM screen
  5. Verify keyboard input works (login to the VM)

Expected Result

  • Console should connect successfully
  • VM display should be visible
  • User should be able to interact with the VM (keyboard/mouse)

**Actual Result: ** PASSED

  • Console connected successfully via Console Proxy
  • VM display visible (CentOS 5.5 login screen)
  • Successfully logged in as root - keyboard input working

Evidence

Image

Test Case 4: VM Stop and Start - VNC Password Masking

Objective Verify that the VNC password remains masked in the agent log when a VM is stopped and then started again.

Test Steps

  1. Stop the test VM:
  2. Wait for the VM to stop completely
  3. Start the VM again:
  4. Check the agent log on the host where the VM started:
grep -i "Starting.*:" /var/log/cloudstack/agent/agent.log | tail -5
grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Expected Result

  • The VNC password in the logged XML should be masked as passwd='*****'
  • No unmasked VNC passwords should appear in the agent log

Actual Result: PASSED

  • VM stopped and started successfully on kvm2
  • VNC password correctly masked in the start log

Evidence:

  • VM Start log entry found on kvm2:
2026-01-18 17:17:44,269 DEBUG [resource.wrapper.LibvirtStartCommandWrapper] (AgentRequest-Handler-4:[]) (logid:) Starting i-2-3-VM : <domain type='kvm'>
  • VNC password masked:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
<graphics type='vnc' autoport='yes' listen='10.1.33.95' passwd='*****'/>
  • No unmasked passwords found:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Test Case 5: VM Reboot - VNC Password Masking

Objective Verify that the VNC password remains masked in the agent log when a VM is rebooted.

Test Steps:

  1. Reboot the test VM:
  2. Check the agent log on the host where the VM is running:

Expected Result

  • No new StartCommand/XML log entries expected (reboot is handled internally by libvirt)
  • No unmasked VNC passwords should appear

**Actual Result: ** PASSED

  • VM reboot does not generate new StartCommand log entries
  • Reboot is handled internally by libvirt/QEMU without CloudStack agent involvement
  • No new XML configuration is logged during reboot
  • Existing entries remain properly masked

Evidence:

  • No new start entries after reboot (only TC4 entry from 17:17:44):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -i "Starting.*i-2-3-VM" /var/log/cloudstack/agent/agent.log | tail -3
2026-01-18 17:17:44,269 DEBUG [resource.wrapper.LibvirtStartCommandWrapper] (AgentRequest-Handler-4:[]) (logid:) Starting i-2-3-VM : <domain type='kvm'>
  • VNC password remains masked:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
<graphics type='vnc' autoport='yes' listen='10.1.33.95' passwd='*****'/>
  • No unmasked passwords:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log

Notes VM reboot operation is handled by libvirt's internal restart mechanism and does not trigger a new CloudStack StartCommand. This is expected behavior - the PR's masking is only relevant when CloudStack explicitly logs VM XML configurations during start or migration operations.

Test Case 6: System VM - VNC Password Masking

Objective Verify that the VNC password is also masked for System VMs (SSVM, CPVM, Virtual Router).

Test Steps

  1. Check agent logs (including rotated logs) on kvm1 for SSVM s-1-VM:
  2. Check agent logs (including rotated logs) on kvm2 for CPVM v-2-VM:

Expected Result:

  • VNC passwords for System VMs should be masked as passwd='*****'
  • No unmasked VNC passwords (except known TC2 bug)

Actual Result: PASSED

  • SSVM (s-1-VM) start log from 2026-01-14 shows masked password
  • CPVM (v-2-VM) start log from 2026-01-14 shows masked password
  • All System VM VNC entries properly masked

Evidence:

  • kvm1 - SSVM (s-1-VM) start found in rotated log:
/var/log/cloudstack/agent/agent.log.2026-01-14.gz:2026-01-14 14:12:47,490 DEBUG [resource.wrapper.LibvirtStartCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Starting s-1-VM : <domain type='kvm'>
  • kvm1 - VNC password masking (all logs):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# zgrep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log* | head -20
/var/log/cloudstack/agent/agent.log:<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
/var/log/cloudstack/agent/agent.log:<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
/var/log/cloudstack/agent/agent.log:    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='*****'>
/var/log/cloudstack/agent/agent.log:2026-01-18 17:05:14,129 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
/var/log/cloudstack/agent/agent.log:    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
/var/log/cloudstack/agent/agent.log:    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='*****'>
/var/log/cloudstack/agent/agent.log.2026-01-14.gz:<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>

(Note: Unmasked password visible is the known TC2 bug from migration)

  • kvm2 - CPVM (v-2-VM) start found in rotated log:
/var/log/cloudstack/agent/agent.log.2026-01-14.gz:2026-01-14 14:13:12,611 DEBUG [resource.wrapper.LibvirtStartCommandWrapper] (AgentRequest-Handler-5:[]) (logid:) Starting v-2-VM : <domain type='kvm'>
  • kvm2 - VNC password masking (all logs):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# zgrep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log* | head -20
/var/log/cloudstack/agent/agent.log:<graphics type='vnc' autoport='yes' listen='10.1.33.95' passwd='*****'/>
/var/log/cloudstack/agent/agent.log.2026-01-14.gz:<graphics type='vnc' autoport='yes' listen='10.1.33.95' passwd='*****'/>

Test Case 7: Reverse Migration (kvm2 → kvm1)

Objective: Confirm that the bug found in TC2 (unmasked VNC password in "Replaced the VNC IP address" log message) is reproducible when migrating in the reverse direction.

TestSteps:

  1. Migrate VM from kvm2 back to kvm1:
  2. After migration completes, check agent log on kvm2 (source host):

Expected Result: All VNC passwords should be masked as passwd='*****'

Actual Result: PARTIAL - Bug Confirmed

  • Main migration XML configuration is properly masked
  • Bug reproduced: The "Replaced the VNC IP address" log message still exposes the actual VNC password

Evidence:

  • Live migration entry (masked correctly):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -i "live migration" /var/log/cloudstack/agent/agent.log | tail -3
2026-01-18 17:53:20,092 INFO  [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Starting live migration of instance i-2-3-VM to destination host qemu+tls://10.1.34.189/system having the final XML configuration: <domain type='kvm'>
  • VNC password entries (mixed results):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log
<graphics type='vnc' autoport='yes' listen='10.1.33.95' passwd='*****'/>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='*****'>
2026-01-18 17:53:20,066 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='*****'>
  • Unmasked password confirmed (bug):
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm2 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log
2026-01-18 17:53:20,066 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>

Notes: This confirms the bug identified in TC2 is consistent and reproducible in both migration directions (kvm1→kvm2 and kvm2→kvm1). The same VNC password is exposed in both cases.

Test Case 8: Storage Migration

Objective: Verify that the VNC password is masked when performing live migration with storage (migrating VM and its volumes to a different storage pool simultaneously).

Test Steps:

  1. Check current volume location
  2. Migrate VM with volume to different storage pool:
migrate virtualmachinewithvolume virtualmachineid=1170e952-de03-410e-8d8a-896260abf583 hostid=550f5e3f-78e6-4229-b9f4-bc0f07eca952 migrateto[0].volume=a3984f50-61fa-4d41-91a7-3d34058c3c16 migrateto[0].pool=f9d5d615-0697-31e6-9e66-978f2974640f
  1. After migration completes, check agent log on source host (kvm1):

Expected Result:

  • All VNC passwords should be masked as passwd='*****'
  • Storage migration logs should not expose VNC passwords

Actual Result PARTIAL - Same bug as TC2/TC7

  • VM migrated successfully from kvm1 to kvm2 with volume moved from pri1 to pri2
  • Main migration XML configuration is properly masked
  • Bug reproduced: The "Replaced the VNC IP address" log message exposes the actual VNC password

Evidence:

  • VNC password entries showing the bug:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd" /var/log/cloudstack/agent/agent.log | tail -10
<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
<graphics type='vnc' autoport='yes' listen='10.1.34.189' passwd='*****'/>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='*****'>
2026-01-18 17:05:14,129 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) 
Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='*****'>
    <graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='*****'>
2026-01-18 17:59:41,528 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-1:[]) (logid:) 
Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
  • Unmasked passwords confirmed:
[root@ref-trl-6151-k-Mol9-rositsa-kyuchukova-kvm1 ~]# grep -E "graphics.*vnc.*passwd=['\"][^*]" /var/log/cloudstack/agent/agent.log
2026-01-18 17:05:14,129 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-3:[]) (logid:) 
Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>
2026-01-18 17:59:41,528 DEBUG [resource.wrapper.LibvirtMigrateCommandWrapper] (AgentRequest-Handler-1:[]) (logid:) Replaced the VNC IP address [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.34.189' passwd='UzAp0PQ9'>
    </graphics>] with [<graphics type='vnc' port='-1' autoport='yes' listen='10.1.33.95' passwd='UzAp0PQ9'>

Notes Storage migration (17:59:41) uses the same LibvirtMigrateCommandWrapper code path as regular live migration
The same bug occurs regardless of whether storage is being migrated along with the VM
Volume successfully moved from pri1 (404b015d-...) to pri2 (f9d5d615-...)

@sudo87
Copy link
Collaborator Author

sudo87 commented Jan 19, 2026

Thank you @RosiKyu for the extremely detailed QA validation. This is very helpful.

I have addressed the issue by masking the XML in the log statement within replaceIpForVNCInDescFileAndNormalizePassword method. Please re-test TC2, TC7, and TC8 with the updated package.

@sudo87
Copy link
Collaborator Author

sudo87 commented Jan 19, 2026

@blueorangutan package

@blueorangutan
Copy link

@sudo87 a [SL] Jenkins job has been kicked to build packages. It will be bundled with KVM, XenServer and VMware SystemVM templates. I'll keep you posted as I make progress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agent logs libvirt xml while live migrating vms

6 participants