針對 Azure 自動化帳戶使用使用者指派的受控識別

本文說明如何為 Azure 自動化帳戶新增使用者指派的受控識別,以及如何將其用來存取其他資源。 如需受控識別如何搭配 Azure 自動化使用的詳細資訊,請參閱受控識別

注意

當已為自動化帳戶建立受控識別 (系統或使用者指派) 時,無法在混合式 Runbook 背景工作角色上使用使用者指派的受控識別。 如果受控識別尚未指派給自動化帳戶,則可以在具有指派受控識別的 Azure VM 的混合式 Runbook 背景工作角色上使用 VM 系統或使用者指派的受控識別。

如果您沒有 Azure 訂用帳戶,請在開始前建立免費帳戶

必要條件

  • Azure 自動化帳戶。 如需相關指示,請參閱建立 Azure 自動化帳戶

  • 使用者指派的受控識別,以及 Runbook 使用該身分識別管理的目標 Azure 資源,可以位於不同的 Azure 訂用帳戶中。

  • 最新版 Azure 帳戶模組。 目前這是 2.2.8。 (如需關於此版本的詳細資訊,請參閱 Az.Accounts)

  • 您想要從自動化 Runbook 存取的 Azure 資源。 此資源必須針對使用者指派的受控識別定義角色,以協助自動化 Runbook 驗證資源的存取權。 若要新增角色,您必須是對應 Microsoft Entra 租用戶中資源的擁有者。

  • 若要指派 Azure 角色,您必須擁有 Microsoft.Authorization/roleAssignments/write 權限,例如使用者存取系統管理員擁有者

新增 Azure 自動化帳戶中使用者指派的受控識別

您可以使用 Azure 入口網站、PowerShell、Azure REST API 或 ARM 範本,為 Azure 自動化帳戶新增使用者指派的受控識別。 如需涉及 PowerShell 的範例,請先使用 Connect-AzAccount Cmdlet 以互動方式登入 Azure,並遵循指示。

# Sign in to your Azure subscription
$sub = Get-AzSubscription -ErrorAction SilentlyContinue
if(-not($sub))
{
    Connect-AzAccount
}

# If you have multiple subscriptions, set the one to use
# Select-AzSubscription -SubscriptionId "<SUBSCRIPTIONID>"

然後初始化將在整個範例中使用的一組變數。 修改下方的值,然後執行。

$subscriptionID = "subscriptionID"
$resourceGroup = "resourceGroupName"
$automationAccount = "automationAccountName"
$userAssignedOne = "userAssignedIdentityOne"
$userAssignedTwo = "userAssignedIdentityTwo"

使用 Azure 入口網站新增

執行下列步驟:

  1. 登入 Azure 入口網站

  2. 在 Azure 入口網站中,瀏覽至您的自動化帳戶。

  3. 在 [帳戶設定] 底下,選取 [身分識別]。

  4. 選取 [使用者指派] 索引標籤,然後選取 [新增]

  5. 選取您現有的使用者指派受控識別,然後選取 [新增]。 您接著會返回 [使用者指派] 索引標籤。

    Output from Portal.

使用 PowerShell 新增

使用 PowerShell Cmdlet Set-AzAutomationAccount 來新增使用者指派的受控識別。 您必須先考慮是否有現有的系統指派的受控識別。 下列範例會將兩個現有的使用者指派的受控識別新增至現有的自動化帳戶,並會停用系統指派的受控識別 (如果存在)。

$output = Set-AzAutomationAccount `
    -ResourceGroupName $resourceGroup `
    -Name $automationAccount `
    -AssignUserIdentity "/subscriptions/$subscriptionID/resourcegroups/$resourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$userAssignedOne", `
        "/subscriptions/$subscriptionID/resourcegroups/$resourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$userAssignedTwo"

$output

若要保留現有的系統指派的受控識別,請使用下列操作:

$output = Set-AzAutomationAccount `
    -ResourceGroupName $resourceGroup `
    -Name $automationAccount `
    -AssignUserIdentity "/subscriptions/$subscriptionID/resourcegroups/$resourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$userAssignedOne", `
        "/subscriptions/$subscriptionID/resourcegroups/$resourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$userAssignedTwo" `
    -AssignSystemIdentity

$output

輸出應如下所示:

Output from Set-AzAutomationAccount command.

如需其他輸出,請執行:$output.identity | ConvertTo-Json

新增 REST API 啟用

以下提供語法和範例步驟。

語法

下列範例本文語法會在尚未啟用時啟用系統指派的受控識別,並將兩個現有的使用者指派受控識別指派給現有的自動化帳戶。

修補檔

{
  "identity": {
    "type": "SystemAssigned, UserAssigned",
    "userAssignedIdentities": {
      "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resource-group-name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/firstIdentity": {},
      "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resource-group-name/providers/Microsoft.ManagedIdentity/userAssignedIdentities/secondIdentity": {}
    }
  }
}

API 的語法如下:

https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resource-group-name/providers/Microsoft.Automation/automationAccounts/automation-account-name?api-version=2020-01-13-preview 

範例

執行下列步驟。

  1. 將上述本文的語法修改為名為 body_ua.json 的檔案。 將檔案儲存在本機電腦或 Azure 儲存體帳戶中。

  2. 修改下方的變數值,然後執行。

    $file = "path\body_ua.json"
    
  3. 此範例會使用 PowerShell Cmdlet Invoke-RestMethod 將 PATCH 要求傳送至您的自動化帳戶。

    # build URI
    $URI = "https://management.azure.com/subscriptions/$subscriptionID/resourceGroups/$resourceGroup/providers/Microsoft.Automation/automationAccounts/$automationAccount`?api-version=2020-01-13-preview"
    
    # build body
    $body = Get-Content $file
    
    # obtain access token
    $azContext = Get-AzContext
    $azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile
    $profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile)
    $token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId)
    $authHeader = @{
        'Content-Type'='application/json'
        'Authorization'='Bearer ' + $token.AccessToken
    }
    
    # Invoke the REST API
    $response = Invoke-RestMethod -Uri $URI -Method PATCH -Headers $authHeader -Body $body
    
    # Review output
    $response.identity | ConvertTo-Json
    

    輸出應如下所示:

    {
    "type": "SystemAssigned, UserAssigned",
    "principalId": "00000000-0000-0000-0000-000000000000",
    "tenantId": "00000000-0000-0000-0000-000000000000",
    "userAssignedIdentities":  {
        "/subscriptions/ContosoID/resourcegroups/ContosoLab/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ContosoUAMI1":  {
                "PrincipalId":  "00000000-0000-0000-0000-000000000000",
                "ClientId":  "00000000-0000-0000-0000-000000000000"
                    },
        "/subscriptions/ContosoID/resourcegroups/ContosoLab/providers/Microsoft.ManagedIdentity/userAssignedIdentities/ContosoUAMI2":  {
                "PrincipalId":  "00000000-0000-0000-0000-000000000000",
                "ClientId":  "00000000-0000-0000-0000-000000000000"
                    }
        }
    }
    

藉由使用 ARM 範本新增

以下提供語法和範例步驟。

範本語法

下列範例範本語法會在尚未啟用時啟用系統指派的受控識別,並將兩個現有的使用者指派受控識別指派給現有的自動化帳戶。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "automationAccountName": {
     "defaultValue": "YourAutomationAccount",
      "type": "String",
      "metadata": {
        "description": "Automation account name"
      }
    },
    "userAssignedOne": {
     "defaultValue": "userAssignedOne",
      "type": "String",
      "metadata": {
        "description": "User-assigned managed identity"
      }
	  },
    "userAssignedTwo": {
     "defaultValue": "userAssignedTwo",
      "type": "String",
      "metadata": {
        "description": "User-assigned managed identity"
      }
	  }
   },
  "resources": [
    {
      "type": "Microsoft.Automation/automationAccounts",
      "apiVersion": "2020-01-13-preview",
      "name": "[parameters('automationAccountName')]",
      "location": "[resourceGroup().location]",
      "identity": {
        "type": "SystemAssigned, UserAssigned",
        "userAssignedIdentities": {
          "[resourceID('Microsoft.ManagedIdentity/userAssignedIdentities/',parameters('userAssignedOne'))]": {},
          "[resourceID('Microsoft.ManagedIdentity/userAssignedIdentities/',parameters('userAssignedTwo'))]": {}
        }
      },
      "properties": {
        "sku": {
          "name": "Basic"
        },
        "encryption": {
          "keySource": "Microsoft.Automation",
          "identity": {}
        }
      }
    }
  ]
}

範例

執行下列步驟。

  1. 將範本複製並貼到名稱為 的 template_ua.json 檔案中。 將檔案儲存在本機電腦或 Azure 儲存體帳戶中。

  2. 修改下方的變數值,然後執行。

    $templateFile = "path\template_ua.json"
    
  3. 使用 PowerShell Cmdlet New-AzResourceGroupDeployment 來部署範本。

    New-AzResourceGroupDeployment `
        -Name "UserAssignedDeployment" `
        -ResourceGroupName $resourceGroup `
        -TemplateFile $templateFile `
        -automationAccountName $automationAccount `
        -userAssignedOne $userAssignedOne `
        -userAssignedTwo $userAssignedTwo
    

    此命令不會產生輸出;不過,您可以使用下方程式碼來確認:

    (Get-AzAutomationAccount `
    -ResourceGroupName $resourceGroup `
    -Name $automationAccount).Identity | ConvertTo-Json
    

    輸出看起來會類似於上方 REST API 範例所顯示的輸出。

對使用者指派的受控識別指派角色

自動化帳戶可以使用本身使用者指派的受控識別來取得權杖,以存取其他受 Microsoft Entra ID 保護的資源 (如 Azure Key Vault)。 這些權杖並不代表任何應用程式的特定使用者。 相反地,這些權杖代表正在存取資源的應用程式。 例如在此情況中,權杖代表自動化帳戶。

在您可以使用使用者指派的受控識別進行驗證之前,請先在您打算使用該身分識別的 Azure 資源上,設定該身分識別的存取權。 若要完成這項工作,請在目標 Azure 資源上將適當的角色指派給該身分識別。

請遵循最低權限的原則,並小心地僅指派執行 Runbook 所需的權限。 例如,如果只需要自動化帳戶才能啟動或停止 Azure VM,則指派給執行身分帳戶或受控識別的權限必須僅用於啟動或停止 VM。 同樣地,如果 Runbook 正在從 Blob 儲存體讀取,請指派唯讀權限。

此範例使用 Azure PowerShell 來示範如何將訂用帳戶中的參與者角色指派給目標 Azure 資源。 參與者角色會作為範例使用,而且在您的案例中可能需要,也可能不需要。 或者,您也可以將角色指派給Azure 入口網站中的目標 Azure 資源。

New-AzRoleAssignment `
    -ObjectId <automation-Identity-object-id> `
    -Scope "/subscriptions/<subscription-id>" `
    -RoleDefinitionName "Contributor"

確認角色指派給使用者管理的身分識別

若要向自動化帳戶的使用者指派受控識別驗證角色,請遵循下列步驟:

  1. 登入 Azure 入口網站

  2. 移至自動化帳戶。

  3. 在 [帳戶設定] 底下,選取 [身分識別]、[使用者指派]

  4. 按下 [使用者指派的身分識別名稱]

    Assigning role in user-assigned identity in Azure portal.

    如果角色已指派給選取的使用者指派的受控識別,您可以看到角色指派的清單。 此清單包含您擁有讀取權限的所有角色指派。

    View role-assignments that you have permission in Azure portal.

  5. 若要變更訂用帳戶,請按一下 [訂用帳戶] 下拉式清單,然後選取適當的訂用帳戶。

  6. 按一下 [新增角色指派 (預覽)]

  7. 在下拉式清單中,選取角色指派所套用的資源集 - [訂用帳戶]、[資源群組]、[角色] 和 [範圍]
    如果您沒有角色指派,則可以將所選範圍的寫入權限以內嵌訊息方式檢視。

  8. 在 [角色] 下拉式清單中選取角色作為 [虛擬機器參與者]

  9. 按一下 [檔案] 。

    Add a role assignment in Azure portal.

幾分鐘後,受控識別將獲指派選取範圍中的角色。

使用使用者指派的受控識別來驗證存取權

啟用自動化帳戶的使用者指派受控識別,並提供目標資源的身分識別存取權之後,您可以針對支援受控識別的資源,在 Runbook 中指定該身分識別。 如需身分識別支援,請使用 Az cmdlet Connect-AzAccount

# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process

# Connect to Azure with user-assigned managed identity
$AzureContext = (Connect-AzAccount -Identity -AccountId <user-assigned-identity-ClientId>).context

# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext

不使用 Azure Cmdlet 來產生存取權杖

針對 HTTP 端點,請確定下列各項。

  • 中繼資料標頭必須存在,且應該設定為「true」。
  • 資源必須連同要求一起傳遞,作為 GET 要求的查詢參數,以及 POST 要求的表單資料。
  • 將環境變數 IDENTITY_HEADER 的值設定為 X-IDENTITY-HEADER。
  • Post 要求的內容類型必須是 application/x-www-form-urlencoded

使用 HTTP Get 取得使用者指派的受控識別的存取權杖

$resource= "?resource=https://management.azure.com/"
$client_id="&client_id=<ClientId of USI>"
$url = $env:IDENTITY_ENDPOINT + $resource + $client_id 
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"  
$Headers.Add("Metadata", "True")
$headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER) 
$accessToken = Invoke-RestMethod -Uri $url -Method 'GET' -Headers $Headers
Write-Output $accessToken.access_token 

使用 HTTP Post 取得使用者指派的受控識別的存取權杖

$url = $env:IDENTITY_ENDPOINT
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Metadata", "True")
$headers.Add("X-IDENTITY-HEADER", $env:IDENTITY_HEADER) 
$body = @{'resource'='https://management.azure.com/' 
'client_id'='<ClientId of USI>'}
$accessToken = Invoke-RestMethod $url -Method 'POST' -Headers $headers -ContentType 'application/x-www-form-urlencoded' -Body $body
Write-Output $accessToken.access_token 

在 Azure PowerShell 中使用使用者指派的受控識別

Write-Output "Connecting to azure via  Connect-AzAccount -Identity -AccountId <ClientId of USI>"  
Connect-AzAccount -Identity -AccountId <ClientId of USI> 
Write-Output "Successfully connected with Automation account's Managed Identity"  
Write-Output "Trying to fetch value from key vault using User Assigned Managed identity. Make sure you have given correct access to Managed Identity"  
$secret = Get-AzKeyVaultSecret -VaultName '<KVname>' -Name '<KeyName>'  
$ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secret.SecretValue)  
try {  
  $secretValueText = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)  
    Write-Output $secretValueText  
} finally {  
    [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr)  
} 

在 Python Runbook 中使用使用者指派的受控識別

#!/usr/bin/env python3  
import os  
import requests   

resource = "?resource=https://management.azure.com/" 
client_id = "&client_id=<ClientId of USI>" 
endPoint = os.getenv('IDENTITY_ENDPOINT')+ resource +client_id 
identityHeader = os.getenv('IDENTITY_HEADER') 
payload={}  
headers = {  
  'X-IDENTITY-HEADER': identityHeader,
  'Metadata': 'True' 
}  
response = requests.request("GET", endPoint, headers=headers, data=payload)  
print(response.text) 

下一步