How to use managed identities with Azure services to connect to Azure Cosmos DB for Table

APPLIES TO: Table

Diagram of the current location ('Prepare') in the sequence of the deployment guide.

Diagram of the sequence of the deployment guide including these locations, in order: Overview, Concepts, Prepare, Role-based access control, and Reference. The 'Prepare' location is currently highlighted.

This article reviews the steps required to create managed identities to use with a deployed application connected to Azure Cosmos DB for Table.

Managed identities are one of many types of identity resources in Microsoft Entra ID for applications to use when connecting to services that support Microsoft Entra authentication. Managed identities can be used in lieu of traditional resource-owned credentials like keys. In Azure, managed identities provide a way for your applications to obtain a Microsoft Entra token to authenticate to Azure services without you needing to write a large amount of authentication code.

You can use Microsoft Entra to authenticate to Azure services including, but not limited to:

  • Azure SQL
  • Azure AI
  • Azure Cosmos DB
  • Azure Storage
  • Azure Event Hubs
  • Azure Container Registry

You can use managed identities to represent the principal that authenticates to an Azure service from other Azure services including, but not limited to:

  • Azure Kubernetes Service
  • Azure Container Apps
  • Azure Virtual Machines
  • Azure Functions
  • Azure App Service
  • Azure Spring Apps
  • Azure Service Fabric

Managed identities enable multiple secure scenarios where various Azure services can connect to each other. Some examples include:

  • Creating a system-assigned managed identity for an application in Azure Spring Apps to connect to and query an Azure SQL account
  • Using a single user-assigned managed identity with both Azure Kubernetes Service and Azure Functions to issue requests to an Azure AI account
  • Using a managed identity for an Azure Cosmos DB account to store keys in Azure Key Vault

For more information, see managed identities for Azure resources.

Prerequisites

Create an Azure service with a system-assigned managed identity

Create a new Azure service with a system-assigned managed identity. This section creates an Azure Container Instances resource.

  1. Use az container create to create a new container instance. Configure the account to use a system-assigned managed identity by using the assign-identity parameter.

    az container create \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-new-container>" \
        --image mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled \
        --cpu 1 \
        --memory 2 \
        --assign-identity
    
  2. Get the details for the system-assigned managed identity using az container show and a JMESPath query.

    az container show \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-container>" \
        --query "identity"
    
  3. Review the output from the command. It should include the unique identifiers for the identity and tenant.

    {
      "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
      "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
      "type": "SystemAssigned",
      "userAssignedIdentities": null
    }
    
  1. Create a new Bicep file to define a new container instance. Name the file container-instance.bicep. Set these properties for the container instance:

    Value
    name Use a parameter named instanceName
    location Set to resource group's location
    identity.type SystemAssigned
    properties.osType Linux
    properties.containers[0].name aspnet-sample
    properties.containers[0].properties.image mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled
    properties.containers[0].properties.resources.requests.cpu 1
    properties.containers[0].properties.resources.requests.memoryInGB 2
    metadata description = 'Create Azure Container Instance resource with system-assigned managed identity.'
    
    @description('Name of the Azure Container Instances resource.')
    param instanceName string
    
    resource instance 'Microsoft.ContainerInstance/containerGroups@2023-05-01' = {
      name: instanceName
      location: resourceGroup().location
      identity: {
        type: 'SystemAssigned'
      }
      properties: {
        osType: 'Linux'
        containers: [
          {
            name: 'aspnet-sample'
            properties: {
              image: 'mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled'
              resources: {
                requests: {
                  cpu: 1
                  memoryInGB: 2
                }
              }
            }
          }
        ]
      }
    }
    
    output systemAssignedIdentity object = instance.identity    
    
  2. Create a new Bicep parameters file named container-instance.bicepparam. In this parameters file, create a unique name for your container instance using the instanceName parameter.

    using './container-instance.bicep'
    
    param instanceName = '<name-of-new-container-instance>'
    
  3. Deploy the Bicep template using az deployment group create. Specify the name of the Bicep template, parameters file, and Azure resource group.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --parameters "container-instance.bicepparam" \
        --template-file "container-instance.bicep"
    
  4. Review the output from the deployment. The output contains the identity object from the container instance in the properties.outputs.systemAssignedIdentity.value property.

    {
      "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
      "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
      "type": "SystemAssigned"
    }
    
  1. Sign in to the Azure portal (https://portal.azure.com).

  2. Enter Azure Container Instances in the global search bar.

    Screenshot of the global search bar in the Azure portal.

  3. Within Services, select Container instances.

    Screenshot of the 'Container instances' option selected in the search menu.

  4. In the Container instances pane, select Create.

    Screenshot of the 'Create' option within the pane for Azure Container Instances.

  5. Within the Basics pane, configure the following options, and then select Review + create:

    Value
    Subscription Select your Azure subscription
    Resource Group Create a new resource group or select an existing resource group
    Container name Provide a globally unique name
    Region Select a supported Azure region for your subscription

    Screenshot of the Azure Container Instances resource creation 'Basics' pane.

    Tip

    You can leave any unspecified options to their default values.

  6. On the Review + create pane, wait for validation of your account to finish successfully, and then select Create.

    Screenshot of the resource validation step in the creation experience for a container instance.

  7. The portal automatically navigates to the Deployment pane. Wait for the deployment to complete.

  8. Once the deployment is complete, select Go to resource to navigate to the new Azure Container Instances resource.

    Screenshot of a fully deployed Azure Container Instances resource with the 'Go to resource' option highlighted.

  9. Within the pane for the new container instance, select Identity inside the Settings section of the service menu.

    Screenshot of the 'Identity' option in the service menu for the container instance.

  10. In the Identity pane, enable the system-assigned managed identity by setting the Status option to On. Then, select Save and resolve any prompts to commit the change.

    Screenshot of setting the 'Status' option to 'On' for a system-assigned managed identity.

  11. Once the system-assigned managed identity is ready, review the value of the Object (principal) ID property. This property's value is the unique identifier for the identity.

    Screenshot of the details for an enabled system-assigned managed identity.

    Tip

    In this example screenshot, the unique identifier for the system-assigned managed identity is bbbbbbbb-1111-2222-3333-cccccccccccc.

  1. Create an object representing a container using New-AzContainerInstanceObject and store it in a variable named $container. Then, use that container object to create a new container instance with New-AzContainerGroup. Configure the account to use a system-assigned managed identity by setting the IdentityType parameter to SystemAssigned.

    $parameters = @{
        Name = "aspnet-sample"
        Image = "mcr.microsoft.com/dotnet/samples:aspnetapp-chiseled"
        RequestCpu = 1 
        RequestMemoryInGb = 2
    }
    $container = New-AzContainerInstanceObject @parameters
    
    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-new-container>"
        Container = $container
        OsType = "Linux"
        Location = "<azure-region>"
        IdentityType = "SystemAssigned"
    }
    New-AzContainerGroup @parameters
    
  2. Get the details for the system-assigned managed identity using Get-AzContainerGroup and Format-List selecting only the Identity property.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-container>"
    }
    Get-AzContainerGroup @parameters | Format-List Identity
    
  3. Review the output from the command. It should include the unique identifiers for the identity and tenant.

    Identity : {
                 "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
                 "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
                 "type": "SystemAssigned"
               }
    

Create a user-assigned managed identity

Create a user-assigned managed identity that can be used with one or more Azure services in a portable manner.

  1. Use az identity create to create a new user-assigned managed identity in your Azure resource group.

    az identity create \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-new-managed-identity>"
    
  2. Get the list of user-assigned managed identities in your resource group using az identity list

    az identity list \
        --resource-group "<name-of-existing-resource-group>"    
    
  3. Review the output from the command. Record the value of the id field as this fully qualified resource identifier is used to assign the user-assigned managed identity to your Azure resource.

    {
      "clientId": "11112222-bbbb-3333-cccc-4444dddd5555",
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned",
      "location": "<azure-location>",
      "name": "msdocs-identity-example-user-assigned",
      "principalId": "cccccccc-dddd-eeee-3333-444444444444",
      "resourceGroup": "msdocs-identity-example",
      "systemData": null,
      "tags": {},
      "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
      "type": "Microsoft.ManagedIdentity/userAssignedIdentities"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned. This example uses fictitious data and your identifier would be distinct from this example.

  1. Create a Bicep file to define a user-assigned managed identity and name the file user-assigned-managed-identity.bicep. Set these minimal properties:

    Value
    name Use an optional parameter named identityName and generate a unique default value
    location Set to resource group's location
    metadata description = 'Create a user-assigned managed identity.'
    
    param identityName string = uniqueString(subscription().id, resourceGroup().id)
    
    resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
      name: identityName
      location: resourceGroup().location
    }
    
    output id string = identity.id
    output name string = identity.name
    
  2. Deploy the Bicep template using az deployment group create. Specify the name of the Bicep template and Azure resource group.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --template-file "user-assigned-managed-identity.bicep"
    
  3. Review the output from the deployment. The output contains the unique identifier of the managed identity in the properties.outputs.name.value property. Record this value as it is required to use when creating a new Azure resource later in this guide.

    {
      "type": "String",
      "value": "msdocs-identity-example-user-assigned"
    }
    

    Note

    In this example, the name.value would be msdocs-identity-example-user-assigned. This example uses fictitious data and your identifier would be distinct from this example.

  1. Enter Managed identity in the global search bar.

  2. Within Services, select Managed identities.

    Screenshot of the 'Managed identities' option selected in the search menu.

  3. In the Container instances pane, select Create.

    Screenshot of the 'Create' option within the pane for Managed Identities.

  4. Within the Basics pane, configure the following options, and then select Review + create:

    Value
    Subscription Select your Azure subscription
    Resource Group Create a new resource group or select an existing resource group
    Region Select a supported Azure region for your subscription
    Name Provide a globally unique name

    Screenshot of the managed identity resource creation 'Basics' pane.

  5. On the Review + create pane, wait for validation of your account to finish successfully, and then select Create.

    Screenshot of the resource validation step in the creation experience for a managed identity.

  6. The portal automatically navigates to the Deployment pane. Wait for the deployment to complete.

  7. Wait for the deployment of the managed identity to complete.

    Screenshot of a fully deployed managed identity resource.

  1. Create a new user-assigned managed identity using New-AzUserAssignedIdentity in your Azure resource group.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-new-managed-identity>"
        Location = "<azure-region>"
    }
    New-AzUserAssignedIdentity @parameters
    
  2. Use Get-AzUserAssignedIdentity to get a list of user-assigned managed identities in your resource group.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
    }
    Get-AzUserAssignedIdentity @parameters | Format-List Name, Id
    
  3. Review the output from the command. Record the value of the Id field as this fully qualified resource identifier is used to assign the user-assigned managed identity to your Azure resource.

    Name : msdocs-identity-example-user-assigned
    Id   : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned
    

    Note

    In this example, the Id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned. This example uses fictitious data and your identifier would be distinct from this example.

Create an Azure service with a user-assigned managed identity

Assign the previously created user-assigned managed identity to a new Azure host service. This section creates an Azure App Services web app resource.

  1. Create a new app service plan using az appservice plan create.

    az appservice plan create \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-new-plan>"
    
  2. Assign the user-assigned managed identity to a new web app with az webapp create. Use the id field recorded earlier in this guide as the value of the ssign-identity parameter.

    az webapp create \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-web-app>" \
        --plan "<name-of-existing-plan>" \
        --assign-identity "<resource-id-recorded-earlier>"
    
  3. Get the details for all identities assigned to this account using az webapp show and a JMESPath query.

    az webapp show \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-account>" \
        --query "identity"   
    
  4. Review the output from the command. It should include both the user-assigned managed identity.

    {
      "principalId": null,
      "tenantId": null,
      "type": "UserAssigned",
      "userAssignedIdentities": {
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned": {
          "clientId": "11112222-bbbb-3333-cccc-4444dddd5555",
          "principalId": "cccccccc-dddd-eeee-3333-444444444444"
        }
      }
    }
    
  1. Create another Bicep file named app-service-web-app.bicep and define an Azure App Service plan and web app. Set these properties for those resources:

    Resource Value
    name Existing managed identity Use a parameter named identityName
    name App service plan Use a parameter named planName
    location App service plan Set to resource group's location
    name Web app Use a parameter named webAppName
    location Web app Set to resource group's location
    identity.type UserAssigned
    identity.userAssignedIdentities.{identity.id} {}
    properties.serverFarmId plan.id
    metadata description = 'Creates an Azure App Service plan and web app with a user-assigned managed identity.'
    
    @description('The name of the app service plan.')
    param planName string
    
    @description('The name of the web app.')
    param webAppName string
    
    @description('The name of the user-assigned managed identity.')
    param identityName string
    
    resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
      name: identityName
    }
    
    resource plan 'Microsoft.Web/serverfarms@2023-12-01' = {
      name: planName
      location: resourceGroup().location
    }
    
    resource webApp 'Microsoft.Web/sites@2023-12-01' = {
      name: webAppName
      location: resourceGroup().location
      identity: {
        type: 'UserAssigned'
        userAssignedIdentities: {
          '${identity.id}': {}
        }
      }
      properties: {
        serverFarmId: plan.id
      }
    }
    
    output userAssignedIdentity object = webApp.identity
    
  2. Create a Bicep parameters file named app-service-web-app.bicepparam. In this parameters file, create a unique name for your web app and plan using the planName and webAppName parameters respectively. Then, provide the name of the user-assigned managed identity as the value of the identityName parameter.

    using './app-service-web-app.bicep'
    
    param planName = '<name-of-new-app-service-plan>'
    param webAppName = '<name-of-new-web-app>'
    param identityName = '<name-of-existing-managed-identity>'
    
  3. Deploy the Bicep template using az deployment group create. Specify the name of the Bicep template, parameters file, and Azure resource group.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --parameters "app-service-web-app.bicepparam" \
        --template-file "app-service-web-app.bicep"
    
  4. Review the output from the deployment. The output contains the identity object from the container instance in the properties.outputs.userAssignedIdentity.value property.

    {
      "type": "UserAssigned",
      "userAssignedIdentities": {
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned": {
          "clientId": "11112222-bbbb-3333-cccc-4444dddd5555",
          "principalId": "cccccccc-dddd-eeee-3333-444444444444"
        }
      }
    }
    
  1. Enter Web app in the global search bar.

  2. Within Services, select App Services.

    Screenshot of the 'App Services' option selected in the search menu.

  3. In the App Services pane, select Create, and then Web App.

    Screenshot of the 'Create' and 'Web App' options within the pane for Azure App Service.

  4. Within the Basics pane, configure the following options, and then select Review + create:

    Value
    Subscription Select your Azure subscription
    Resource Group Create a new resource group or select an existing resource group
    Name Provide a globally unique name
    Plan Create a new plan or select an existing plan

    Screenshot of a web app's resource creation 'Basics' pane.

  5. On the Review + create pane, wait for validation of your account to finish successfully, and then select Create.

    Screenshot of the resource validation step in the creation experience for a web app resource.

  6. The portal automatically navigates to the Deployment pane. Wait for the deployment to complete.

  7. Once the deployment is complete, select Go to resource to navigate to the new Azure Container Instances resource.

    Screenshot of a fully deployed Azure App Service web app resource with the 'Go to resource' option highlighted.

  8. Within the pane for the new container instance, select Identity inside the Settings section of the service menu.

    Screenshot of the 'Identity' option in the service menu for the web app.

  9. In the Identity pane, select the User assigned option.

    Screenshot of the 'User assigned' option in the 'Identity' pane for the web app.

  10. Select Add to open a dialog to assign existing user-assigned managed identities. In the dialog, select your existing user-assigned managed identity and then select Add.

    Screenshot of the 'Add' option and the 'Add user assigned managed identity' dialog in the 'Identity' pane for the web app.

  11. Finally, review the list of user-assigned managed identities associated with your web app. It should include the identity's name, resource group name, and subscription identifier.

    Screenshot of the list of user-assigned managed identities associated with the current web app.

  1. Use New-AzWebApp to create a new Azure App Service web app.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-new-web-app>"
        Location = "<azure-region>"
    }
    New-AzWebApp @parameters
    
  2. Patch the newly created web app to set the identity.type property to UserAssigned and add your existing user-assigned managed identity to the identity.userAssignedIdentities property. To accomplish this task, first provide the id field recorded earlier in this guide as the value of the identityId shell variable. Then, construct a payload object and convert it to JSON. Finally, use Invoke-AzRestMethod with the PATCH HTTP verb to update the existing web app.

    $identityId = "<resource-id-recorded-earlier>"
    
    $payload = @{
        identity = @{
            type = "UserAssigned"
            userAssignedIdentities = @{
                "$identityId" = @{}
            }
        }
    } | ConvertTo-Json -Depth 3
    
    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-web-app>"
        ResourceProviderName = 'Microsoft.Web'
        ResourceType = 'sites'
        ApiVersion = '2023-12-01'
        Method = 'PATCH'
        Payload = $payload
    }
    Invoke-AzRestMethod @parameters
    
  3. Get the details for all identities assigned to the web app using Get-AzWebApp, Select-Object, and ConvertTo-Json selecting only the Identity property.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-web-app>"
    }
    Get-AzWebApp @parameters | Select-Object Identity | ConvertTo-Json -Depth 3
    
  4. Review the output from the command. It should include the unique identifiers for the identity and tenant.

    {
      "Identity": {
        "Type": "UserAssigned",
        "TenantId": null,
        "PrincipalId": null,
        "UserAssignedIdentities": {
          "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msdocs-identity-example-user-assigned": {
            "PrincipalId": "cccccccc-dddd-eeee-3333-444444444444",
            "ClientId": "11112222-bbbb-3333-cccc-4444dddd5555"
          }
        }
      }
    }
    

Next step