這很重要
Azure 磁碟加密預定於 2028 年 9 月 15 日退休。 在此之前,您可以繼續使用 Azure 磁碟加密,不會中斷。 2028 年 9 月 15 日,啟用 ADE 的工作負載仍可繼續運行,但加密磁碟在虛擬機重啟後將無法解鎖,導致服務中斷。
對於新虛擬機,可以在主機上使用 加密 ,或考慮 機密虛擬機大小搭配作業系統磁碟加密 來處理機密運算工作負載。 所有啟用 ADE 的虛擬機(包括備份)必須在退休日前遷移至主機加密,以避免服務中斷。 詳情請參見「 從 Azure 磁碟加密遷移到主機加密 」。
適用於:✔️ Windows VM
本文提供了對於準備預先加密 VHD 和其他工作的範例指令碼。
注意
除非另有說明,所有指令碼參考的都是 ADE 的最新且非 AAD 的版本。
Azure 磁碟加密的範例 PowerShell 指令碼
- 列出訂用帳戶中的所有已加密 VM
你可以使用 Find_1passAdeVersion_VM.ps1 PowerShell 指令碼,找出訂閱中所有資源群組內所有經 ADE 加密的虛擬機器及其擴充功能版本。
或者,這些 cmdlet 顯示所有 DEDE 加密的虛擬機(但不包括擴充功能版本):
$osVolEncrypted = {(Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name).OsVolumeEncrypted}
$dataVolEncrypted= {(Get-AzVMDiskEncryptionStatus -ResourceGroupName $_.ResourceGroupName -VMName $_.Name).DataVolumesEncrypted}
Get-AzVm | Format-Table @{Label="MachineName"; Expression={$_.Name}}, @{Label="OsVolumeEncrypted"; Expression=$osVolEncrypted}, @{Label="DataVolumesEncrypted"; Expression=$dataVolEncrypted}
列出訂用帳戶中的所有已加密 VMSS 執行個體
你可以透過 Find_1passAdeVersion_VMSS.ps1 PowerShell 腳本找到所有 DEDE 加密的虛擬機 Scale Set 實例及擴充版本,涵蓋訂閱中所有資源群組。
列出所有用於虛擬機器加密且存放於金鑰保存庫中的磁碟加密憑證
Get-AzKeyVaultSecret -VaultName $KeyVaultName | where {$_.Tags.ContainsKey('DiskEncryptionKeyFileName')} | format-table @{Label="MachineName"; Expression={$_.Tags['MachineName']}}, @{Label="VolumeLetter"; Expression={$_.Tags['VolumeLetter']}}, @{Label="EncryptionKeyURL"; Expression={$_.Id}}
使用 Azure 磁碟加密先決條件 PowerShell 指令碼
如果您已經熟悉 Azure 磁碟加密的必要條件,您可以使用 Azure 磁碟加密必要條件 PowerShell 指令碼。 如需使用此 PowerShell 指令碼的範例,請參閱加密 VM 快速入門。 您可以從指令碼區段 (起自 211 行) 中移除註解,以對現有資源群組中現有 VM 的所有磁碟加密。
下表顯示可在 PowerShell 腳本中使用的參數:
| 參數 | 描述 | 必要? |
|---|---|---|
| $resourceGroupName | 金鑰庫所屬的資源群組名稱。 如果沒有這個名稱的資源群組,腳本會建立一個新的資源群組。 | True |
| $keyVaultName | 存放加密金鑰的金庫名稱。 如果不存在使用此名稱的保險庫,腳本會建立一個新的保險庫。 | True |
| $location | 鑰匙庫的位置。 確保金鑰庫和要加密的虛擬機都在同一個位置。 使用 Get-AzLocation 取得位置清單。 |
True |
| $subscriptionId | 要使用的 Azure 訂用帳戶識別碼。 使用 Get-AzSubscription 取得您的訂閱 ID。 |
True |
| $aadAppName | 將祕密寫入 金鑰保存庫 的 Microsoft Entra 應用程式名稱。 如果沒有這個名稱的應用程式,腳本會建立一個新的應用程式。 如果這個應用程式已經存在,請將 aadClientSecret 參數傳給腳本。 | 假 |
| $aadClientSecret | 先前建立之 Microsoft Entra 應用程式的用戶端秘密。 | 假 |
| $keyEncryptionKeyName | 金鑰保存庫 中選用的金鑰加密金鑰名稱。 如果沒有這個名稱的金鑰,腳本會建立一個新的金鑰。 | 假 |
Resource Manager 範本
在沒有 Microsoft Entra 應用程式的情況下加密或解密 VM
使用 Microsoft Entra 應用程式來加密或解密虛擬機
- 在現有或執行中的 Windows VM 上啟用磁碟加密
- 在執行中 Windows VM 上停用加密
- 從預先加密的 VHD/儲存區建立新的加密管理磁碟 - 從預加密的 VHD 及其相應的加密設定建立新的加密管理磁碟。
準備已預先加密的 Windows VHD
以下章節說明如何準備預先加密的 Windows VHD,以便在 Azure IaaS 中部署為加密 VHD。 利用這些資訊在 Azure Site Recovery 或 Azure 上準備並啟動一個全新的 Windows 虛擬機(VHD)。 欲了解更多如何準備與上傳 VHD,請參閱「上傳通用 VHD 並使用它在 Azure 中建立新虛擬機」。
更新群組原則以允許沒有使用 TPM 的作業系統防護措施。
設定 BitLocker 磁碟機加密的 BitLocker 群組政策設定,位於 本機電腦原則>電腦設定>系統管理範本>Windows 元件。 變更此設定為作業系統磁碟驅動器>在啟動時需額外驗證>允許在無相容 TPM 的情況下使用 BitLocker,如下圖所示:
安裝 BitLocker 功能元件
針對 Windows Server 2012 和更新版本,請使用下列命令︰
dism /online /Enable-Feature /all /FeatureName:BitLocker /quiet /norestart
針對 Windows Server 2008 R2,請使用下列命令︰
ServerManagerCmd -install BitLockers
使用 bdehdcfg 來準備 OS 磁碟區供 BitLocker 使用
若要壓縮作業系統磁碟分割並為 BitLocker 準備電腦,請視需要執行 bdehdcfg:
bdehdcfg -target c: shrink -quiet
使用 BitLocker 保護作業系統磁碟區
使用 manage-bde 命令來使用外部金鑰保護裝置啟用開機磁碟區的加密。 也將外部金鑰 (.bek 檔案) 放置於外部磁碟機或磁碟區。 下次重新開機後,會在系統/開機磁碟區上啟用加密。
manage-bde -on %systemdrive% -sk [ExternalDriveOrVolume]
reboot
注意
使用 BitLocker,為 VM 準備獨立的資料/資源 VHD,以取得外部金鑰。
上傳加密的 VHD 至 Azure 儲存體帳戶
啟用 BitLocker 加密之後,您必須將本機加密的 VHD 上傳至您的儲存體帳戶。
Add-AzVhd [-Destination] <Uri> [-LocalFilePath] <FileInfo> [[-NumberOfUploaderThreads] <Int32> ] [[-BaseImageUriToPatch] <Uri> ] [[-OverWrite]] [ <CommonParameters>]
將已預先加密 VM 的祕密上傳至金鑰保存庫
把您之前在金鑰保存庫中取得的磁碟加密秘密資料上傳。 若要這麼做,請將 set secret 權限和 wrap key 權限授與給上傳祕密的帳戶。
# Typically, account Id is the user principal name (in user@domain.com format)
$upn = (Get-AzureRmContext).Account.Id
Set-AzKeyVaultAccessPolicy -VaultName $kvname -UserPrincipalName $acctid -PermissionsToKeys wrapKey -PermissionsToSecrets set
# In cloud shell, the account ID is a managed service identity, so specify the username directly
# $upn = "user@domain.com"
# Set-AzKeyVaultAccessPolicy -VaultName $kvname -UserPrincipalName $acctid -PermissionsToKeys wrapKey -PermissionsToSecrets set
# When running as a service principal, retrieve the service principal ID from the account ID, and set access policy to that
# $acctid = (Get-AzureRmContext).Account.Id
# $spoid = (Get-AzureRmADServicePrincipal -ServicePrincipalName $acctid).Id
# Set-AzKeyVaultAccessPolicy -VaultName $kvname -ObjectId $spoid -BypassObjectIdValidation -PermissionsToKeys wrapKey -PermissionsToSecrets set
未經 KEK 加密的磁碟加密密碼
若要在金鑰保存庫中設定密碼,請使用 Set-AzKeyVaultSecret。 複雜密碼會以 base64 字串編碼,然後上傳至金鑰保存庫。 此外,請確定在金鑰保存庫中建立密碼時會設定下列標籤。
# This is the passphrase that was provided for encryption during the distribution installation
$passphrase = "contoso-password"
$tags = @{"DiskEncryptionKeyEncryptionAlgorithm" = "RSA-OAEP"; "DiskEncryptionKeyFileName" = "LinuxPassPhraseFileName"}
$secretName = [guid]::NewGuid().ToString()
$secretValue = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($passphrase))
$secureSecretValue = ConvertTo-SecureString $secretValue -AsPlainText -Force
$secret = Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $secretName -SecretValue $secureSecretValue -tags $tags
$secretUrl = $secret.Id
在下一個步驟中,使用 $secretUrl 來在不使用 KEK 的情況下附加 OS 磁碟。
使用 KEK 加密的磁碟加密祕密
將密碼上傳至金鑰保存庫之前,您可以選擇性地使用金鑰加密金鑰來加密密碼。 使用包裝 API,先以金鑰加密金鑰加密該秘密。 這個包裝作業的輸出是 base64 URL 編碼的字串,您可以接著使用 Set-AzKeyVaultSecret Cmdlet 將它上傳做為密碼。
# This is the passphrase that was provided for encryption during the distribution installation
$passphrase = "contoso-password"
Add-AzKeyVaultKey -VaultName $KeyVaultName -Name "keyencryptionkey" -Destination Software
$KeyEncryptionKey = Get-AzKeyVaultKey -VaultName $KeyVault.OriginalVault.Name -Name "keyencryptionkey"
$apiversion = "2015-06-01"
##############################
# Get Auth URI
##############################
$uri = $KeyVault.VaultUri + "/keys"
$headers = @{}
$response = try { Invoke-RestMethod -Method GET -Uri $uri -Headers $headers } catch { $_.Exception.Response }
$authHeader = $response.Headers["www-authenticate"]
$authUri = [regex]::match($authHeader, 'authorization="(.*?)"').Groups[1].Value
Write-Host "Got Auth URI successfully"
##############################
# Get Auth Token
##############################
$uri = $authUri + "/oauth2/token"
$body = "grant_type=client_credentials"
$body += "&client_id=" + $AadClientId
$body += "&client_secret=" + [Uri]::EscapeDataString($AadClientSecret)
$body += "&resource=" + [Uri]::EscapeDataString("https://vault.azure.net")
$headers = @{}
$response = Invoke-RestMethod -Method POST -Uri $uri -Headers $headers -Body $body
$access_token = $response.access_token
Write-Host "Got Auth Token successfully"
##############################
# Get KEK info
##############################
$uri = $KeyEncryptionKey.Id + "?api-version=" + $apiversion
$headers = @{"Authorization" = "Bearer " + $access_token}
$response = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers
$keyid = $response.key.kid
Write-Host "Got KEK info successfully"
##############################
# Encrypt passphrase by using a KEK
##############################
$passphraseB64 = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Passphrase))
$uri = $keyid + "/encrypt?api-version=" + $apiversion
$headers = @{"Authorization" = "Bearer " + $access_token; "Content-Type" = "application/json"}
$bodyObj = @{"alg" = "RSA-OAEP"; "value" = $passphraseB64}
$body = $bodyObj | ConvertTo-Json
$response = Invoke-RestMethod -Method POST -Uri $uri -Headers $headers -Body $body
$wrappedSecret = $response.value
Write-Host "Encrypted passphrase successfully"
##############################
# Store secret
##############################
$secretName = [guid]::NewGuid().ToString()
$uri = $KeyVault.VaultUri + "/secrets/" + $secretName + "?api-version=" + $apiversion
$secretAttributes = @{"enabled" = $true}
$secretTags = @{"DiskEncryptionKeyEncryptionAlgorithm" = "RSA-OAEP"; "DiskEncryptionKeyFileName" = "LinuxPassPhraseFileName"}
$headers = @{"Authorization" = "Bearer " + $access_token; "Content-Type" = "application/json"}
$bodyObj = @{"value" = $wrappedSecret; "attributes" = $secretAttributes; "tags" = $secretTags}
$body = $bodyObj | ConvertTo-Json
$response = Invoke-RestMethod -Method PUT -Uri $uri -Headers $headers -Body $body
Write-Host "Stored secret successfully"
$secretUrl = $response.id
在下一個步驟中,使用 $KeyEncryptionKey 和 $secretUrl 來使用 KEK 附加 OS 磁碟。
在附加作業系統磁碟時,指定一個秘密的 URL。
不使用 KEK
附加 OS 磁碟時,請傳遞 $secretUrl。 URL 會在「未使用 KEK 加密的磁碟加密祕密」章節中產生。
Set-AzVMOSDisk `
-VM $VirtualMachine `
-Name $OSDiskName `
-SourceImageUri $VhdUri `
-VhdUri $OSDiskUri `
-Windows `
-CreateOption FromImage `
-DiskEncryptionKeyVaultId $KeyVault.ResourceId `
-DiskEncryptionKeyUrl $SecretUrl
使用 KEK
連接 OS 磁碟時,傳遞 $KeyEncryptionKey 和 $secretUrl。 該 URL 會在「以 KEK 加密的磁碟加密秘密」區塊中產生。
Set-AzVMOSDisk `
-VM $VirtualMachine `
-Name $OSDiskName `
-SourceImageUri $CopiedTemplateBlobUri `
-VhdUri $OSDiskUri `
-Windows `
-CreateOption FromImage `
-DiskEncryptionKeyVaultId $KeyVault.ResourceId `
-DiskEncryptionKeyUrl $SecretUrl `
-KeyEncryptionKeyVaultId $KeyVault.ResourceId `
-KeyEncryptionKeyURL $KeyEncryptionKey.Id