0. Name
Managed identities for Azure resources is the new name for the service formerly known as Managed Service Identity (MSI).
Thank you @WillHuang!
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:
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,
3.1 How come no credentials are needed?
Because access tokens are used instead. The general workflow summed up:
- Assign a managed identity to an MSI resource.
- Grant access to that managed identity on the target resource.
- Request an access token
- Use the token through / from the MSI resource to perform actions on the target resource.
- 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)
- Set up a virtual machine (
AZVM
) with system-assigned MSI (AZVM-id
).
- Authorize this identity in an Azure key vault (
AZKV
).
- SSH into
AZVM
.
- Get an access token.
- 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
- Set up (existing) virtual machines (
AZVM-<n>
) with system-assigned managed identities (AZVM-id-<n>
).
- Assign additional user-assigned MSIs (
AZVM-user-id-<n>
; docs: create & assign)
- 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)
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).
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.
SSH into the VM in Step 1.
ssh -l <username> -i <private_key> 1.2.3.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"
}
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.