From: Thomas Lamprecht <t.lamprecht@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH manager 08/10] report: redact sensitive values from guest, storage and SDN configs
Date: Sun, 1 Nov 2026 22:34:57 +0100 [thread overview]
Message-ID: <20261101213835.353604-9-t.lamprecht@proxmox.com> (raw)
In-Reply-To: <20261101213835.353604-1-t.lamprecht@proxmox.com>
The system report only requires Sys.Audit, but includes all guest
configs and the SDN configs verbatim. So it contains cloud-init
passwords, in plain text for Windows guests, and the API tokens of SDN
IPAM and DNS integrations, while the config API masks the password for
everyone. A report is often sent to support by someone who does not own
these credentials, for example a hosting provider renting out VMs.
Replace the values of all properties marked as sensitive in their
schema, in every section including snapshots and pending changes. The
key stays visible, and so does every other line of the file, including
invalid ones.
storage.cfg holds no secrets of the built-in plugins, which store them
in separate files, but third-party plugins that keep credentials inline
can now mark them and have them redacted too.
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
NOTE: needs a libpve-common-perl with the raw config redaction helpers
as a hard runtime dependency; with an older one the report shows errors
instead of the guest, storage and SDN configs. The redaction only takes
effect with qemu-server and libpve-network-perl versions that mark their
secrets.
PVE/Report.pm | 56 ++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 49 insertions(+), 7 deletions(-)
diff --git a/PVE/Report.pm b/PVE/Report.pm
index e255d538f..7182c091d 100644
--- a/PVE/Report.pm
+++ b/PVE/Report.pm
@@ -4,11 +4,27 @@ use strict;
use warnings;
use PVE::IPRoute2;
+use PVE::JSONSchema;
+use PVE::LXC::Config;
+use PVE::Network::SDN::Dns;
+use PVE::Network::SDN::Ipams;
+use PVE::QemuServer;
+use PVE::Storage;
use PVE::Tools;
+my $redaction_placeholder = '<redacted>';
+
+my sub file2text {
+ my ($path, $redact) = @_;
+
+ my $content = PVE::Tools::file_get_contents($path);
+ $content = $redact->($content, $path) if $redact;
+ return "\n# cat $path\n$content\n";
+}
+
# output the content of all the files of a directory
my sub dir2text {
- my ($target_dir, $regexp) = @_;
+ my ($target_dir, $regexp, $redact) = @_;
print STDERR "dir2text '${target_dir}${regexp}'...";
my $text = "# output '${target_dir}${regexp}' file(s)\n";
@@ -18,13 +34,39 @@ my sub dir2text {
sub {
my ($file) = @_;
return if $file eq '.' || $file eq '..';
- $text .= "\n# cat $target_dir$file\n";
- $text .= PVE::Tools::file_get_contents($target_dir . $file) . "\n";
+ $text .= file2text($target_dir . $file, $redact);
},
);
return $text;
}
+my sub redact_qemu_config {
+ my ($raw) = @_;
+
+ my $schema = { type => 'object', properties => PVE::QemuServer::json_config_properties({}) };
+ return PVE::JSONSchema::redact_raw_config($schema, $raw, $redaction_placeholder);
+}
+
+my sub redact_lxc_config {
+ my ($raw) = @_;
+
+ my $schema = { type => 'object', properties => PVE::LXC::Config->json_config_properties({}) };
+ return PVE::JSONSchema::redact_raw_config($schema, $raw, $redaction_placeholder);
+}
+
+my $section_configs = {
+ '/etc/pve/sdn/dns.cfg' => 'PVE::Network::SDN::Dns::Plugin',
+ '/etc/pve/sdn/ipams.cfg' => 'PVE::Network::SDN::Ipams::Plugin',
+ '/etc/pve/storage.cfg' => 'PVE::Storage::Plugin',
+};
+
+my sub redact_section_config {
+ my ($raw, $path) = @_;
+
+ my $class = $section_configs->{$path} // return $raw;
+ return $class->redact_raw_config($raw, $redaction_placeholder);
+}
+
# command -v is the posix equivalent of 'which'
my sub cmd_exists { system("command -v '$_[0]' > /dev/null 2>&1") == 0 }
@@ -59,7 +101,7 @@ my $init_report_cmds = sub {
storage => {
order => 30,
cmds => [
- 'cat /etc/pve/storage.cfg',
+ sub { file2text('/etc/pve/storage.cfg', \&redact_section_config) },
'pvesm status',
'cat /etc/fstab',
'findmnt --ascii',
@@ -71,9 +113,9 @@ my $init_report_cmds = sub {
order => 40,
cmds => [
'qm list',
- sub { dir2text('/etc/pve/qemu-server/', '\d+\.conf') },
+ sub { dir2text('/etc/pve/qemu-server/', '\d+\.conf', \&redact_qemu_config) },
'pct list',
- sub { dir2text('/etc/pve/lxc/', '\d+\.conf') },
+ sub { dir2text('/etc/pve/lxc/', '\d+\.conf', \&redact_lxc_config) },
],
},
network => {
@@ -85,7 +127,7 @@ my $init_report_cmds = sub {
'cat /etc/network/interfaces',
sub { dir2text('/etc/network/interfaces.d/', '.*') },
'cat /etc/pve/sdn/.running-config',
- sub { dir2text('/etc/pve/sdn/', '.+\.cfg') },
+ sub { dir2text('/etc/pve/sdn/', '.+\.cfg', \&redact_section_config) },
sub { dir2text('/etc/pve/sdn/', '.+\.json') },
],
},
--
2.47.3
next prev parent reply other threads:[~2026-11-01 21:40 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-01 21:34 [PATCH common,qemu-server,network,manager 0/10] mark secrets in schemas and redact them from the system report Thomas Lamprecht
2026-11-01 21:34 ` [PATCH common 01/10] section config: do not add isolated property lists on lookups Thomas Lamprecht
2026-11-01 21:34 ` [PATCH common 02/10] schema: allow marking properties as sensitive Thomas Lamprecht
2026-11-01 21:34 ` [PATCH common 03/10] schema: add helpers to redact sensitive values Thomas Lamprecht
2026-11-01 21:34 ` [PATCH common 04/10] section config: add redaction of sensitive values in raw configs Thomas Lamprecht
2026-11-01 21:34 ` [PATCH qemu-server 05/10] cloud-init: mark the password as sensitive Thomas Lamprecht
2026-11-01 21:34 ` [PATCH qemu-server 06/10] config: hide sensitive values of unparsable lines in warnings Thomas Lamprecht
2026-11-01 21:34 ` [PATCH network 07/10] sdn: ipam, dns: mark API tokens as sensitive Thomas Lamprecht
2026-11-01 21:34 ` Thomas Lamprecht [this message]
2026-11-01 21:34 ` [PATCH manager 09/10] report: redact credentials in URLs, options and environment variables Thomas Lamprecht
2026-11-01 21:34 ` [PATCH manager 10/10] pvereport: man page: document which values get redacted Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261101213835.353604-9-t.lamprecht@proxmox.com \
--to=t.lamprecht@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.