From: Thomas Lamprecht <t.lamprecht@proxmox.com>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>,
Fiona Ebner <f.ebner@proxmox.com>
Subject: Re: [pve-devel] [PATCH qemu-server 2/2] fix #6985: ovmf: auto-enroll Microsoft UEFI CA 2023 for Windows
Date: Fri, 14 Nov 2025 02:18:47 +0100 [thread overview]
Message-ID: <5ce79121-9ce3-4f6f-9842-3c9a5572b99b@proxmox.com> (raw)
In-Reply-To: <20251111135808.110791-3-f.ebner@proxmox.com>
Am 11.11.25 um 14:57 schrieb Fiona Ebner:
> Microsoft's UEFI CA 2011 will expire in June 2026. It's necessary to
> ensure that the new UEFI CA 2023 is enrolled for Windows to keep
> updates working.
>
> pve-edk2-firmware >= 4.2025.05-1 includes the 2023 certificate
> already, so new disks are fine. Still, check during EFI disk creation
> what is actually there, since there is no guarantee that a new enough
> version of pve-edk2-firmware is installed.
>
> A new 'ms-cert' drive property for EFI disks records the year of the
> last known-to-be-enrolled MS UEFI CA. This avoids the need to re-check
> every time if the 2023 certificate needs to be enrolled. The downside
> is that this breaks backwards migration, because a disk with an
> unknown option is dropped from the configuration.
>
> Enrollment and checking for existing disks is done via virt-fw-vars,
> which is a new dependency recorded in d/control. While virt-fw-vars
> supports raw and qcow2 files out of the box, this is not enough,
> because EFI disks can also be vmdk formatted and there are also
> storages that use a protocol path like 'rbd://' or 'iscsi://' for
> QEMU, which virt-fw-vars cannot handle. Thus, use a FUSE export to
> cover all cases.
>
> Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
> ---
> debian/control | 1 +
> src/PVE/QemuServer.pm | 20 +++++++++++++
> src/PVE/QemuServer/Drive.pm | 9 ++++++
> src/PVE/QemuServer/OVMF.pm | 59 +++++++++++++++++++++++++++++++++++++
> 4 files changed, 89 insertions(+)
>
needs a rebase (or I fumbled something).
> diff --git a/debian/control b/debian/control
> index 5ac6b0fc..661ac65b 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -58,6 +58,7 @@ Depends: conntrack,
> pve-firewall (>= 6.0.3),
> pve-ha-manager (>= 5.0.3),
> pve-qemu-kvm (>= 7.1~),
> + python3-virt-firmware,
> socat,
> swtpm,
> swtpm-tools,
> diff --git a/src/PVE/QemuServer.pm b/src/PVE/QemuServer.pm
> index 79ff637a..74836833 100644
> --- a/src/PVE/QemuServer.pm
> +++ b/src/PVE/QemuServer.pm
> @@ -5373,6 +5373,24 @@ my sub remove_left_over_vmstate_opts {
> PVE::QemuConfig->write_config($vmid, $conf) if $found;
> }
>
> +my sub check_efi_vars {
> + my ($storecfg, $vmid, $conf) = @_;
> +
> + return if PVE::QemuConfig->is_template($conf);
> + return if !$conf->{efidisk0};
> + return if $conf->{ostype} ne 'win10' && $conf->{ostype} ne 'win11';
> +
> + if (
> + my $updated = PVE::QemuServer::OVMF::ensure_ms_2023_cert_enrolled(
> + $storecfg, $vmid, $conf->{efidisk0},
> + )
> + ) {
> + $conf->{efidisk0} = $updated;
> + PVE::QemuConfig->write_config($vmid, $conf);
> + }
> + return;
> +}
> +
> # see vm_start_nolock for parameters, additionally:
> # migrate_opts:
> # storagemap = parsed storage map for allocating NBD disks
> @@ -5548,6 +5566,8 @@ sub vm_start_nolock {
> # With -blockdev, it is necessary to activate the volumes before generating the command line
> PVE::Storage::activate_volumes($storecfg, $vollist);
>
> + check_efi_vars($storecfg, $vmid, $conf) if $conf->{bios} && $conf->{bios} eq 'ovmf';
> +
> # Note that for certain cases like templates, the configuration is minimized, so need to ensure
> # the rest of the function here uses the same configuration that was used to build the command
> ($cmd, $spice_port, my $pci_devices, $conf) = config_to_command(
> diff --git a/src/PVE/QemuServer/Drive.pm b/src/PVE/QemuServer/Drive.pm
> index f54f9612..c772c803 100644
> --- a/src/PVE/QemuServer/Drive.pm
> +++ b/src/PVE/QemuServer/Drive.pm
> @@ -521,6 +521,15 @@ my %efitype_fmt = (
> optional => 1,
> default => 0,
> },
> + 'ms-cert' => {
> + type => 'string',
> + enum => [qw(2011 2023)],
> + description =>
> + "Informational marker indicating the version of the latest Microsof UEFI certificate"
> + . " that has been enrolled by Proxmox VE.",
> + optional => 1,
> + default => '2011',
> + },
> );
>
> my $efidisk_fmt = {
> diff --git a/src/PVE/QemuServer/OVMF.pm b/src/PVE/QemuServer/OVMF.pm
> index 08134e30..badacf54 100644
> --- a/src/PVE/QemuServer/OVMF.pm
> +++ b/src/PVE/QemuServer/OVMF.pm
> @@ -11,7 +11,9 @@ use PVE::Tools;
>
> use PVE::QemuServer::Blockdev;
> use PVE::QemuServer::Drive qw(checked_volume_format parse_drive print_drive);
> +use PVE::QemuServer::Helpers;
> use PVE::QemuServer::QemuImage;
> +use PVE::QemuServer::QSD;
>
> my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/';
> my $OVMF = {
> @@ -128,6 +130,30 @@ sub get_efivars_size {
> return -s $ovmf_vars;
> }
>
> +my sub is_ms_2023_cert_enrolled {
> + my ($path) = @_;
> +
> + my $inside_db_section;
> + my $found_ms_2023_cert;
> +
> + my $detect_ms_2023_cert = sub {
> + my ($line) = @_;
> + return if $found_ms_2023_cert;
> + $inside_db_section = undef if !$line;
> + $found_ms_2023_cert = 1
> + if $inside_db_section && $line =~ m/CN=Microsoft UEFI CA 2023/;
> + $inside_db_section = 1 if $line =~ m/^name=db guid=guid:EfiImageSecurityDatabase/;
> + return;
> + };
> +
> + PVE::Tools::run_command(
> + ['virt-fw-vars', '--input', $path, '--print', '--verbose'],
> + outfunc => $detect_ms_2023_cert,
> + );
> +
> + return $found_ms_2023_cert;
> +}
> +
> sub create_efidisk($$$$$$$$) {
> my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm, $amd_sev_type) = @_;
>
> @@ -141,6 +167,10 @@ sub create_efidisk($$$$$$$$) {
> PVE::QemuServer::QemuImage::convert($ovmf_vars, $volid, $vars_size_b);
> my $size = PVE::Storage::volume_size_info($storecfg, $volid, 3);
>
> + if ($efidisk->{'pre-enrolled-keys'} && is_ms_2023_cert_enrolled($ovmf_vars)) {
> + $efidisk->{'ms-cert'} = '2023'
> + }
> +
> return ($volid, $size / 1024);
> }
>
> @@ -235,4 +265,33 @@ sub print_ovmf_commandline {
> return ($cmd, $machine_flags);
> }
>
> +sub ensure_ms_2023_cert_enrolled {
> + my ($storecfg, $vmid, $efidisk_str) = @_;
> +
> + my $efidisk = parse_drive('efidisk0', $efidisk_str);
> + return if !$efidisk->{'pre-enrolled-keys'};
> + return if $efidisk->{'ms-cert'} && $efidisk->{'ms-cert'} eq '2023';
> +
> + print "efidisk0: enrolling Microsoft UEFI CA 2023\n";
> +
> + my $new_qsd = !PVE::QemuServer::Helpers::qsd_running_locally($vmid);
> + PVE::QemuServer::QSD::start($vmid) if $new_qsd;
> +
> + eval {
> + my $efi_vars_path =
> + PVE::QemuServer::QSD::add_fuse_export($vmid, $efidisk, 'efidisk0-enroll');
> + PVE::Tools::run_command(
> + ['virt-fw-vars', '--inplace', $efi_vars_path, '--distro-keys', 'ms-uefi']);
> + PVE::QemuServer::QSD::remove_fuse_export($vmid, 'efidisk0-enroll');
> + };
> + my $err = $@;
> +
> + PVE::QemuServer::QSD::quit($vmid) if $new_qsd;
if other request start using this QSD after it was started here they might get
interrupted? Albeit currently this is probably rather theoretically due to QSD
being per-vmid and we the operations QSD is used as of now are not really being
able to run concurently for a single VM FWICT.
Might be still good to at least add a comment for this for the case that QSD gets
adopted more.
> +
> + die "efidisk0: enrolling Microsoft UEFI CA 2023 failed - $err" if $err;
> +
> + $efidisk->{'ms-cert'} = '2023';
> + return print_drive($efidisk);
> +}
> +
> 1;
_______________________________________________
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-11-14 1:18 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-11 13:57 [pve-devel] [PATCH-SERIES qemu-server 0/2] " Fiona Ebner
2025-11-11 13:57 ` [pve-devel] [PATCH qemu-server 1/2] qsd: add remove_fuse_export() function Fiona Ebner
2025-11-14 11:50 ` [pve-devel] applied: " Thomas Lamprecht
2025-11-11 13:57 ` [pve-devel] [PATCH qemu-server 2/2] fix #6985: ovmf: auto-enroll Microsoft UEFI CA 2023 for Windows Fiona Ebner
2025-11-14 1:18 ` Thomas Lamprecht [this message]
2025-11-14 11:03 ` Fiona Ebner
2025-11-14 11:48 ` Thomas Lamprecht
2025-11-14 12:03 ` Fiona Ebner
2025-11-14 12:12 ` 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=5ce79121-9ce3-4f6f-9842-3c9a5572b99b@proxmox.com \
--to=t.lamprecht@proxmox.com \
--cc=f.ebner@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox