Skip to main content

Azure Managed Identity (MSI)

The Azure MSI method authenticates workloads using Azure Managed Identity. The workload fetches a managed identity access token from the Azure Instance Metadata Service (IMDS); the Trust Domain Server verifies the token's authenticity using Azure Entra's OIDC discovery endpoint.

Use this method for Azure VMs, AKS pods, or any Azure workload with a Managed Identity assigned.

Attributes available for SVID issuance

AttributeDescription
azure_msi.tenant.idAzure AD tenant ID (tid claim from the token)
azure_msi.identity.principal_idObject ID (oid claim) of the managed identity

All attributes have the origin azure_msi.

Example SPIFFE ID template:

/azure/{{azure_msi.tenant.id}}/{{azure_msi.identity.principal_id}}

Prerequisites

The workload must have an Azure Managed Identity assigned — either system-assigned or user-assigned.

Run the following one-time script to create the app registration used as the default token audience (replace <tenantId> with your Azure AD tenant ID):

TENANT_ID=$(az account show --query tenantId -o tsv)
az ad app create \
--display-name "defakto-server" \
--identifier-uris "api://$TENANT_ID/defakto-server" \
--sign-in-audience "AzureADMyOrg"

This creates an app registration with URI api://<tenantId>/defakto-server. Both the agent and server use this URI as the default audience automatically — no further audience configuration is needed in most cases.

How to Deploy

section: ServerlessAttestation
schema: v1
spec:
policies:
- name: azure_policy
svidPolicy:
pathTemplate: "/azure/{{azure_msi.tenant_id}}/{{azure_msi.principal_id}}"
requiredAttestors:
- type: azure_msi
config:
tenants:
- tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
principalID: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
# audience defaults to "api://<tenantId>/defakto-server"

Multiple tenant entries can be configured to allow workloads from different Azure Entra tenants:

tenants:
- tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
principalID: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
- tenantID: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
principalID: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
audience: "https://myotherdefaktoapp.com/"

For V2 token issuers (not the default):

tenants:
- tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
principalID: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
issuerURL: "https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/v2.0"

Apply it using spirlctl:

spirlctl config set trust-domain --id <trust-domain-id> serverless.yaml

Or using Terraform:

resource "spirl_trust_domain_config" "serverless_attestation" {
trust_domain_id = spirl_trust_domain.my_trust_domain.id
sections = {
ServerlessAttestation = <<-YAML
section: ServerlessAttestation
schema: v1
spec:
policies:
- name: azure_policy
svidPolicy:
pathTemplate: "/azure/{{azure_msi.tenant_id}}/{{azure_msi.principal_id}}"
requiredAttestors:
- type: azure_msi
config:
tenants:
- tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
principalID: "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
YAML
}
}

Once a configuration document is validated and stored, the Defakto control plane syncs it to your Trust Domain Servers automatically. No restart is required.

Server Configuration Reference

FieldRequiredDefaultDescription
tenantsYesList of allowed Azure MSI identity configurations. At least one entry is required.
tenants[].tenantIDYesAzure AD tenant ID. Matched against the tid claim.
tenants[].principalIDYesObject ID of the managed identity allowed to connect. Matched against the oid claim.
tenants[].audienceNoapi://<tenantId>/defakto-serverExpected token audience (aud claim).
tenants[].issuerURLNohttps://sts.windows.net/<tenantId>/OIDC issuer URL. Override for V2 tokens (https://login.microsoftonline.com/<tenantId>/v2.0).
note

The default issuer is the V1 endpoint (sts.windows.net). V1 vs V2 is controlled by the accessTokenAcceptedVersion setting in the app registration manifest. Only override issuerURL if you have explicitly configured V2 tokens.

Security Considerations

  • The principalID in each tenant entry is the primary access control. Only the specific managed identity with that object ID can authenticate.
  • The audience constraint prevents tokens issued for other Azure resources from being used to authenticate to the Trust Domain Server.
  • User-assigned identities are identified by the oid claim, which corresponds to the identity's object ID (not the client ID).