共用方式為


Azure VM 上的 BitLocker 開機錯誤

適用於:✔️ Windows VM

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

徵兆

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

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

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

  • 輸入密碼以將此磁碟機 [ ] 解除鎖定。按 Insert 鍵可看到您輸入的密碼。

  • 輸入修復金鑰。從 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 檔案。

    如果內容類型值是包裝 BEK,請移至金鑰加密金鑰 (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 OFF:
    manage-bde -protectors -disable F: -rc 0
    
    • 完全解密磁碟驅動器。 若要這樣做,請執行下列命令:
    manage-bde -off F:
    

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

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

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

  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 OFF:
    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並檢查 輸出中的 SettingsKeyEncryptionKeyURL 。 以下是範例:
“KeyEncryptionKeyURL”:https://myKeyVault2707.vault.azure.net/keys/mykey/000072b987145a3b79b0ed415f0000
$kekName mykey 執行 Get-AzVM -ResourceGroupName $rgName -Name $vmName -DisplayHint expand 並檢查 輸出中的 SettingsKeyEncryptionKeyURL 。 以下是範例:
“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 識別碼的 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 意見反應社群提交產品意見反應。