all lists on lists.proxmox.com
 help / color / mirror / Atom feed
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


  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 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.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal