更新 VM 上的安全啟動憑證

本文說明如何在 Google Distributed Cloud (GDC) 實體隔離方案的虛擬機器 (VM) 上,更新統一可延伸韌體介面 (UEFI) 安全啟動憑證。

UEFI 安全啟動是一項安全防護功能,可驗證所有啟動元件的數位簽章,確保 VM 系統執行的是正版軟體。如果驗證失敗,安全啟動功能會停止 VM 啟動程序。

Microsoft 使用安全性憑證,在各種作業系統上支援安全啟動。部分安全啟動憑證即將到期。為避免系統中斷,請務必更新這些憑證。

本文適用對象為平台管理員或應用程式操作員群組中的開發人員,他們會在 Distributed Cloud 環境中設定 VM 的安全啟動功能。詳情請參閱「GDC 實體隔離方案說明文件的目標對象」。

事前準備

Distributed Cloud 的所有指令都使用 gdcloud 或 kubectl CLI,且需要作業系統 (OS) 環境。請務必下載、安裝及設定 gdcloud CLI。

取得 kubeconfig 檔案

如要對 Management API 伺服器執行指令,請確認您具備下列資源:

  1. 如果您沒有管理 API 伺服器的 kubeconfig 檔案,請登入並產生該檔案。

  2. 請使用 Management API 伺服器的 kubeconfig 檔案路徑,取代這些操作說明中的 MANAGEMENT_API_SERVER。

要求 IAM 角色

如要更新 VM 的安全啟動憑證,請向 IAM 專案管理員要求虛擬機器專案管理員 (project-vm-admin) 角色。

所有 VM 角色都必須繫結至 VM 所在專案的命名空間。按照步驟驗證存取權。

安全啟動憑證

所有安全啟動憑證都有到期日。憑證過期的 VM 會正常啟動,直到您為 Windows Boot Manager 或 Linux shim 安裝第一個安全性更新為止。完成上述任一更新後,VM 將無法啟動,直到您更新過期憑證為止。

即將到期的憑證

下表說明舊安全啟動憑證的最終到期日:

憑證名稱 憑證到期日
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 日

憑證續約程序

如要在 VM 上執行安全啟動憑證更新,您必須使用註解和受控更新選擇加入。更新後,使用舊或新映像檔建立的所有新 VM 都會安裝這兩個憑證,並成功啟動。

找出 VM 並套用註解

找出命名空間或專案中受影響的 VM。找出後,請將更新註解套用至受影響的 VM 執行個體。

  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. 將註解套用至 VM 自訂資源,將 VM 標示為可更新。這會在下次 VM 重新啟動時註冊憑證:

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

    請替換下列變數:

    • VM_NAME:VM 執行個體的名稱。
    • VM_NAMESPACE:VM 所在的命名空間名稱。
  3. 將註解大量套用至專案中的所有 VM:

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

    只要未使用磁碟加密,您就可以在組織中的所有 VM 大量套用註解標籤。

    在專案層級,專案擁有者可以個別為符合條件的 VM 套用標籤。

  4. 如要套用變更,請重新啟動 VM:

    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. 重新啟動 VM 即可註冊憑證。
  5. 確認更新後,重新啟用 BitLocker、LUKS 或 FDE。

停用 BitLocker

套用 "virtualmachine.gdc.goog/enable-microsoft-2023-sbcert" 註解前,請務必停用 VM 上的 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 指令碼新增至 VM 開機指令碼

如要在 VM 重新啟動時停用 BitLocker,您可以在執行中的 VM 執行這個指令碼,或將其新增至開機指令碼。請按照步驟將這個指令碼設為開機指令碼。

  1. 對指令碼進行 Base 編碼,並建立 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. 修補 VM 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. 重新啟動 VM:

    • 停止 VM:

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

      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 狀態

選用:驗證

如要驗證 VM 上的憑證,請按照對應 OS 的步驟操作:

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. 確認系統上有安全啟動憑證:

    Confirm-SecureBootUEFI
    

    如果機器上有憑證,輸出內容會是 True。

  2. 使用 -match 旗標,在指令中附加適用的憑證年份:

    [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI KEK).bytes) -match "2023"
    [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI KEK).bytes) -match "2011"
    [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match "2011"
    [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match "2023"
    

疑難排解續訂問題

如果現有 VM 發生續約問題,請在 VM CR 中新增註解,復原變更。VM 會使用先前的舊憑證啟動。

復原變更

  1. 將下列註解新增至 VM 自訂資源:

    註解:

    kubectl --kubeconfig MANAGEMENT_API_SERVER annotate virtualmachine VM_NAME -n VM_NAMESPACE virtualmachine.gdc.goog/recover-efi-backup="true" --overwrite
    
  2. 重新啟動 VM,復原舊憑證:

    • 停止 VM:

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

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