使用與包含虛擬機器的 Azure 訂用帳戶相關聯的 Azure 帳戶。
若要啟用系統指派的受控識別,請將範本載入到編輯器、在 resources
區段中找出感興趣的 Microsoft.Compute/virtualMachines
資源,然後在與 "type": "Microsoft.Compute/virtualMachines"
屬性相同的層級上新增 "identity"
屬性。 使用下列語法:
"identity": {
"type": "SystemAssigned"
},
最終範本看起來如下範例
"resources": [
{
"apiVersion": "2021-11-01",
"type": "Microsoft.Compute/virtualMachines",
"name": "[parameters('vmName')]",
"location": "[parameters('location')]",
"identity": {
"type": "SystemAssigned",
},
//other resource provider properties...
}
]
將存取原則新增至您的 Azure Key Vault
為 CVM 啟用系統指派的受控識別之後,您必須提供其存取權給儲存機碼物件的 Azure Key Vault 資料平面。 為了確保只有機密虛擬機可以執行發行作業,我們只會授與所需的特定許可權。
[Bicep 1]
@description('Required. Specifies the object ID of a user, service principal or security group in the Azure Active Directory tenant for the vault. The object ID must be unique for the list of access policies. Get it by using Get-AzADUser or Get-AzADServicePrincipal cmdlets.')
param objectId string
resource keyVaultCvmAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = {
parent: keyVault
name: 'add'
properties: {
accessPolicies: [
{
objectId: objectId
tenantId: tenantId
permissions: {
keys: [
'release'
]
}
}
]
}
}
[ARM 範本 2]
{
"type": "Microsoft.KeyVault/vaults/accessPolicies",
"apiVersion": "2022-07-01",
"name": "[format('{0}/{1}', 'mykeyvault', 'add')]",
"properties": {
"accessPolicies": [
{
"objectId": "[parameters('objectId')]",
"tenantId": "[parameters('tenantId')]",
"permissions": {
"keys": [
"release"
]
}
}
]
},
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', 'mykeyvault')]"
]
}
準備發行原則
Key Vault 安全金鑰發行原則會在 Azure 原則之後模型化, 其文法略有不同。
其概念是當我們 以 JSON Web 令牌 (JWT) 的形式,將證明的平台報告傳遞至 Key Vault。 接著,會查看 JWT 並檢查證明的平台報告宣告是否符合原則中的宣告。
例如,假設只有當證明的平台報告具有如下的屬性時,我們才想要發行金鑰:
- Microsoft Azure 證明 (MAA) 服務端點 “https://sharedweu.weu.attest.azure.net";。
- 原則的
authority
值會與權杖中的 iss
(簽發者) 屬性進行比較。
- 此外,它也包含名為
x-ms-isolation-tee
的物件,其具有稱為 x-ms-attestation-type
的屬性,其會保留值 sevsnpvm
。
- MAA 即 Azure 服務已證明 CVM 正在 AMD SEV-SNP 正版處理器中執行。
- 此外,它也包含名為
x-ms-isolation-tee
的物件,其具有稱為 x-ms-compliance-status
的屬性,其會保留值 azure-compliant-cvm
。
- MAA 即 Azure 服務能夠證明 CVM 是符合規範的 Azure 機密虛擬機。
建立名為 assets
的新資料夾,並將下列 JSON 內容新增至名為 cvm-release-policy.json
的檔案:
{
"version": "1.0.0",
"anyOf": [
{
"authority": "https://sharedweu.weu.attest.azure.net",
"allOf": [
{
"claim": "x-ms-isolation-tee.x-ms-attestation-type",
"equals": "sevsnpvm"
},
{
"claim": "x-ms-isolation-tee.x-ms-compliance-status",
"equals": "azure-compliant-cvm"
}
]
}
]
}
發行原則是包括金鑰授權單位陣列的 anyOf
條件。 claim
條件是 JSON 物件,可識別宣告名稱、比對的條件,以及值。 AnyOf
和 AllOf
條件物件允許 OR
和 AND
的模型化。 目前,我們只能在 claim
上執行 equals
比較。 條件屬性會與 authority
屬性放在一起。
重要
環境判斷提示包含至少一個金鑰加密金鑰,以及一或多個與金鑰發行原則相符的目標環境相關宣告 (例如 TEE 類型、發行者、版本)。 金鑰加密金鑰是由用於金鑰匯出的目標執行環境所擁有及保護的公用 RSA 金鑰。 此金鑰必須出現在 TEE 金鑰宣告 (x-ms-runtime/keys) 中。 此宣告是代表 JSON Web 金鑰集的 JSON 物件。 在 JWKS 中,其中一個金鑰必須符合作為加密金鑰使用的需求,(key_use 為 "enc",或包含 "enc"的 key_ops)。 系統會選擇第一個合適的金鑰。
Key Vault 會從 「x-ms-runtime
」 物件的「keys
」陣列屬性中挑選第一個合適的金鑰,它會尋找具有 "key_use": ["enc"]
或 "key_ops": ["encrypt"]
的公用 RSA 金鑰。 證明平台報告的範例如下所示:
{
//...
"x-ms-runtime": {
"client-payload": {
"nonce": "MTIzNA=="
},
"keys": [
{
"e": "AQAB",
"key_ops": [
"encrypt"
],
"kid": "TpmEphemeralEncryptionKey",
"kty": "RSA",
"n": "9v2XQgAA6y18CxV8dSGnh..."
}
]
},
//...
}
在此範例中,我們在 $.x-ms-runtime.keys
路徑下只有一個索引鍵。 Key Vault 會使用 TpmEphemeralEncryptionKey
金鑰作為金鑰加密金鑰。
注意
請注意, $.x-ms-isolation-tee.x-ms-runtime.keys
下可能有金鑰, 不會 Key Vault 將使用的金鑰。
使用發行原則建立可匯出金鑰
我們會建立 Key Vault 存取原則,讓 Azure 機密虛擬機器執行 release
金鑰作業。 最後,我們必須在金鑰建立期間,將發行原則納入為 base64 編碼字串。 金鑰必須是由 HSM 支援的可匯出金鑰。
注意
HSM 支援的金鑰適用於 Azure Key Vault Premium 和 Azure Key Vault 受控 HSM。
[Bicep 2]
@description('The type of the key. For valid values, see JsonWebKeyType. Must be backed by HSM, for secure key release.')
@allowed([
'EC-HSM'
'RSA-HSM'
])
param keyType string = 'RSA-HSM'
@description('Not before date in seconds since 1970-01-01T00:00:00Z.')
param keyNotBefore int = -1
@description('Expiry date in seconds since 1970-01-01T00:00:00Z.')
param keyExpiration int = -1
@description('The elliptic curve name. For valid values, see JsonWebKeyCurveName.')
@allowed([
'P-256'
'P-256K'
'P-384'
'P-521'
])
param curveName string
@description('The key size in bits. For example: 2048, 3072, or 4096 for RSA.')
param keySize int = -1
resource exportableKey 'Microsoft.KeyVault/vaults/keys@2022-07-01' = {
parent: keyVault
name: 'mykey'
properties: {
kty: keyType
attributes: {
exportable: true
enabled: true
nbf: keyNotBefore == -1 ? null : keyNotBefore
exp: keyExpiration == -1 ? null : keyExpiration
}
curveName: curveName // applicable when using key type (kty) 'EC'
keySize: keySize == -1 ? null : keySize
keyOps: ['encrypt','decrypt'] // encrypt and decrypt only work with RSA keys, not EC
release_policy: {
contentType: 'application/json; charset=utf-8'
data: loadFileAsBase64('assets/cvm-release-policy.json')
}
}
}
[ARM 範本 2]
{
"type": "Microsoft.KeyVault/vaults/keys",
"apiVersion": "2022-07-01",
"name": "[format('{0}/{1}', 'mykeyvault', 'mykey')]",
"properties": {
"kty": "RSA-HSM",
"attributes": {
"exportable": true,
"enabled": true,
"nbf": "[if(equals(parameters('keyNotBefore'), -1), null(), parameters('keyNotBefore'))]",
"exp": "[if(equals(parameters('keyExpiration'), -1), null(), parameters('keyExpiration'))]"
},
"curveName": "[parameters('curveName')]",
"keySize": "[if(equals(parameters('keySize'), -1), null(), parameters('keySize'))]",
"keyOps": [
"encrypt",
"decrypt"
],
"release_policy": {
"contentType": "application/json; charset=utf-8",
"data": "[variables('cvmReleasePolicyBase64EncodedString')]"
}
},
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults', 'mykeyvault')]"
]
}
我們可以藉由瀏覽至 Azure 入口網站並選取金鑰,確認 Key Vault 已建立新的、HSM 支援的、金鑰,並包含我們的安全金鑰發行原則。 預期的金鑰將會標示為「可匯出」。
訪客證明用戶端
證明可協助我們 以密碼編譯方式評估某個專案在預定作業狀態中執行。 這是驗證者一方,評估潛在不受信任對等,證明者的信任度的程式。 使用遠端訪客證明,受信任的執行環境會提供一個平台,可讓您在其中執行整個操作系統。
重要
Microsoft 提供 C/C++ 程式庫,適用於 Windows 和 Linux ,可協助您進行開發工作。 程式庫可讓您輕鬆地從硬體取得 SEV-SNP 平台報告 ,並讓其由 Azure 證明服務的執行個體證明。 Azure 證明服務可以是 Microsoft (共用) 或您自己的私人執行個體所裝載的服務。
使用訪客證明程式庫的開放原始碼 Windows 和 Linux 用戶端二進位檔,可讓您輕鬆地使用 CVM 進行訪客證明程式。 用戶端二進位檔會以 JSON Web 權杖的形式傳回證明的平台報表,這是 Key Vault release
金鑰作業所需的專案。
注意
來自 Azure 證明服務的權杖在 8 小時內有效。
[Linux]
登入您的虛擬機器。
複製範例 Linux 應用程式。
安裝 build-essential
套件。 此套件會安裝編譯範例應用程式所需的一切。
sudo apt-get install build-essential
安裝 libcurl4-openssl-dev
和 libjsoncpp-dev
套件。
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libjsoncpp-dev
下載證明套件。
安裝證明套件。 確定將 <version>
取代為您下載的版本。
sudo dpkg -i azguestattestation1_<latest-version>_amd64.deb
若要執行範例用戶端,請在解壓縮的資料夾內瀏覽,然後執行下列命令:
sudo ./AttestationClient -a <attestation-url> -n <nonce-value> -o token
注意
如果未將 -o
指定為 token
,exe 會根據證明結果和 sevsnp
平台,列印二進位結果 true 或 false。
登入您的虛擬機器。
複製範例 Windows 應用程式。
在解壓縮的資料夾內瀏覽,然後執行 VC_redist.x64.exe
。 VC_redist 會在電腦上安裝 Microsoft C 和 C++ (MSVC) 執行階段程式庫。
若要執行範例用戶端,請在解壓縮的資料夾內瀏覽,然後執行下列命令:
sudo ./AttestationClient -a <attestation-url> -n <nonce-value> -o token
注意
如果未將 -o
指定為 token
,exe 會根據證明結果和 sevsnp
平台,列印二進位結果 true 或 false。
訪客證明結果
訪客證明客戶端的結果只是 base64 編碼字串。 這個編碼的字串值是帶標題、本文和簽章的已簽署 JSON Web 令牌 (JWT)。 您可以依 .
值和 base64 解碼結果來分割字串。
eyJhbGciO...
標題包含 jku
,也稱為 JWK Set URI 連結至一組 JSON 編碼公開金鑰。 其中一個對應至用來數位簽章 JWS 的金鑰。 kid
指出用來簽署 JWS 的金鑰。
{
"alg": "RS256",
"jku": "https://sharedweu.weu.attest.azure.net/certs",
"kid": "dRKh+hBcWUfQimSl3Iv6ZhStW3TSOt0ThwiTgUUqZAo=",
"typ": "JWT"
}
訪客證明回應的本文將會由 Azure Key Vault 驗證,作為針對金鑰發行原則進行測試的輸入。 如先前所述,Azure Key Vault 會使用「TpmEphemeralEncryptionKey
」作為金鑰加密金鑰。
{
"exp": 1671865218,
"iat": 1671836418,
"iss": "https://sharedweu.weu.attest.azure.net",
"jti": "ce395e5de9c638d384cd3bd06041e674edee820305596bba3029175af2018da0",
"nbf": 1671836418,
"secureboot": true,
"x-ms-attestation-type": "azurevm",
"x-ms-azurevm-attestation-protocol-ver": "2.0",
"x-ms-azurevm-attested-pcrs": [
0,
1,
2,
3,
4,
5,
6,
7
],
"x-ms-azurevm-bootdebug-enabled": false,
"x-ms-azurevm-dbvalidated": true,
"x-ms-azurevm-dbxvalidated": true,
"x-ms-azurevm-debuggersdisabled": true,
"x-ms-azurevm-default-securebootkeysvalidated": true,
"x-ms-azurevm-elam-enabled": false,
"x-ms-azurevm-flightsigning-enabled": false,
"x-ms-azurevm-hvci-policy": 0,
"x-ms-azurevm-hypervisordebug-enabled": false,
"x-ms-azurevm-is-windows": false,
"x-ms-azurevm-kerneldebug-enabled": false,
"x-ms-azurevm-osbuild": "NotApplication",
"x-ms-azurevm-osdistro": "Ubuntu",
"x-ms-azurevm-ostype": "Linux",
"x-ms-azurevm-osversion-major": 20,
"x-ms-azurevm-osversion-minor": 4,
"x-ms-azurevm-signingdisabled": true,
"x-ms-azurevm-testsigning-enabled": false,
"x-ms-azurevm-vmid": "6506B531-1634-431E-99D2-42B7D3414AD0",
"x-ms-isolation-tee": {
"x-ms-attestation-type": "sevsnpvm",
"x-ms-compliance-status": "azure-compliant-cvm",
"x-ms-runtime": {
"keys": [
{
"e": "AQAB",
"key_ops": [
"encrypt"
],
"kid": "HCLAkPub",
"kty": "RSA",
"n": "tXkRLAABQ7vgX96..1OQ"
}
],
"vm-configuration": {
"console-enabled": true,
"current-time": 1671835548,
"secure-boot": true,
"tpm-enabled": true,
"vmUniqueId": "6506B531-1634-431E-99D2-42B7D3414AD0"
}
},
"x-ms-sevsnpvm-authorkeydigest": "0000000000000..00",
"x-ms-sevsnpvm-bootloader-svn": 3,
"x-ms-sevsnpvm-familyId": "01000000000000000000000000000000",
"x-ms-sevsnpvm-guestsvn": 2,
"x-ms-sevsnpvm-hostdata": "0000000000000000000000000000000000000000000000000000000000000000",
"x-ms-sevsnpvm-idkeydigest": "57486a44..96",
"x-ms-sevsnpvm-imageId": "02000000000000000000000000000000",
"x-ms-sevsnpvm-is-debuggable": false,
"x-ms-sevsnpvm-launchmeasurement": "ad6de16..23",
"x-ms-sevsnpvm-microcode-svn": 115,
"x-ms-sevsnpvm-migration-allowed": false,
"x-ms-sevsnpvm-reportdata": "c6500..0000000",
"x-ms-sevsnpvm-reportid": "cf5ea742f08cb45240e8ad4..7eb7c6c86da6493",
"x-ms-sevsnpvm-smt-allowed": true,
"x-ms-sevsnpvm-snpfw-svn": 8,
"x-ms-sevsnpvm-tee-svn": 0,
"x-ms-sevsnpvm-vmpl": 0
},
"x-ms-policy-hash": "wm9mHlvTU82e8UqoOy1..RSNkfe99-69IYDq9eWs",
"x-ms-runtime": {
"client-payload": {
"nonce": ""
},
"keys": [
{
"e": "AQAB",
"key_ops": [
"encrypt"
],
"kid": "TpmEphemeralEncryptionKey", // key-encryption key candidate!
"kty": "RSA",
"n": "kVTLSwAAQpg..Q"
}
]
},
"x-ms-ver": "1.0"
}
Microsoft Azure 證明服務的文件有一份廣泛的清單,其中包含所有這些 SEV-SNP 相關宣告的描述。
我們可以使用任何指令碼或程序設計語言,以使用 AttestationClient 二進位檔接收證明的平台報表。 由於我們在上一個步驟中部署的虛擬機已啟用受控識別,因此我們應該從執行個體中繼資料服務取得適用於 Key Vault 的 Azure AD 權杖(IMDS)。
藉由將證明的平台報告設定為本文承載,以及我們授權標提中的 Microsoft Entra 權杖,您就擁有執行金鑰 release
作業所需的一切。
#Requires -Version 7
#Requires -RunAsAdministrator
#Requires -PSEdition Core
<#
.SYNOPSIS
Perform Secure Key Release operation in Azure Key Vault, provided this script is running inside an Azure Confidential Virtual Machine.
.DESCRIPTION
Perform Secure Key Release operation in Azure Key Vault, provided this script is running inside an Azure Confidential Virtual Machine.
The release key operation is applicable to all key types. The target key must be marked exportable. This operation requires the keys/release permission.
.PARAMETER -AttestationTenant
Provide the attestation instance base URI, for example https://mytenant.attest.azure.net.
.PARAMETER -VaultBaseUrl
Provide the vault name, for example https://myvault.vault.azure.net.
.PARAMETER -KeyName
Provide the name of the key to get.
.PARAMETER -KeyName
Provide the version parameter to retrieve a specific version of a key.
.INPUTS
None.
.OUTPUTS
System.Management.Automation.PSObject
.EXAMPLE
PS C:\> .\Invoke-SecureKeyRelease.ps1 -AttestationTenant "https://sharedweu.weu.attest.azure.net" -VaultBaseUrl "https://mykeyvault.vault.azure.net/" -KeyName "mykey" -KeyVersion "e473cd4c66224d16870bbe2eb4c58078"
#>
param (
[Parameter(Mandatory = $true)]
[string]
$AttestationTenant,
[Parameter(Mandatory = $true)]
[string]
$VaultBaseUrl,
[Parameter(Mandatory = $true)]
[string]
$KeyName,
[Parameter(Mandatory = $false)]
[string]
$KeyVersion
)
# Check if AttestationClient* exists.
$fileExists = Test-Path -Path "AttestationClient*"
if (!$fileExists) {
throw "AttestationClient binary not found. Please download it from 'https://github.com/Azure/confidential-computing-cvm-guest-attestation'."
}
$cmd = $null
if ($isLinux) {
$cmd = "sudo ./AttestationClient -a $attestationTenant -o token"
}
elseif ($isWindows) {
$cmd = "./AttestationClientApp.exe -a $attestationTenant -o token"
}
$attestedPlatformReportJwt = Invoke-Expression -Command $cmd
if (!$attestedPlatformReportJwt.StartsWith("eyJ")) {
throw "AttestationClient failed to get an attested platform report."
}
## Get access token from IMDS for Key Vault
$imdsUrl = 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net'
$kvTokenResponse = Invoke-WebRequest -Uri $imdsUrl -Headers @{Metadata = "true" }
if ($kvTokenResponse.StatusCode -ne 200) {
throw "Unable to get access token. Ensure Azure Managed Identity is enabled."
}
$kvAccessToken = ($kvTokenResponse.Content | ConvertFrom-Json).access_token
# Perform release key operation
if ([string]::IsNullOrEmpty($keyVersion)) {
$kvReleaseKeyUrl = "{0}/keys/{1}/release?api-version=7.3" -f $vaultBaseUrl, $keyName
}
else {
$kvReleaseKeyUrl = "{0}/keys/{1}/{2}/release?api-version=7.3" -f $vaultBaseUrl, $keyName, $keyVersion
}
$kvReleaseKeyHeaders = @{
Authorization = "Bearer $kvAccessToken"
'Content-Type' = 'application/json'
}
$kvReleaseKeyBody = @{
target = $attestedPlatformReportJwt
}
$kvReleaseKeyResponse = Invoke-WebRequest -Method POST -Uri $kvReleaseKeyUrl -Headers $kvReleaseKeyHeaders -Body ($kvReleaseKeyBody | ConvertTo-Json)
if ($kvReleaseKeyResponse.StatusCode -ne 200) {
Write-Error -Message "Unable to perform release key operation."
Write-Error -Message $kvReleaseKeyResponse.Content
}
else {
$kvReleaseKeyResponse.Content | ConvertFrom-Json
}
金鑰發行回應
安全金鑰發行作業只會在其 JSON 承載內傳回單一屬性。 不過,內容也經過 base64 編碼。
{
"value": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg4RUFDM.."
}
在這裡,我們有另一個標題,雖然這個標頭具有 X.509 憑證鏈結 作為屬性。
{
"alg": "RS256",
"kid": "88EAC2DB6BE4E051B0E05AEAF6CB79E675296121",
"x5t": "iOrC22vk4FGw4Frq9st55nUpYSE",
"typ": "JWT",
"x5t#S256": "BO7jbeU3BG0FEjetF8rSisRbkMfcdy0olhcnmYEwApA",
"x5c": [
"MIIIfDCCBmSgA..XQ==",
"MII..8ZZ8m",
"MII..lMrY="
]
}
您可以從 PowerShell 中的 「x5c
」 陣列讀取,這可協助您確認這是有效的憑證。 範例如下:
$certBase64 = "MIIIfDCCBmSgA..XQ=="
$cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]([System.Convert]::FromBase64String($certBase64))
$cert | Format-List *
# NotAfter : 9/18/2023 6:14:06 PM
# NotBefore : 9/23/2022 6:14:06 PM
# ...
# Issuer : CN=Microsoft Azure TLS Issuing CA 06, O=Microsoft Corporation, C=US
# Subject : CN=vault.azure.net, O=Microsoft Corporation, L=Redmond, S=WA, C=US
回應的 JWT 權杖主體看起來非常類似您在叫用 get
金鑰作業時得到的回應。 不過,release
作業包括 key_hsm
屬性等。
{
"request": {
"api-version": "7.3",
"enc": "CKM_RSA_AES_KEY_WRAP",
"kid": "https://mykeyvault.vault.azure.net/keys/mykey"
},
"response": {
"key": {
"key": {
"kid": "https://mykeyvault.vault.azure.net/keys/mykey/e473cd4c66224d16870bbe2eb4c58078",
"kty": "RSA-HSM",
"key_ops": [
"encrypt",
"decrypt"
],
"n": "nwFQ8p..20M",
"e": "AQAB",
"key_hsm": "eyJzY2hlbW..GIifQ"
},
"attributes": {
"enabled": true,
"nbf": 1671577355,
"exp": 1703113355,
"created": 1671577377,
"updated": 1671827011,
"recoveryLevel": "Recoverable+Purgeable",
"recoverableDays": 90,
"exportable": true
},
"tags": {},
"release_policy": {
"data": "eyJ2ZXJzaW9uIjoiMS4wLjAiLCJhbnlPZiI6W3siYXV0aG9yaXR5IjoiaHR0cHM6Ly9zaGFyZWR3ZXUud2V1LmF0dGVzdC5henVyZS5uZXQiLCJhbGxPZiI6W3siY2xhaW0iOiJ4LW1zLWlzb2xhdGlvbi10ZWUueC1tcy1hdHRlc3RhdGlvbi10eXBlIiwiZXF1YWxzIjoic2V2c25wdm0ifSx7ImNsYWltIjoieC1tcy1pc29sYXRpb24tdGVlLngtbXMtY29tcGxpYW5jZS1zdGF0dXMiLCJlcXVhbHMiOiJhenVyZS1jb21wbGlhbnQtY3ZtIn1dfV19",
"immutable": false
}
}
}
}
如果您的 base64 譯碼 $.response.key.release_policy.data
下的值,您會取得我們在先前步驟中定義的Key Vault 金鑰發行原則 JSON 表示法。
key_hsm
屬性 base64 解碼值看起來像這樣:
{
"schema_version": "1.0",
"header": {
"kid": "TpmEphemeralEncryptionKey", // (key identifier of KEK)
"alg": "dir", // Direct mode, i.e. the referenced 'kid' is used to directly protect the ciphertext
"enc": "CKM_RSA_AES_KEY_WRAP"
},
"ciphertext": "Rftxvr..lb"
}
下一步
SKR 原則範例瞭解如何使用適用於雲端的 Microsoft Defender 與已安裝訪客證明的機密 VM 整合,深入瞭解訪客證明功能,瞭解 Azure 機密 VM