建立會部署使用客戶自控金鑰進行加密之儲存體帳戶的 Azure 受控應用程式
本文描述如何建立會部署使用客戶自控金鑰進行加密之儲存體帳戶的 Azure 受控應用程式。 儲存體帳戶、Cosmos DB 與適用於 Postgres 的 Azure 資料庫支援使用客戶自控金鑰或 Microsoft 管理的金鑰對待用資料進行加密。 您可以使用自己的加密金鑰來保護儲存體帳戶中的資料。 當您指定客戶自控金鑰時,該金鑰會用來保護及控制加密資料所需金鑰的存取權。 客戶自控金鑰可提供更大的彈性來管理存取控制。
必要條件
- 具有作用中訂用帳戶,以及對 Microsoft Entra 資源 (例如使用者、群組或服務主體) 具有權限的 Azure 帳戶。 如果您沒有帳戶,請在開始之前建立免費帳戶。
- Visual Studio Code 搭配最新的 Azure Resource Manager 工具延伸模組。 針對 Bicep 檔案,請安裝適用於 Visual Studio Code 的 Bicep 延伸模組 (英文)。
- 安裝最新版的 Azure PowerShell 或 Azure CLI。
- 熟悉如何建立 (部分機器翻譯) 和部署服務類別目錄定義。
受控識別
設定由受控應用程式作為受控資源群組內的資源部署之儲存體帳戶的客戶自控金鑰,需要使用者指派的受控識別。 此使用者指派的受控識別可以用來將其他現有資源的存取權授與受控應用程式。 若要了解如何使用使用者指派的受控識別來設定您的受控應用程式,請移至具有受控識別的 Azure 受控應用程式。
您的應用程式可以授與兩種類型的身分識別:
- 會將系統指派的受控識別指派給您的應用程式,且在刪除您應用程式的情況下,也會將該身分識別刪除。 應用程式只能有一個系統指派的受控識別。
- 使用者指派的受控識別是一個獨立 Azure 資源,可指派給您的應用程式。 應用程式可以有多個使用者指派的受控識別。
若要在您受控應用程式使用現有金鑰保存庫中的客戶金鑰加密的受控資源群組中部署儲存體帳戶,則需要進行更多設定。 搭配您受控應用程式設定的受控識別需要對金鑰保存庫具備存取權之受控識別的內建 Azure 角色型存取控制「受控識別操作員」角色。 如需詳細資料,請移至受控識別操作員角色 (部分機器翻譯)。
建立具清除保護的金鑰保存庫
- 登入 Azure 入口網站。
- 從 Azure 入口網站功能表或從首頁,選取 [建立資源]。
- 在 [搜尋] 方塊中輸入 Key Vault。
- 從結果清單中,選取 [Key Vault]。
- 在 [Key Vault] 區段上,選取 [建立]。
- 在 [建立金鑰保存庫] 區段上提供下列資訊:
- 訂用帳戶︰選取您的訂用帳戶。
- 資源群組:選取 [新建],然後輸入名稱,例如 demo-cmek-rg。
- 名稱:需要唯一名稱,例如 demo-keyvault-cmek。
- 區域:選取位置,例如 [美國東部]。
- 定價層:從下拉式清單中選取 [標準]。
- 清除保護:選取 [啟用清除保護]。
- 選取 [下一步] 並移至 [存取原則] 索引標籤。
- 存取設定:選取 [Azure 角色型存取控制]。
- 接受所有其他選項的預設值。
- 選取 [檢閱 + 建立]。
- 確認設定是正確的,然後選取 [建立]。
部署成功之後,選取 [前往資源]。 在 [概觀] 索引標籤上,記下下列屬性:
- 保存庫名稱:在此範例中,保存庫名稱為 demo-keyvault-cmek。 您會在其他步驟中使用此名稱。
- 保存庫 URI:在此範例中,保存庫 URI 為
https://demo-keyvault-cmek.vault.azure.net/
。
建立使用者指派的受控識別
若要建立使用者指派的受控識別,您的帳戶需要受控識別「參與者」角色指派。
- 在搜尋方塊中,輸入「受控識別」。
- 在 [服務] 下,選取 [受控識別]。
- 選取 [建立] 並在 [基本] 索引標籤上,輸入下列值:
- 訂用帳戶︰選取您的訂用帳戶。
- 資源群組:選取您在先前步驟中建立的資源群組 [demo-cmek-rg]。
- 區域:選取區域,例如 [美國東部]。
- 名稱:輸入您的使用者指派的受控識別名稱,例如 demokeyvaultmi。
- 選取 [檢閱 + 建立]。
- 在顯示 [驗證通過] 之後,請選取 [建立]。
部署成功之後,請選取 [前往資源]。
建立角色指派
您需要為金鑰保存庫建立兩個角色指派。 如需詳細資料,請參閱使用 Azure 入口網站指派 Azure 角色 (部分機器翻譯)。
為受控識別授與金鑰保存庫的金鑰權限
為金鑰保存庫受控識別 demokeyvaultmi 建立角色指派以對金鑰進行包裝和解除包裝。
- 移至您的金鑰保存庫 demo-cmek-keyvault。
- 選取 [存取控制 (IAM)]。
- 選取 [新增>][新增角色指派]。
- 指派下列角色:
- 角色:Key Vault 密碼編譯服務加密使用者
- 存取權指派對象為:受控識別
- 成員:demokeyvaultmi
- 選取 [檢閱 + 指派] 以檢視您的設定。
- 選取 [檢閱 + 指派] 以建立角色指派。
為您的帳戶建立角色指派
建立另一個角色指派,使您的帳戶可以在您的金鑰保存庫中建立新的金鑰。
- 指派下列角色:
- 角色:Key Vault 密碼編譯長
- 存取權指派對象為:使用者、群組或服務主體
- 成員:您的 Microsoft Entra 帳戶
- 選取 [檢閱 + 指派] 以檢視您的設定。
- 選取 [檢閱 + 指派] 以建立角色指派。
您可以在 [存取控制 (IAM)]>[角色指派] 中確認金鑰保存庫的角色指派。
建立金鑰
您必須建立金鑰保存庫用來將儲存體帳戶加密的金鑰。
- 移至您的金鑰保存庫 demo-cmek-keyvault。
- 選取 [金鑰]。
- 選取產生/匯入。
- 在 [建立金鑰] 頁面上,選取下列值:
- 選項:產生
- 名稱:demo-cmek-key
- 接受其他選項的預設值。
- 選取 建立。
記下金鑰的名稱。 當您部署受控應用程式時,將會使用該名稱。
為受控應用程式建立使用者指派的受控識別
建立使用者指派的受控識別以作為受控應用程式的受控識別使用。
- 在搜尋方塊中,輸入受控識別。
- 在 [服務] 下,選取 [受控識別]。
- 選取 建立。
- 訂用帳戶︰選取您的訂用帳戶。
- 資源群組:選取資源群組 [demo-cmek-rg]。
- 區域:選取區域,例如 [美國東部]。
- 名稱:輸入您的使用者指派的受控識別名稱,例如 demomanagedappmi。
- 選取 [檢閱 + 建立]。
- 在顯示 [驗證通過] 之後,請選取 [建立]。
部署成功之後,請選取 [前往資源]。
將角色權限指派給受控識別
將 [受控識別操作員] 角色以名為 demokeyvaultmi 的使用者指派的受控識別的範圍指派給受控識別。
- 移至名為 demokeyvaultmi 的使用者指派的受控識別。
- 選取 [存取控制 (IAM)]。
- 選取 [新增 > 角色指派 ] 以開啟 [新增角色指派] 頁面。
- 指派下列角色。
- 角色:受控識別操作員
- 存取權指派對象為:受控識別
- 成員:demomanagedappmi
- 選取 [檢閱 + 指派] 以檢視您的設定。
- 選取 [檢閱 + 指派] 以建立角色指派。
您可以在 [存取控制 (IAM)]>[角色指派] 中確認 demokeyvaultmi 的角色指派。
範例受控應用程式範本
建立會部署至受控資源群組中的儲存體帳戶,並使用金鑰保存庫中預先存在的金鑰對儲存體帳戶中的資料進行加密的受控應用程式。
若要將受控應用程式發佈至您的服務類別目錄,請執行下列工作:
- 從本文中的範例建立 creatUIDefinition.json 檔案。 部署受控應用程式時,範本會定義入口網站的使用者介面元素。
- 透過將本文中的 Bicep 檔案轉換成 JSON,建立名為 mainTemplate.json 的 Azure Resource Manager 範本。 該範本會定義要與受控應用程式一起部署的資源。
- 建立包含下列所需 JSON 檔案的 .zip 套件:createUiDefinition.json 和 mainTemplate.json。
- 發佈受控應用程式定義,使其可在您的服務類別目錄中使用。 如需詳細資訊,請移至快速入門:建立和發佈 Azure 受控應用程式定義 (部分機器翻譯)。
建立範本 createUiDefinition.json
下列範本會為受控應用程式建立使用者指派的受控識別。 在此範例中,我們會停用系統指派的受控識別,因為我們需要跨越金鑰保存庫的受控識別,預先使用「受控識別操作員」的權限設定使用者指派的受控識別。
- 在 Visual Studio Code 中建立名為 creatUIDefinition.json 的新檔案。
- 複製下列程式碼並貼到該檔案中。
- 儲存檔案。
{
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
"handler": "Microsoft.Azure.CreateUIDef",
"version": "0.1.2-preview",
"parameters": {
"basics": [],
"steps": [
{
"name": "managedApplicationSetting",
"label": "Application Settings",
"subLabel": {
"preValidation": "Configure your application settings and Managed Identity for the application",
"postValidation": "Done"
},
"bladeTitle": "Application Settings - Config",
"elements": [
{
"name": "appIdentity",
"type": "Microsoft.ManagedIdentity.IdentitySelector",
"label": "Managed Identity Configuration for the Application (Needs Managed Identity Operator permissions over KV Managed Identity).",
"toolTip": {
"systemAssignedIdentity": "Enable system assigned identity to grant the managed application access to additional existing resources.",
"userAssignedIdentity": "Add user assigned identities to grant the managed application access to additional existing resources."
},
"defaultValue": {
"systemAssignedIdentity": "Off"
},
"options": {
"hideSystemAssignedIdentity": true,
"hideUserAssignedIdentity": false,
"readOnlySystemAssignedIdentity": true
},
"visible": true
}
]
},
{
"name": "configuration",
"type": "Microsoft.Common.Section",
"label": "Configuration",
"elements": [
{
"name": "cmek",
"type": "Microsoft.Common.Section",
"label": "Customer Managed Encryption Key (CMEK)",
"elements": [
{
"name": "cmekEnable",
"type": "Microsoft.Common.CheckBox",
"label": "Enable CMEK",
"toolTip": "Enable to provide a CMEK",
"constraints": {
"required": false
}
},
{
"name": "cmekKeyVaultUrl",
"type": "Microsoft.Common.TextBox",
"label": "Key Vault URL",
"toolTip": "Specify the CMEK Key Vault URL",
"defaultValue": "",
"constraints": {
"required": "[steps('configuration').cmek.cmekEnable]",
"regex": ".*",
"validationMessage": "The value must not be empty."
},
"visible": "[steps('configuration').cmek.cmekEnable]"
},
{
"name": "cmekKeyName",
"type": "Microsoft.Common.TextBox",
"label": "Key Name",
"toolTip": "Specify the key name from your key vault.",
"defaultValue": "",
"constraints": {
"required": "[steps('configuration').cmek.cmekEnable]",
"regex": ".*",
"validationMessage": "The value must not be empty."
},
"visible": "[steps('configuration').cmek.cmekEnable]"
},
{
"name": "cmekKeyIdentity",
"type": "Microsoft.ManagedIdentity.IdentitySelector",
"label": "Managed Identity Configuration for Key Vault Access",
"toolTip": {
"systemAssignedIdentity": "Enable system assigned identity to grant the managed application access to additional existing resources.",
"userAssignedIdentity": "Add user assigned identities to grant the managed application access to additional existing resources."
},
"defaultValue": {
"systemAssignedIdentity": "Off"
},
"options": {
"hideSystemAssignedIdentity": true,
"hideUserAssignedIdentity": false,
"readOnlySystemAssignedIdentity": true
},
"visible": "[steps('configuration').cmek.cmekEnable]"
}
],
"visible": true
}
]
}
],
"outputs": {
"location": "[location()]",
"managedIdentity": "[steps('managedApplicationSetting').appIdentity]",
"cmekConfig": {
"kvUrl": "[if(empty(steps('configuration').cmek.cmekKeyVaultUrl), '', steps('configuration').cmek.cmekKeyVaultUrl)]",
"keyName": "[if(empty(steps('configuration').cmek.cmekKeyName), '', steps('configuration').cmek.cmekKeyName)]",
"identityId": "[if(empty(steps('configuration').cmek.cmekKeyIdentity), '', steps('configuration').cmek.cmekKeyIdentity)]"
}
}
}
}
建立範本 mainTemplate.json
下列 Bicep 檔案是您 mainTemplate.json 的原始程式碼。 該範本使用 createUiDefinition.json 檔案中定義的使用者指派的受控識別。
- 在 Visual Studio Code 中建立名為 mainTemplate.bicep 的新檔案。
- 複製下列程式碼並貼到該檔案中。
- 儲存檔案。
param cmekConfig object = {
kvUrl: ''
keyName: ''
identityId: {}
}
@description('Specify the Azure region to place the application definition.')
param location string = resourceGroup().location
/////////////////////////////////
// Common Resources Configuration
/////////////////////////////////
var commonproperties = {
name: 'cmekdemo'
displayName: 'Common Resources'
storage: {
sku: 'Standard_LRS'
kind: 'StorageV2'
accessTier: 'Hot'
minimumTlsVersion: 'TLS1_2'
}
}
var identity = items(cmekConfig.identityId.userAssignedIdentities)[0].key
resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = {
name: '${commonproperties.name}${uniqueString(resourceGroup().id)}'
location: location
sku: {
name: commonproperties.storage.sku
}
kind: commonproperties.storage.kind
identity: cmekConfig.identityId
properties: {
accessTier: commonproperties.storage.accessTier
minimumTlsVersion: commonproperties.storage.minimumTlsVersion
encryption: {
identity: {
userAssignedIdentity: identity
}
services: {
blob: {
enabled: true
}
table: {
enabled: true
}
file: {
enabled: true
}
}
keySource: 'Microsoft.Keyvault'
keyvaultproperties: {
keyname: '${cmekConfig.keyName}'
keyvaulturi: '${cmekConfig.kvUrl}'
}
}
}
}
使用 PowerShell 或 Azure CLI 來建置 mainTemplate.json 檔案。 移至儲存 Bicep 檔案的目錄並執行 build
命令。
bicep build mainTemplate.bicep
將 Bicep 檔案轉換成 JSON 之後,您的 mainTemplate.json 檔案應該符合下列範例。 在 version
和 templateHash
的 metadata
屬性中,您可能有不同的值。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.16.2.56959",
"templateHash": "1234567891234567890"
}
},
"parameters": {
"cmekConfig": {
"type": "object",
"defaultValue": {
"kvUrl": "",
"keyName": "",
"identityId": {}
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Specify the Azure region to place the application definition."
}
}
},
"variables": {
"commonproperties": {
"name": "cmekdemo",
"displayName": "Common Resources",
"storage": {
"sku": "Standard_LRS",
"kind": "StorageV2",
"accessTier": "Hot",
"minimumTlsVersion": "TLS1_2"
}
},
"identity": "[items(parameters('cmekConfig').identityId.userAssignedIdentities)[0].key]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2022-05-01",
"name": "[format('{0}{1}', variables('commonproperties').name, uniqueString(resourceGroup().id))]",
"location": "[parameters('location')]",
"sku": {
"name": "[variables('commonproperties').storage.sku]"
},
"kind": "[variables('commonproperties').storage.kind]",
"identity": "[parameters('cmekConfig').identityId]",
"properties": {
"accessTier": "[variables('commonproperties').storage.accessTier]",
"minimumTlsVersion": "[variables('commonproperties').storage.minimumTlsVersion]",
"encryption": {
"identity": {
"userAssignedIdentity": "[variables('identity')]"
},
"services": {
"blob": {
"enabled": true
},
"table": {
"enabled": true
},
"file": {
"enabled": true
}
},
"keySource": "Microsoft.Keyvault",
"keyvaultproperties": {
"keyname": "[format('{0}', parameters('cmekConfig').keyName)]",
"keyvaulturi": "[format('{0}', parameters('cmekConfig').kvUrl)]"
}
}
}
}
]
}
部署受控應用程式
建立服務類別目錄定義之後,您便可以部署受控應用程式。 如需詳細資訊,請移至快速入門:部署服務類別目錄受控應用程式。
在部署期間,您會使用您的使用者指派的受控識別、金鑰保存庫名稱、金鑰保存庫 URL、金鑰保存庫的金鑰名稱。 createUiDefinition.json 檔案會建立使用介面。
例如,在入口網站部署中,於 [應用程式設定] 索引標籤上,您會新增 demomanagedappmi。
在 [設定] 索引標籤上,您會啟用客戶自控金鑰並為金鑰保存庫新增使用者指派的受控識別,demokeyvaultmi。 您也會指定金鑰保存庫的 URL 和您建立之金鑰保存庫的金鑰名稱。
檢查部署
在部署完成之後,您可以驗證受控應用程式的身分識別指派。 使用者指派的受控識別 demomanagedappmi 會指派給受控應用程式。
- 移至您部署受控應用程式的資源群組。
- 在 [設定]>[身分識別] 下,選取 [使用者指派 (預覽)]。
您也可以確認受控應用程式所部署的儲存體帳戶。 [加密] 索引標籤顯示金鑰 demo-cmek-key,以及使用者指派的受控識別的資源識別碼。
- 移至受控應用程式的儲存體帳戶部署所在的受控資源群組。
- 在 [安全性 + 網路] 下,選取 [加密]。
下一步
- 如需有關儲存體加密的詳細資訊,請移至為 Azure 儲存體加密的客戶自控金鑰。
- 如需具備存取金鑰保存庫中金鑰之權限的使用者指派的受控識別的詳細資訊,請移至在相同租用戶中為現有儲存體帳戶設定客戶自控金鑰。