更新虚拟机上的安全启动证书

本文档介绍了如何在 Google Distributed Cloud (GDC) 气隙环境中续订虚拟机 (VM) 上的统一可扩展固件接口 (UEFI) 安全启动证书。

UEFI 安全启动是一项安全功能,通过验证所有启动组件的数字签名,确保虚拟机系统运行正版软件。如果验证失败,安全启动会停止虚拟机启动过程。

Microsoft 使用安全证书来支持各种操作系统中的安全启动。部分安全启动证书即将过期。为避免系统中断,您必须续订这些证书。

本文档适用于平台管理员或应用运维人员群组中的开发者,这些开发者需要在 Distributed Cloud 环境中配置虚拟机的安全启动。如需了解详情,请参阅 GDC 网闸隔离配置文档的受众群体

准备工作

Distributed Cloud 的所有命令都使用 gdcloudkubectl CLI,并且需要操作系统 (OS) 环境。确保您已下载、安装并配置 gdcloud CLI

获取 kubeconfig 文件

如需针对管理 API 服务器运行命令,请确保您拥有以下资源:

  1. 登录并生成管理 API 服务器的 kubeconfig 文件(如果您还没有)。

  2. 使用管理 API 服务器的 kubeconfig 文件的路径替换这些说明中的 MANAGEMENT_API_SERVER

申请 IAM 角色

如需更新虚拟机上的安全启动证书,请与项目 IAM 管理员联系,请求授予 Virtual Machine Project Admin (project-vm-admin) 角色。

所有虚拟机角色都必须绑定到虚拟机所在项目的命名空间。按照相关步骤验证您的访问权限。

安全启动证书

所有安全启动证书都有失效日期。在您安装 Windows 启动管理器或 Linux shim 的第一个安全更新之前,证书过期的虚拟机会正常启动。在进行上述任何更新后,虚拟机将无法启动,直到您更新过期的证书为止。

即将过期的证书

下表介绍了旧版安全启动证书的最终过期日期:

证书名称 证书失效日期
Microsoft Corporation KEK CA 2011 2026 年 6 月 26 日
Microsoft UEFI CA 2011 2026 年 6 月 26 日
Microsoft Windows Production PCA 2011 2026 年 10 月 19 日

新证书

下表介绍了新安全启动证书的最终到期日期:

证书名称 证书失效日期
Microsoft UEFI CA 2023 2038 年 6 月 13 日
Microsoft Corporation KEK 2K CA 2023 2038 年 3 月 2 日
Microsoft Option ROM UEFI CA 2023 2038 年 10 月 26 日
Windows UEFI CA 2023 2035 年 6 月 13 日

证书续订流程

如需在虚拟机上执行安全启动证书续订,您必须使用注释和受控更新选择启用。更新后,使用旧映像或新映像创建的所有新虚拟机会同时安装这两个证书,并成功启动。

识别虚拟机并应用注解

确定命名空间或项目中受影响的虚拟机。确定后,将更新注解应用于受影响的虚拟机实例。

  1. 使用 kubectl 检查 enableSecureBoot 状态:

    kubectl --kubeconfig MANAGEMENT_API_SERVER get vms --all-namespaces -o \
        custom-columns="NAMESPACE:.metadata.namespace,NAME:.metadata.name,SECURE_BOOT:.spec.shieldConfig.enableSecureBoot"
    
  2. 将注解应用于虚拟机自定义资源,以将虚拟机标记为已准备好进行更新。这会在下次虚拟机重新启动时注册证书:

    kubectl --kubeconfig MANAGEMENT_API_SERVER annotate virtualmachine VM_NAME -n VM_NAMESPACE virtualmachine.gdc.goog/enable-microsoft-2023-sbcert="true" --overwrite
    

    执行以下变量替换操作:

    • VM_NAME:虚拟机实例的名称。
    • VM_NAMESPACE:虚拟机所在的命名空间的名称。
  3. 批量将注解应用于项目中的所有虚拟机:

    kubectl --kubeconfig MANAGEMENT_API_SERVER annotate virtualmachine --all -n VM_NAMESPACE virtualmachine.gdc.goog/enable-microsoft-2023-sbcert="true" --overwrite
    

    只要未使用磁盘加密,您就可以在组织中的所有虚拟机上批量应用注解标签。

    在项目级层,项目所有者可以单独为符合条件的虚拟机应用标签。

  4. 如需应用更改,请重启虚拟机:

    kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine VM_NAME -n VM_NAMESPACE -p '{"spec":{"runningState":"Stopped"}}' --type=merge
    
    kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine VM_NAME -n VM_NAMESPACE -p '{"spec":{"runningState":"Running"}}' --type=merge
    

特殊处理:BitLocker 和 FDE

您必须执行以下任务:

  1. 暂时停用 BitLocker、LUKS 或任何类似的加密解决方案。
  2. 确保恢复密钥随时可用,并且备份是最新的。
  3. 应用证书续订流程的第 2 步中提到的安全启动更新注解。
  4. 重新启动虚拟机以注册证书。
  5. 验证更新后,重新启用 BitLocker、LUKS 或 FDE。

停用 BitLocker

在应用 "virtualmachine.gdc.goog/enable-microsoft-2023-sbcert" 注解之前,您必须在虚拟机上停用 BitLocker。这需要进行磁盘解密。等待解密过程完成后再应用注解。

使用以下脚本停用 BitLocker:

disable_bitlocker.ps1

   # Log start time
   Add-Content -Path C:\disable_bitlocker_log.txt -Value "Script started at $(Get-Date)"

   # Get all BitLocker volumes
   $BitLockerVolumes = Get-BitLockerVolume

   if ($BitLockerVolumes) {
       foreach ($Volume in $BitLockerVolumes) {
           Add-Content -Path C:\disable_bitlocker_log.txt -Value "Processing volume: $($Volume.MountPoint)"
           if ($Volume.ProtectionStatus -eq 'On') {
               Add-Content -Path C:\disable_bitlocker_log.txt -Value "Disabling BitLocker on $($Volume.MountPoint)"
               try {
                   Disable-BitLocker -MountPoint $Volume.MountPoint -ErrorAction Stop
                   Add-Content -Path C:\disable_bitlocker_log.txt -Value "Successfully initiated BitLocker disable on $($Volume.MountPoint). Decryption may take time."
               } catch {
                   Add-Content -Path C:\disable_bitlocker_log.txt -Value "ERROR disabling BitLocker on $($Volume.MountPoint): $($_.Exception.Message)"
               }
           } else {
               Add-Content -Path C:\disable_bitlocker_log.txt -Value "BitLocker is already Off or Unprotected on $($Volume.MountPoint)"
           }
       }
   } else {
       Add-Content -Path C:\disable_bitlocker_log.txt -Value "No BitLocker volumes found."
   }

   # Log end time
   Add-Content -Path C:\disable_bitlocker_log.txt -Value "Script finished at $(Get-Date)"

disable_bitlocker.ps1 脚本添加到虚拟机启动脚本

如需在虚拟机重启时停用 BitLocker,您可以在正在运行的虚拟机中运行此脚本,也可以将其添加到启动脚本中。按照以下步骤将此脚本用作启动脚本。

  1. 对脚本进行 Base64 编码并创建 Kubernetes Secret:

    # Encode the script
    B64_SCRIPT=$(base64 -w 0 disable_bitlocker.ps1)
    
    # Create Secret YAML
    cat <<EOF > disable_bitlocker_secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: disable-bitlocker-script
      namespace: VM_NAMESPACE
    type: Opaque
    data:
      script: $B64_SCRIPT
    EOF
    
    # Apply the Secret to the GDCer
    kubectl --kubeconfig MANAGEMENT_API_SERVER -f disable_bitlocker_secret.yaml
    
  2. 修补虚拟机 CR 以将 disable-bitlocker.ps1 脚本添加到启动脚本 spec 字段:

    spec:
      # ... other existing spec fields ...
      osType: Windows
      startupScripts:
        - name: disable-bitlocker-ps1 # Note the -ps1 suffix
          scriptSecretRef:
            name: disable-bitlocker-script
    
  3. 重启虚拟机:

    • 停止虚拟机:

      kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine VM_NAME -n VM_NAMESPACE -p '{"spec":{"runningState":"Stopped"}}' --type=merge
      
    • 启动该虚拟机:

      kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine <vm-name> -n VM_NAMESPACE -p '{"spec":{"runningState":"Running"}}' --type=merge
      

检查 BitLocker 状态

如需验证卷是否已完全解密,然后再继续操作,请使用以下任一 PowerShell 命令检查 BitLocker 状态:

  • 检查所有硬盘的状态:

    Get-BitLockerVolume
    
  • 检查特定硬盘的状态:

    Get-BitLockerVolume -MountPoint "C:"
    

或者,您可以使用 manage-bde 命令检查所有硬盘的状态:

manage-bde -status

停用 BitLocker 后的输出类似于下图:

一个 PowerShell CLI 屏幕,在运行 manage-bde -status 后显示 BitLocker 状态为 False

可选:验证

如果您想验证虚拟机上存在的证书,请按照相应操作系统的步骤操作:

Linux

  1. 使用 mokutil 验证您的计算机上是否已启用安全启动:

    user@vm1:~$ mokutil --sb-state
    

    如果启用了安全启动,则输出类似于以下内容:

    SecureBoot enabled
    
  2. mokutil 命令与相应标志搭配使用,并使用 grep 将搜索范围缩小到特定证书年份。

    2023 年证书

    user@vm1:~$ mokutil --kek | grep 2023
    

    输出类似于以下内容:

        Not Before: Mar  2 20:21:35 2023 GMT
        Subject: C=US, O=Microsoft Corporation, CN=Microsoft Corporation KEK 2K CA 2023
    
    user@vm1:~$ mokutil --db | grep 2023
    

    输出类似于以下内容:

        Not Before: Jun 13 19:21:47 2023 GMT
        Subject: C=US, O=Microsoft Corporation, CN=Microsoft UEFI CA 2023
        Not Before: Jun 13 18:58:29 2023 GMT
        Subject: C=US, O=Microsoft Corporation, CN=Windows UEFI CA 2023
    

    2011 年证书

    user@vm1:~$ mokutil --kek | grep 2011
    

    输出类似于以下内容:

        Not Before: Jun 24 20:41:29 2011 GMT
        Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation KEK CA 2011
    
    user@vm1:~$ mokutil --db | grep 2011
    

    输出类似于以下内容:

        Not Before: Oct 19 18:41:42 2011 GMT
        Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Windows Production PCA 2011
        Not Before: Jun 27 21:22:45 2011 GMT
        Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation UEFI CA 2011
    

Windows

  1. 验证系统上是否存在安全启动证书:

    PS C:\Windows\system32> Confirm-SecureBootUEFI
    

    如果您的计算机上存在证书,则输出为 True

  2. 使用 -match 标志将命令附加到适用的证书年份:

    PS C:\Windows\system32> [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI KEK).bytes) -match "2023"
    PS C:\Windows\system32> [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI KEK).bytes) -match "2011"
    PS C:\Windows\system32> [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match "2011"
    PS C:\Windows\system32> [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match "2023"
    

排查续订问题

如果现有虚拟机上出现续订问题,请通过向虚拟机 CR 添加注解来回滚更改。虚拟机将使用之前的旧证书启动。

回滚更改

  1. 将以下注解添加到您的虚拟机自定义资源:

    注释

    kubectl --kubeconfig MANAGEMENT_API_SERVER annotate virtualmachine VM_NAME -n VM_NAMESPACE virtualmachine.gdc.goog/recover-efi-backup="true" --overwrite
    
  2. 重启虚拟机以恢复旧证书:

    • 停止虚拟机:

      kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine VM_NAME -n VM_NAMESPACE -p '{"spec":{"runningState":"Stopped"}}' --type=merge
      
    • 启动该虚拟机:

      kubectl --kubeconfig MANAGEMENT_API_SERVER patch VirtualMachine VM_NAME -n VM_NAMESPACE -p '{"spec":{"runningState":"Running"}}' --type=merge