Skip to content

Instantly share code, notes, and snippets.

@toraritte
Last active March 31, 2023 10:49
Show Gist options
  • Save toraritte/c58778aa92d9a8b93aa3d3a0741d89a3 to your computer and use it in GitHub Desktop.
Save toraritte/c58778aa92d9a8b93aa3d3a0741d89a3 to your computer and use it in GitHub Desktop.
What are Azure managed identities (MSI)?

1. Definition

A managed identity (MSI1) is a special kind of service principal that is assigned to an Azure resource that supports wielding managed identities to access other Azure services / resources without credentials.

2. Terms

Going to use the following terms (some arbitrarily chosen) here:

  • MSI resource: an Azure resource that support having (or endowed with) managed identities

  • target resource: an Azure resource that the MSI resource is trying to access

  • identity: Azure Active Directory identities); a quick overview:

    security
    principal
        │
        ├─► user
        │
        ├─► group
        │                  managed
        └─► service  ────► identity
            principal      (MSI)
    

    (See also [this answer] (https://stackoverflow.com/a/75850555/1498178).)

  • service principal:

    A security identity used by applications or services to access specific Azure resources. You can think of it as a user identity (username and password or certificate) for an application.
    (from Steps to assign an Azure role)

    or

    "An application whose tokens can be used to authenticate and grant access to specific Azure resources from a user-app, service or automation tool, when an organization is using Azure Active Directory"

    In essence, by using a Service Principal, you avoid creating “fake users” (we would call them service account in on-premises Active Directory…) in Azure AD to manage authentication when you need to access Azure Resources.
    (from Demystifying Service Principals – Managed Identities)

3. Properties of managed identities

TL;DR

user-assigned MSI system-assigned MSI
What if MSI resource is deleted? unassigned and remains intact deleted
How many can be assigned
to an MSI resource?
any number only 1
How many can be authorized
on a target resource?
any number any number
Can it be authorized on multiple
target resources at the same time?
yes yes

(MSI resource =/= managed identity)

The relationship between MSI resources and managed identities is similar to boxes with labels or people having names & nicknames / aliases:

An MSI resource

  • can have ONE system-assigned managed identity

    (such as a person is only allowed to have one legal name)

  • can be assigned MANY user-assigned managed identities

    (such as a person can be known by different nicknames by their associates)

Not sure what the intention was with this design choice, but this allows one to create multiple identities for an MSI resource (or, put another way, an MSI resource can assume multiple identities), each of which could be authorized to perform different operations on target resources. (A target resource can also authorize multiple MSIs; see "Examples" section below.)

When an MSI resource is deleted,

  • the system-assigned MSI is deleted with it

  • the user-assigned managed identities will remain (these will only get unassigned)

3.1 How come no credentials are needed?

Because access tokens are used instead. The general workflow summed up:

  1. Assign a managed identity to an MSI resource.
  2. Grant access to that managed identity on the target resource.
  3. Request an access token
  4. Use the token through / from the MSI resource to perform actions on the target resource.
  5. When the token expires, go to Step 3.

See "Example A (with commands)" section below for the specifics.

4. Examples2

NOTE
In the examples below, the type of the target resources is an Azure Key Vault, that supports access control (IAM) and access policies to authorize MSIs; this is a tricky topic, but this Stackoverflow thread has a great explanation.

4.1 Example A (overview)

  1. Set up a virtual machine (AZVM) with system-assigned MSI (AZVM-id).
  2. Authorize this identity in an Azure key vault (AZKV).
  3. SSH into AZVM.
  4. Get an access token.
  5. Perform operations on AZKV that AZVM (through its AZVM-id) is permitted to do (in Step 2.).

For the specifics, see "Example A (with commands)" section below.

                          (e.g., REST API)
                   ┌── ── ── ── ── ── ─── ─── ─── ─── ──┐
                   │                                    │
         ┌─AZVM─── │ ─┐                ┌─AZKV────────┐  │
         │            │                │             │  │
         │         │  │                │             │
                   ▼  │                │             │  │
   ┌─ ── ───(service) │                │ + secrets   │  │
   │                  │                │ + keys      │
         │            │                    + key1       │
   │     └────────────┘          ┌── ── ─► + key2 ── ───┘
   │         identities=         │
   └── ─── ───►[ AZVM-id ]─── ───┘     │             │
                                       │             │
                                       └─────────────┘

4.2 Example B

  1. Set up (existing) virtual machines (AZVM-<n>) with system-assigned managed identities (AZVM-id-<n>).
  2. Assign additional user-assigned MSIs (AZVM-user-id-<n>; docs: create & assign)
  3. Authorize the above MSIs on multiple a key vaults (AZKV-<n>).
                                   ┌─────────────────────────────┐
                                   │                             │
                                   │         ┌──AZKV-1────────┐  │
              ┌──AZVM-1─────┐      │         │                │  │
              │             │      │         │                │  │
              │             │      │         │ + keys         │  │
           ┌──── (service) ◄───────┘         │    + key-1     │  │
           │  │             │           ┌──────► + key-2 ────────┘
           │  │             │           │    │                │ 
           │  │             │           │    │                │
           │  └─────────────┘           │    │ + secrets      │
           │      identities=           │    │   + secret-1   │
           │        [ AZVM-id-1         │  ┌──── + password ◄─────┐
           │        , AZVM-user-id-1    │  │ │                │   │
           │        , AZVM-user-id-2    │  │ │                │   │
           └──────► , AZVM-user-id-3 ───┘  │ └────────────────┘   │
                    ]                      │                      │
                                           │                      │
                                           │ ┌──AZKV-2────────┐   │
                                           │ │                │   │
           ┌─────AZVM-2─────┐              │ │ + secrets      │   │
           │                │              │ │   + secret-2   │   │
           │                │              │ │   + password   │   │
     USER ────┐◄───────────────────────────┘ │                │   │
           │  │             │                │ + keys         │   │
           │  │             │     ┌───────────── + key-3 ◄──────┐ │
           │  │ ┌──(service) ◄────┘          │   + key-4      │ │ │
           │  │ │           │                │                │ │ │
           └──│─│───────────┘                └────────────────┘ │ │
              │ │ identities=                                   │ │
              │ └──►[ AZVM-id-2  ───────────────────────────────┘ │
              └────►, AZVM-user-id-3 ─────────────────────────────┘
                    ]

4.3 Example A (with commands)

  1. Endow a virtual machine (the MSI resource) with system-assigned managed identity

    When using the Portal, this can be done by going to the "Identity" menu item in a virtual machine's page on the Portal (see Demystifying Service Principals – Managed Identities or Configure managed identities for Azure resources on a VM using the Azure portal in the docs).

    Screenshot from Azure portal of a virtual machine's page highlighting the "Identity" item in the menu.

  2. Grant access to the system-assigned managed identity on the key vault (the target resource).

    When using the Portal, this can be done by clicking on "Access policies" menu item, and then on the "+ Create" button. The 1st page will ask to choose what privileges one wants to assign to the policy, the 2nd page will ask which identity to be used so choose the system-assigned MSI in Step 1. See more at Azure Key Vault security in the docs.

  3. SSH into the VM in Step 1.

    ssh -l <username> -i <private_key> 1.2.3.4
    
  4. Request a token.

    Using the Azure REST API via curl.

    (The jq command is not necessary; it just makes the output easier to read.)

    $ curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net" \
        -H Metadata:true  | jq
    
    {
      "access_token": "...",
      "client_id": "12345678-9abc-def1-2345-6789abcdef12",
      "expires_in": "84162",
      "expires_on": "1680292962",
      "ext_expires_in": "86399",
      "not_before": "1680206262",
      "resource": "https://vault.azure.net",
      "token_type": "Bearer"
    }
    
  5. Use the token.

    For example, to list the keys in the key vault (again, using the Azure REST API via curl):

    $ curl https://my-project.vault.azure.net/keys?api-version=7.3 \
        -H "Authorization: Bearer <ACCESS_TOKEN-FROM-STEP-4>" | jq
    
    {
      "value": [
        {
          "kid": "https://my-project.vault.azure.net/keys/keyname",
          "attributes": {
            "enabled": true,
            "created": 1679939404,
            "updated": 1679939404,
            "recoveryLevel": "Recoverable+Purgeable",
            "recoverableDays": 90,
            "exportable": false
          },
          "tags": {}
        }
      ],
      "nextLink": null
    }
    

To avoid copying access_token manually:

$ access_token=$(curl "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net"  -H Metadata:true  | jq '.access_token' -r)
$
$ curl https://my-project.vault.azure.net/keys?api-version=7.3 \
    -H "Authorization: Bearer ${access_token}" | jq

Footnotes

[1]: From note in the docs: "Managed identities for Azure resources is the new name for the service formerly known as Managed Service Identity (MSI)." Decided to keep using this because every single Azure API implementation and 3rd party application that I used thus far referred to managed identity as MSI.

[2]: Loosely based on the one in Demystifying Service Principals – Managed Identities.

Notes

  • Figures were created with asciiflow.

  • Finding MSIs on the Portal

    User-assigned MSIs have a their own sub-category "Managed Identities", but this won't show system-assigned ones. The latter need to be searched individually.

  • Resource groups and MSIs

    This is only based on my experiences on the Portal, but it seems that system-assigned MSIs don't belong to a resource group (or they are hidden). That is, user-assigned ones show it clearly when called up, but couldn't find this info for system-assigned MSIs, and it doesn't make sense. The latter are tied tightly to the MSI resource so I went to the particular resource's resource group, listed all members, but they also don't show up there. Weird.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment