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
| Attribute | Description |
|---|---|
azure_msi.tenant.id | Azure AD tenant ID (tid claim from the token) |
azure_msi.identity.principal_id | Object 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
| Field | Required | Default | Description |
|---|---|---|---|
tenants | Yes | — | List of allowed Azure MSI identity configurations. At least one entry is required. |
tenants[].tenantID | Yes | — | Azure AD tenant ID. Matched against the tid claim. |
tenants[].principalID | Yes | — | Object ID of the managed identity allowed to connect. Matched against the oid claim. |
tenants[].audience | No | api://<tenantId>/defakto-server | Expected token audience (aud claim). |
tenants[].issuerURL | No | https://sts.windows.net/<tenantId>/ | OIDC issuer URL. Override for V2 tokens (https://login.microsoftonline.com/<tenantId>/v2.0). |
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
principalIDin each tenant entry is the primary access control. Only the specific managed identity with that object ID can authenticate. - The
audienceconstraint prevents tokens issued for other Azure resources from being used to authenticate to the Trust Domain Server. - User-assigned identities are identified by the
oidclaim, which corresponds to the identity's object ID (not the client ID).