2
votes

I have been testing out the recently released Managed Service Identity (MSI) for Azure and have successfully created an MSI for our App Services using the ARM template approach described in the documentation here: How to use Azure Managed Service Identity (public preview) in App Service and Azure Functions

However, I would like to grant access for the managed identity on other resources, such as a key vault. I have been able to do this through the portal, but need to be able to script it in PowerShell in order to integrate with our continuous deployment builds.

I have successfully created the access using PowerShell by executing Set-AzureRmKeyVaultAccessPolicy cmdlet. However I have only been able to do this with a hard-coded object id, manually copied and pasted from the portal once the MSI has been created.

My question is, how in PowerShell can I get a reference to the MSI's object id, so that I can grant access to it on other resources? The only examples I can find (such as this one), refer only to VMs and not App Services.

4

4 Answers

2
votes

You could use Get-AzureADServicePrincipal.

$web=Get-AzureADServicePrincipal -SearchString "<name>"
$web.ObjectId

By default, the name is your web app name.

Update:

For OP's scenario, we could use the template to get a reference to an Azure MSI.

1
votes

Because you deployed your resources using ARM, I'd like to add this answer as you can do it using ARM only:

  1. Enable ARM template deployment for your key vault:

    {
      "type": "Microsoft.KeyVault/vaults",   
      "name": "[parameters('keyVaultName')]",       
      ...
      "properties": {
        "enabledForTemplateDeployment": true,
        ...
      }
    }
    
  2. Create the system identity:

    {
      "type": "Microsoft.Web/sites",
      "name": "[parameters('functionAppName')]",       
      ...
      "identity": {
        "type": "SystemAssigned"
      }
      ...
    }
    
  3. Create an access policy:

    {
      "apiVersion": "2018-02-14",
      "type": "Microsoft.KeyVault/vaults/accessPolicies",
      "name": "[concat(parameters('keyVaultName'), '/add')]",
      "properties": {
        "accessPolicies": [
          {
            "tenantId": "[parameters('tenantId')]",
            "objectId": "[reference(resourceId('Microsoft.Web/sites', parameters('functionAppName')), '2018-02-01', 'Full').identity.principalId]",
            "permissions": {
              "secrets": [ "get" ]
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]",
        "[resourceId('Microsoft.Web/sites', parameters('functionAppName'))]"
      ]
    }
    
1
votes

With the latest AzureRM Module (6.13.1)

$AppProp = Get-AzureRmWebApp -ResourceGroupName $resourceGroupName -Name $name

Write-Output $AppProp.Identity

This Identity property gives all the required details about MSI.

Type        : SystemAssigned

TenantId    : c764619f-8856-4a9f-a81e-eeb0c3f93592

PrincipalId : 3d317dfe-5589-4aae-94a4-51f1776979a7
0
votes

If you want to use the Azure RM PowerShell Commandlets than you can use:

$(Get-AzureRmADServicePrincipal -SearchString $Name | where {$_.DisplayName -eq $Name}).Id

The where part is to make sure you have the specific SP and not multiple results starting with the same name.

Edit: Even this above could result in multiple values. An even better solution is to filter further like this:

Get-AzureRmADServicePrincipal -SearchString $Name | where {($_.DisplayName -eq $Name) -and ($_.ServicePrincipalNames -match "https://identity.azure.net")}