Azure 磁碟加密範例指令碼
適用於:✔️ Windows VM
本文提供了對於準備預先加密 VHD 和其他工作的範例指令碼。
注意
除非另有說明,所有指令碼參考的都是 ADE 的最新且非 AAD 的版本。
Azure 磁碟加密的範例 PowerShell 指令碼
列出訂用帳戶中的所有已加密 VM
您可以使用 此 PowerShell 指令碼,訂閱中的所有資源群組中找到所有 ADE 加密的 VM 和延伸模組版本。
或者,這些 Cmdlet 也會顯示所有 ADE 加密的 VM (但不會顯示延伸模組版本):
$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 執行個體
您可以使用此 PowerShell 指令碼,在訂用帳戶中的所有資源群組中找到所有 ADE 加密的虛擬機器擴展集執行個體和延伸模組版本。
列出所有用來加密金鑰保存庫中 VM 的磁碟加密祕密
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 | KeyVault 所屬資源群組的名稱。 如果不存在此名稱的應用程式,將會以此名稱建立新的資源群組。 | True |
$keyVaultName | 要用來放置加密金鑰的金鑰保存庫名稱。 如果不存在此名稱的應用程式,將會以此名稱建立新的保存庫。 | True |
$location | 金鑰保存庫的位置。 請確定金鑰保存庫和要加密的 VM 位於相同位置。 使用 Get-AzLocation 取得位置清單。 |
True |
$subscriptionId | 要使用的 Azure 訂用帳戶識別碼。 您可以使用 Get-AzSubscription 取得您的訂用帳戶識別碼。 |
True |
$aadAppName | 會用來將祕密寫入到 KeyVault 的 Microsoft Entra 應用程式名稱。 如果不存在此名稱的應用程式,將會以此名稱建立新的應用程式。 如果此應用程式已經存在,請將 aadClientSecret 參數傳遞至指令碼。 | False |
$aadClientSecret | 稍早建立的 Microsoft Entra 應用程式用戶端密碼。 | False |
$keyEncryptionKeyName | 金鑰保存庫中選用金鑰加密金鑰的名稱。 如果不存在此名稱的應用程式,將會以此名稱建立新的金鑰。 | False |
Resource Manager 範本
在沒有 Microsoft Entra 應用程式的情況下加密或解密 VM
使用 Microsoft Entra 應用程式加密或解密 VM (舊版)
- 在現有或執行中的 Windows VM 上啟用磁碟加密
- 在執行中 Windows VM 上停用加密
- 從預先加密的 VHD/儲存體 Blob 建立新加密的受控磁碟
- 建立已加密的新受控磁碟,新的受控磁碟具備預先加密的 VHD 以及對應的加密設定
準備已預先加密的 Windows VHD
下列各節是準備預先加密的 Windows VHD 以在 Azure IaaS 中部署為加密的 VHD 的必要項目。 使用該資訊以在 Azure Site Recovery 或 Azure 上準備並啟動全新的 Windows VM (VHD)。 如需有關如何準備和上傳 VHD 的詳細資訊,請參閱上傳一般化 VHD 並使用它在 Azure 中建立新的 VM。
更新群組原則以對作業系統保護允許非 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
準備用於 BitLocker 的 OS 磁碟區
若要壓縮作業系統磁碟分割並為 BitLocker 準備電腦,請視需要執行 bdehdcfg:
bdehdcfg -target c: shrink -quiet
使用 BitLocker 保護作業系統磁碟區
使用 manage-bde
命令,以使用外部的金鑰保護裝置在開機磁碟區上啟用加密。 也將外部金鑰 (.bek 檔案) 放置於外部磁碟機或磁碟區。 下次重新開機後,會在系統/開機磁碟區上啟用加密。
manage-bde -on %systemdrive% -sk [ExternalDriveOrVolume]
reboot
注意
使用不同的資料/資源 VHD 來準備 VM,才能使用 BitLocker 取得外部金鑰。
上傳加密的 VHD 至 Azure 儲存體帳戶
在啟用 BitLocker 加密之後,需要將本機加密的 VHD 上傳至儲存體帳戶。
Add-AzVhd [-Destination] <Uri> [-LocalFilePath] <FileInfo> [[-NumberOfUploaderThreads] <Int32> ] [[-BaseImageUriToPatch] <Uri> ] [[-OverWrite]] [ <CommonParameters>]
將已預先加密 VM 的祕密上傳至金鑰保存庫
先前取得的磁碟加密密碼必須上傳,做為金鑰保存庫中的密碼。 若要這樣做,您必須將設定的秘密權限和 wrapkey 權限授與將上傳秘密的帳戶。
# 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 using 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 磁碟。
連接 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