From: Thomas Lamprecht <t.lamprecht@proxmox.com>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>,
Maximiliano Sandoval <m.sandoval@proxmox.com>
Cc: Wolfgang Bumiller <w.bumiller@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server] config: add system and service credentials support
Date: Thu, 3 Apr 2025 09:49:40 +0200 [thread overview]
Message-ID: <09b570e5-fce3-4ecc-a898-9400f21d778a@proxmox.com> (raw)
In-Reply-To: <20250402143620.440158-1-m.sandoval@proxmox.com>
Am 02.04.25 um 16:36 schrieb Maximiliano Sandoval:
> Allows to pass system and service credentials to a VM. See [1] for a
> description of credentials. This can be potentially used to provision a
> VM as per [2]. Values can be passed either as plain text or as a base64
> encoded string when the base64 flag is set.
Would this also make sense for Containers?
If it's something we can expose for all guests, we could also (later) look
into implementing some simple registry (like a mappings type) fulfilling
what the snippets approach would provide one while having it nicely
integrated into our access control system.
>
> A VM configuration file which, for example, contains:
>
> systemd-cred0: name=foo,value=bar
> systemd-cred1: name=encoded-foo,value=YmFy,base64=1
Tangentially related: Moving the VM config fully over to section config
parsing would get us list/array support for free – albeit the move might be
rather costly..
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index ffd5d56b..1f902b8b 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -150,6 +150,31 @@ my $watchdog_fmt = {
> };
> PVE::JSONSchema::register_format('pve-qm-watchdog', $watchdog_fmt);
>
> +my $MAX_CREDENTIALS = 16;
> +
> +my $systemd_cred_fmt = {
> + value => {
> + description => 'The credential\'s value. This is a Base64 encoded string.'
But it isn't if the base64 flag is not set?
> + .' If the value should contain arbitrary binary data,'
nit: why the early line break in the mid of the same sentence?
> + .' then the value can be a Base64 encoded string and the base64=1 flag should be set.',
different casing: Base64 here and base64 below for the property
with the same name.
> + type => 'string',
> + pattern => '[A-Za-z0-9+\/]+={0,2}',
> + typetext => '<string>',
> + },
> + name => {
> + description => 'The credential\'s name. This is a short ASCII string suitable as filename in the filesystem',
> + type => 'string',
> + pattern => '[A-Za-z0-9\-\._]+',
The dot does not need to be escaped in a [characterset] pattern, and new use-sites
might prefer using a quoted regex via qr/REGEX/ [perlop-regex-quote], which we
already use on a few sites and has some small performance benefit and also
features like having some regex-modifier flags enforced just for that sub
pattern. I.e. the following should be the same: qr/[a-z0-9_.-]/i – not that
you need to use exactly that here, just fyi in case you did not know about qr//.
[perlop-regex-quote]: https://perldoc.perl.org/perlop#Regexp-Quote-Like-Operators
> + typetext => '<string>',
> + },
> + base64 => {
> + description => 'Whether the credential\'s value is base64 encoded.',
> + type => 'boolean',
> + optional => 1,
> + default => 0,
> + },
> +};
> +
> my $agent_fmt = {
> enabled => {
> description => "Enable/disable communication with a QEMU Guest Agent (QGA) running in the VM.",
> @@ -946,6 +971,13 @@ my $netdesc = {
> description => "Specify network devices.",
> };
>
> +my $systemd_cred_desc = {
> + optional => 1,
> + type => 'string',
> + format => $systemd_cred_fmt,
> + description => 'Specify system and service credentials.',
> +};
> +
> PVE::JSONSchema::register_standard_option("pve-qm-net", $netdesc);
>
> my $ipconfig_fmt = {
> @@ -1955,6 +1991,16 @@ sub parse_guest_agent {
> return $res;
> }
>
> +sub parse_systemd_credential {
> + my ($value) = @_;
> +
> + return {} if !$value;
> +
> + my $res = eval { parse_property_string($systemd_cred_fmt, $value) };
> + warn $@ if $@;
Should we really just ignore the error and warn here in a generic parser?
Isn't that the callers job to decide?
> + return $res;
> +}
> +
> sub get_qga_key {
> my ($conf, $key) = @_;
> return undef if !defined($conf->{agent});
> @@ -3383,6 +3429,17 @@ my sub get_vga_properties {
> return ($vga, $qxlnum);
> }
>
> +sub smbios_11_cred_arg {
> + my ($name, $value, $is_encoded) = @_;
> +
> + if ($is_encoded) {
> + die "value $value is not base64 encoded\n" if $value !~ /^[A-Za-z0-9+\/]+={0,2}$/;
A base64 regex might be good to have in a module wide variable, that then can
also be used in the JSONSchema format above. Can be here in this module for now.
> + return ('-smbios', "type=11,value=io.systemd.credential.binary:$name=$value");
> + } else {
> + return ('-smbios', "type=11,value=io.systemd.credential:$name=$value");
> + }
> +}
> +
> sub config_to_command {
> my ($storecfg, $vmid, $conf, $defaults, $forcemachine, $forcecpu,
> $live_restore_backing) = @_;
> @@ -4015,6 +4072,21 @@ sub config_to_command {
> push @$cmd, '-snapshot';
> }
>
> + for (my $i = 0; $i < $MAX_CREDENTIALS; $i++) {
> + my $cred_name = "systemd-cred$i";
> +
> + next if !$conf->{$cred_name}
might be tiny bit nicer if written as:
my $cred = $conf->{"systemd-cred$i"} or next;
;
> +
> + my $opts = parse_systemd_credential($conf->{$cred_name});
> + my $name = $opts->{'name'};
> + my $is_encoded = $opts->{'base64'};
> + my $value = $opts->{'value'};
I'd avoid those useless intermediate variables, this part is not big enough
to justify them IMO, just go for direct shell access.
> +
> + if ($value && $name) {
> + push @$cmd, smbios_11_cred_arg($name, $value, $is_encoded);
> + }
> + }
> +
> # add custom args
> if ($conf->{args}) {
> my $aa = PVE::Tools::split_args($conf->{args});
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-04-03 7:50 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-02 14:36 Maximiliano Sandoval
2025-04-03 7:49 ` Thomas Lamprecht [this message]
2025-04-03 7:56 ` Thomas Lamprecht
2025-04-03 8:48 ` Maximiliano Sandoval
2025-04-03 8:34 ` Maximiliano Sandoval
2025-04-03 9:04 ` Thomas Lamprecht
2025-04-03 9:42 ` Lukas Wagner
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=09b570e5-fce3-4ecc-a898-9400f21d778a@proxmox.com \
--to=t.lamprecht@proxmox.com \
--cc=m.sandoval@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
--cc=w.bumiller@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal