Azure VM 上的 BitLocker 開機錯誤

本文說明當您在 Microsoft Azure 中啟動 Windows 虛擬機器 (VM) 時,可能會遇到的 BitLocker 錯誤。

徵兆

Windows VM 不會啟動。 當您在 [ 開機診斷 ] 視窗中檢查螢幕快照時,您會看到下列其中一個錯誤訊息:

  • 插入具有 BitLocker 金鑰的 USB 驅動程式

  • 您已遭鎖定! 輸入修復金鑰以 (鍵盤配置:美國) 輸入錯誤的登入資訊太多次,因此您的電腦已鎖定以保護您的隱私權。 若要擷取修復金鑰,請從另一部電腦或行動裝置移至 https://windows.microsoft.com/recoverykeyfaq 。 如果您需要,金鑰標識碼是 XXXXXXXXX。 或者,您可以重設計算機。

  • 輸入密碼以解除鎖定此磁碟驅動器 [ ] 按下 [插入金鑰] 以在您輸入時查看密碼。

  • 輸入修復金鑰 從 USB 裝置載入修復金鑰。

原因

如果 VM 找不到 BitLocker 修復金鑰 (BEK) 檔案來解密加密的磁碟,就可能會發生此問題。

解密加密的OS磁碟

提示

如果您有 VM 的最新備份,您可以嘗試 從備份還原 VM ,以修正開機問題。

若要解決此問題,請停止並解除分配 VM,然後啟動它。 此作業會強制 VM 從 Azure 金鑰保存庫 擷取 BEK 檔案,然後將它放在加密的磁碟上。

如果此方法無法解決問題,請遵循下列步驟手動還原 BEK 檔案:

  1. 擷取受影響 VM 的 OS 磁碟快照作為備份。 如需詳細資訊,請參閱 建立磁碟的快照集。

  2. 將 OS 磁碟連結至復原 VM。 當您連接受控磁碟時,可能會收到「包含加密設定,因此無法作為數據磁碟」錯誤訊息。 在此情況下,請執行下列腳本來再次嘗試連結磁碟:

    $rgName = "myResourceGroup"
    $osDiskName = "ProblemOsDisk"
    # Set the EncryptionSettingsEnabled property to false, so you can attach the disk to the recovery VM.
    New-AzDiskUpdateConfig -EncryptionSettingsEnabled $false |Update-AzDisk -diskName $osDiskName -ResourceGroupName $rgName
    
    $recoveryVMName = "myRecoveryVM" 
    $recoveryVMRG = "RecoveryVMRG" 
    $OSDisk = Get-AzDisk -ResourceGroupName $rgName -DiskName $osDiskName;
    
    $vm = get-AzVM -ResourceGroupName $recoveryVMRG -Name $recoveryVMName 
    
    Add-AzVMDataDisk -VM $vm -Name $osDiskName -ManagedDiskId $osDisk.Id -Caching None -Lun 3 -CreateOption Attach 
    
    Update-AzVM -VM $vm -ResourceGroupName $recoveryVMRG
    

    您無法將受控磁碟連結至從 Blob 映射還原的 VM。

  3. 連接磁碟之後,請建立與復原 VM 的遠端桌面連線。

  4. 在復原 VM 中安裝 Az PowerShell 模組和 Az.Account 1.9.4

  5. (以系統管理員) 身分執行,開啟提升許可權的 Azure PowerShell 會話。 執行下列命令以登入 Azure 訂用帳戶:

    Add-AzAccount -SubscriptionID [SubscriptionID]
    
  6. 執行下列腳本來檢查 BEK 檔案的名稱 (秘密名稱) :

    $vmName = "myVM"
    $vault = "myKeyVault"
    Get-AzKeyVaultSecret -VaultName $vault | where {($_.Tags.MachineName -eq $vmName) -and ($_.ContentType -match 'BEK')} `
            | Sort-Object -Property Created `
            | ft  Created, `
                @{Label="Content Type";Expression={$_.ContentType}}, `
                @{Label ="MachineName"; Expression = {$_.Tags.MachineName}}, `
                @{Label ="Volume"; Expression = {$_.Tags.VolumeLetter}}, `
                @{Label ="DiskEncryptionKeyFileName"; Expression = {$_.Tags.DiskEncryptionKeyFileName}}
    

    以下是輸出的範例。 在此情況下,我們假設檔名是 EF7B2F5A-50C6-4637-0001-7F599C12F85C。BEK。

    Created               Content Type Volume MachineName DiskEncryptionKeyFileName
    -------               ------------ ------ ----------- -------------------------
    11/20/2020 7:41:56 AM BEK          C:\    myVM   EF7B2F5A-50C6-4637-0001-7F599C12F85C.BEK
    

    如果您看到兩個重複的磁碟區,具有較新時間戳的磁碟區就是復原 VM 目前使用的 BEK 檔案。

    如果 內容類型 值為 Wrapped BEK,請移至 KEY Encryption Key (KEK) 案例

    現在您已擁有磁碟驅動器的 BEK 檔案名稱,您必須建立 secret-file-name。將磁碟驅動器解除鎖定的 BEK 檔案。

  7. 將 BEK 檔案下載到復原磁碟。 下列範例會將 BEK 檔案儲存至 C:\BEK 資料夾。 執行文稿之前, C:\BEK\ 請確定路徑存在。

    $vault = "myKeyVault"
    $bek = "EF7B2F5A-50C6-4637-0001-7F599C12F85C"
    $keyVaultSecret = Get-AzKeyVaultSecret -VaultName $vault -Name $bek
    $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($keyVaultSecret.SecretValue)
    $bekSecretBase64 = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
    $bekFileBytes = [Convert]::FromBase64String($bekSecretbase64)
    $path = "C:\BEK\DiskEncryptionKeyFileName.BEK"
    [System.IO.File]::WriteAllBytes($path,$bekFileBytes)
    
  8. 若要使用 BEK 檔案解除鎖定連結的磁碟,請執行下列命令。

    manage-bde -unlock F: -RecoveryKey "C:\BEK\EF7B2F5A-50C6-4637-0001-7F599C12F85C.BEK"
    

    在此範例中,連結的OS磁碟是磁碟驅動器 F。請確定您使用正確的驅動器號。

  9. 使用 BEK 金鑰成功解除鎖定磁碟之後,請中斷磁碟與復原 VM 的連結,然後使用這個新的 OS 磁碟重新建立 VM。

    注意事項

    交換OS磁碟適用於任何使用單一傳遞 ADE 版本加密的 VM,但不支援雙重傳遞。

  10. 如果新的 VM 仍然無法正常開機,請在解除鎖定磁碟驅動器之後嘗試下列其中一個步驟:

    • 執行下列命令,暫停保護以暫時關閉 BitLocker:
    manage-bde -protectors -disable F: -rc 0
    
    • 完全解密磁碟驅動器。 若要執行此動作,請執行下列命令:
    manage-bde -off F:
    

金鑰加密金鑰案例 (包裝的 BEK)

針對金鑰加密金鑰案例,請遵循下列步驟:

  1. 請確定登入的用戶帳戶需要使用者中 金鑰保存庫 存取原則中的「未包裝」許可權|密鑰限 |密碼編譯作業 |解除包裝金鑰

  2. 將下列文稿儲存至 .PS1 檔案:

    注意事項

    此腳本中使用的 ADAL 元件 (dll 檔案) 僅適用於 Az.Account 1.9.4 和舊版。 若要安裝 Az.Account 模組,請參閱 安裝 Az PowerShell 模組

    #Set the Parameters for the script. If you have question about the Parameters, see the "KEK script parameters" section.
    param (
            [Parameter(Mandatory=$true)]
            [string] 
            $keyVaultName,
            [Parameter(Mandatory=$true)]
            [string] 
            $kekName,
            [Parameter(Mandatory=$true)]
            [string]
            $secretName,
            [Parameter(Mandatory=$true)]
            [string]
            $bekFilePath,
            [Parameter(Mandatory=$true)]
            [string] 
            $adTenant
            )
    # Load ADAL Assemblies. If the ADAL Assemblies cannot be found, please see the "Install Az PowerShell module" section. 
    
    $adal = "${env:ProgramFiles}\WindowsPowerShell\Modules\Az.Accounts\1.9.4\PreloadAssemblies\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
    $adalforms = "${env:ProgramFiles}\WindowsPowerShell\Modules\Az.Accounts\1.9.4\PreloadAssemblies\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"  
    
    If ((Test-Path -Path $adal) -and (Test-Path -Path $adalforms)) { 
    
    [System.Reflection.Assembly]::LoadFrom($adal)
    [System.Reflection.Assembly]::LoadFrom($adalforms)
     }
     else
     {
      Write-output "ADAL Assemblies files cannot be found. Please set the correct path for `$adal` and `$adalforms`, then run the script again." 
      exit    
     }  
    
    # Set well-known client ID for AzurePowerShell
    $clientId = "1950a258-227b-4e31-a9cf-717495945fc2" 
    # Set redirect URI for Azure PowerShell
    $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
    # Set Resource URI to Azure Service Management API
    $resourceAppIdURI = "https://vault.azure.net"
    # Set Authority to Azure AD Tenant
    $authority = "https://login.windows.net/$adtenant"
    # Create Authentication Context tied to Azure AD Tenant
    $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
    # Acquire token
    $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
    $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $clientId, $redirectUri, $platformParameters).result
    # Generate auth header 
    $authHeader = $authResult.CreateAuthorizationHeader()
    # Set HTTP request headers to include Authorization header
    $headers = @{'x-ms-version'='2014-08-01';"Authorization" = $authHeader}
    
    ########################################################################################################################
    # 1. Retrieve wrapped BEK
    # 2. Make KeyVault REST API call to unwrap the BEK
    # 3. Convert the Base64Url string returned by KeyVault unwrap to Base64 string 
    # 4. Convert Base64 string to bytes and write to the BEK file
    ########################################################################################################################
    
    #Get wrapped BEK and place it in JSON object to send to KeyVault REST API
    $keyVaultSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $secretName
    $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($keyVaultSecret.SecretValue)
    $wrappedBekSecretBase64 = [Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
    $jsonObject = @"
    {
    "alg": "RSA-OAEP",
    "value" : "$wrappedBekSecretBase64"
    }
    "@
    
    #Get KEK Url
    $kekUrl = (Get-AzKeyVaultKey -VaultName $keyVaultName -Name $kekName).Key.Kid;
    $unwrapKeyRequestUrl = $kekUrl+ "/unwrapkey?api-version=2015-06-01";
    
    #Call KeyVault REST API to Unwrap 
    $result = Invoke-RestMethod -Method POST -Uri $unwrapKeyRequestUrl -Headers $headers -Body $jsonObject -ContentType "application/json" -Debug
    
    #Convert Base64Url string returned by KeyVault unwrap to Base64 string
    $base64UrlBek = $result.value;
    $base64Bek = $base64UrlBek.Replace('-', '+');
    $base64Bek = $base64Bek.Replace('_', '/');
    if($base64Bek.Length %4 -eq 2)
    {
        $base64Bek+= '==';
    }
    elseif($base64Bek.Length %4 -eq 3)
    {
        $base64Bek+= '=';
    }
    
    #Convert base64 string to bytes and write to BEK file
    $bekFileBytes = [System.Convert]::FromBase64String($base64Bek);
    [System.IO.File]::WriteAllBytes($bekFilePath,$bekFileBytes)
    
    #Delete the key from the memory
    [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
    clear-variable -name wrappedBekSecretBase64
    
  3. 設定參數。 腳本會處理 KEK 秘密以建立 BEK 金鑰,然後將其儲存至復原 VM 上的本機資料夾。 如果您在執行文稿時收到錯誤,請參閱 腳本疑難解答一 節。

  4. 當文稿開始時,您會看到下列輸出:

    GAC 版本位置


    False v4.0.30319 C:\Program Files\WindowsPowerShell\Modules\Az.Accounts...False v4.0.30319 C:\Program Files\WindowsPowerShell\Modules\Az.Accounts...

    當文稿完成時,您會看到下列輸出:

    VERBOSE: POST https://myvault.vault.azure.net/keys/rondomkey/<KEY-ID>/unwrapkey?api-
    version=2015-06-01 with -1-byte payload
    VERBOSE: received 360-byte response of content type application/json; charset=utf-8
    
  5. 若要使用 BEK 檔案解除鎖定連結的磁碟,請執行下列命令:

    manage-bde -unlock F: -RecoveryKey "C:\BEK\EF7B2F5A-50C6-4637-9F13-7F599C12F85C.BEK
    

    在此範例中,連結的OS磁碟是磁碟驅動器 F。請確定您使用正確的驅動器號。

  6. 使用 BEK 金鑰成功解除鎖定磁碟之後,請將磁碟從復原 VM 中斷連結,然後使用 交換 OS 磁碟 功能,將原始 VM 的 OS 磁碟取代為此修復的磁碟。

  7. 如果新的 VM 仍然無法正常開機,請在解除鎖定磁碟驅動器之後嘗試下列其中一個步驟:

    • 執行下列命令,暫停保護以暫時關閉 BitLocker:
    manage-bde -protectors -disable F: -rc 0
    
    • 完全解密磁碟驅動器。 若要執行此動作,請執行下列命令:
    manage-bde -off F:
    

腳本疑難解答

錯誤:無法載入檔案或元件

發生此錯誤的原因是ADAL元件的路徑錯誤。 您可以搜尋 Az.Accounts 資料夾以尋找正確的路徑。

錯誤:Get-AzKeyVaultSecret 或 Get-AzKeyVaultSecret 無法辨識為 Cmdlet 的名稱

如果您使用舊的 Az PowerShell 模組,則必須將兩個命令變更為 Get-AzureKeyVaultSecretGet-AzureKeyVaultSecret

KEK 腳本參數

參數 範例 如何檢查
$keyVaultName myKeyVault2707 Get-AzVM -ResourceGroupName $rgName -Name $vmName -DisplayHint Expand輸出中執行並檢查 [設定 ] 和 [KeyEncryptionKeyURL ]。 以下是範例:「
KeyEncryptionKeyURL」:https://myKeyVault2707.vault.azure.net/keys/mykey/000072b987145a3b79b0ed415f0000
$kekName mykey Get-AzVM -ResourceGroupName $rgName -Name $vmName -DisplayHint expand 輸出中執行並檢查 [設定 ] 和 [KeyEncryptionKeyURL ]。 以下是範例:「
KeyEncryptionKeyURL」:https://myKeyVault2707.vault.azure.net/keys/mykey/000072b987145a3b79b0ed415f0000
$secretName 7EB4F531-5FBA-4970-8E2D-C11FD6B0C69D VM 金鑰的秘密名稱。
若要尋找正確的秘密名稱,請檢查 解密加密 OS 磁碟 一節中的步驟 6。
$bekFilePath c:\bek\7EB4F531-5FBA-4970-8E2D-C11FD6B0C69D。BEK 您要儲存 BEK 檔案的本機路徑。 在此範例中,您必須先建立 「bek」 資料夾,才能執行腳本,否則會發生錯誤。
$adTenant contoso.onmicrosoft.com 裝載金鑰保存庫之 Microsoft Entra ID 的 FQDN 或 GUID

安裝 Az PowerShell 模組

若要安裝復原 VM 的 Az PowerShell 模組,請遵循下列步驟:

  1. 以系統管理員身分開啟PowerShell工作階段,並將目前工作階段的 HTTP API 安全性通訊協定設定為 TLS 1.2。 關閉目前的會話之後,安全性通訊協定將會還原為預設值。

    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    
  2. 下載最新版的 Nuget 套件:

     Install-PackageProvider -Name "Nuget" -Force
    
    
  3. 安裝最新版的 PowerShellGet 套件,然後重新啟動 PowerShell。

    Install-Module -Name PowerShellGet -Force
    
  4. 執行下列命令以安裝最新版的 Azure Az 模組:

    Install-Module -Name Az -Scope AllUsers -Repository PSGallery -Force
    
  5. 安裝 Az.Account 1.9.4 套件:

    Install-Module -Name Az.Accounts -Scope AllUsers -RequiredVersion "1.9.4" -Repository PSGallery -Force
    

與我們連絡,以取得說明

如果您有問題或需要相關協助,請建立支援要求,或詢問 Azure community 支援。 您也可以將產品意見反應提交給 Azure 意應見反社群