Skip to main content

Azure IMDS

The Azure IMDS method attests agents using the Azure Instance Metadata Service attested document. Unlike Azure MSI, this method does not require the VM to have a Managed Identity assigned, making it usable for a broader set of Azure workloads.

The agent fetches a PKCS#7-signed attested document from the IMDS endpoint; the Trust Domain Server verifies the document's cryptographic signature, validates a challenge nonce, and optionally queries the Azure Compute API for additional VM details.

Attributes available for SVID issuance

AttributeDescription
azure_imds.tenant.idAzure AD tenant ID (from server config)
azure_imds.subscription.idAzure subscription ID (from attested document)
azure_imds.vm.idUnique VM ID (from attested document)
azure_imds.vm.nameVM name (validated via Azure Compute API)
azure_imds.vmss.nameVM Scale Set name, if applicable
azure_imds.locationAzure region/location (via Compute API)
azure_imds.resource_groupResource group name
azure_imds.network_security_groupNetwork Security Group name(s)
azure_imds.virtual_networkVirtual Network name(s)
azure_imds.virtual_network_subnetSubnet name(s)
azure_imds.vm.tag.<tag_key>VM tag values filtered by attributeVMTagKeys

All attributes have the origin azure_imds.

Example SPIFFE ID template:

/azure/{{azure_imds.tenant.id}}/{{azure_imds.subscription.id}}/{{azure_imds.vm.name}}

Prerequisites

warning

Certificate pinning: The Trust Domain Server pins the Azure IMDS root certificate when verifying the PKCS#7 attested document. When Azure changes roots for the IMDS signing certificate chain, a new version of the Trust Domain Server must be deployed with the updated roots.

Additionally, the Trust Domain Server makes outbound connections to Microsoft's certificate distribution URL (determined from the leaf certificate) at runtime to retrieve intermediate CAs.

The Trust Domain Server requires:

  • Outbound network access to https://www.microsoft.com (to retrieve intermediate CA certificates)
  • Outbound network access to the Azure Resource Manager API (to resolve VM details)
  • An Azure Managed Identity assigned to the Trust Domain Server with the Azure RBAC Reader role on the relevant VM and VMSS resources

How to Deploy

Step 1 — Update cluster configuration

section: AgentAttestation
schema: v1
spec:
policies:
- name: azure_imds_policy
requiredAttestors:
- type: azure_imds
config:
tenants:
contoso.onmicrosoft.com:
tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
restrictToSubscriptions:
- "ssssssss-ssss-ssss-ssss-ssssssssssss"
attributeVMTagKeys:
- environment
- team

Multiple tenant domains can be configured:

tenants:
contoso.onmicrosoft.com:
tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
restrictToSubscriptions:
- "ssssssss-ssss-ssss-ssss-ssssssssssss"
fabrikam.onmicrosoft.com:
tenantID: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
attributeVMTagKeys:
- app

For Azure Government or other sovereign clouds:

cloudEnvironment: AzureUSGovernmentCloud
tenants:
contoso.onmicrosoft.us:
tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Apply it using spirlctl:

spirlctl config set cluster --id <cluster-id> attestation-policy.yaml

Or using Terraform:

resource "spirl_cluster_config" "agent_attestation" {
cluster_id = spirl_cluster.my_cluster.id
sections = {
AgentAttestation = <<-YAML
section: AgentAttestation
schema: v1
spec:
policies:
- name: azure_imds_policy
requiredAttestors:
- type: azure_imds
config:
tenants:
contoso.onmicrosoft.com:
tenantID: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
restrictToSubscriptions:
- "ssssssss-ssss-ssss-ssss-ssssssssssss"
YAML
}
}

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

Server Configuration Reference

FieldRequiredDefaultDescription
tenantsYesMap of Azure tenant domains (e.g., contoso.onmicrosoft.com) to tenant configuration.
tenants.<domain>.tenantIDYesAzure AD tenant ID for this domain.
tenants.<domain>.restrictToSubscriptionsNoAny subscription in the tenantList of allowed Azure subscription IDs.
tenants.<domain>.attributeVMTagKeysNoVM tag keys to include as attributes.
cloudEnvironmentNoAzurePublicCloudAzure cloud environment. Valid values: AzurePublicCloud, AzureChinaCloud, AzureUSGovernmentCloud, AzureGermanCloud.

Step 2 — Configure the Agent

agent:
auth:
clusterId: c-xxxxxx
attestors:
- type: azure_imds
config:
tenant_domain: "contoso.onmicrosoft.com"

Agent Configuration Reference

FieldRequiredDescription
tenant_domainYesAzure tenant domain. Must match a key in the server's tenants map.

Step 3 — Verify

Server logs — look for these in order:

  1. "Login started with multi-attestation support" — confirms the agent offered providedMethods: ["azure_imds"]
  2. "Authorization received and verified" — includes agentAttestationAttributes with the VM identity:
    {
    "msg": "Authorization received and verified",
    "agentAttestationAttributes": [
    "azure_imds:azure_imds.tenant.id=\"contoso.onmicrosoft.com\"",
    "azure_imds:azure_imds.vm.name=\"my-vm\"",
    "azure_imds:azure_imds.subscription.id=\"ssssssss-ssss-ssss-ssss-ssssssssssss\""
    ]
    }
  3. "Connected to agent" — session is fully established

Agent logs — enable debug logging to see "Sending Login" with attestors: ["azure_imds"]. At the default log level, "Connected to server" confirms the session is live.

Metrics — confirm proofs are succeeding:

spirl_attestation_signer.proof{attestor_type="azure_imds",outcome="success"}
spirl_attestation_agent.proof{attestor_type="azure_imds",outcome="success"}

Alert on outcome="failed" to detect PKCS#7 signature or nonce verification failures.

Common errors:

ErrorLikely cause
no cluster policy authorizes the provided attestorsAgent's azure_imds method doesn't match any policy — verify tenant_domain matches a key in the server's tenants map
Attestor rejected proof, policy failedPKCS#7 signature verification failed, subscription not in restrictToSubscriptions, or nonce mismatch
VM details not resolvingTrust Domain Server lacks Azure RBAC Reader access on VM or VMSS resources in the relevant subscriptions

Attestation Flow

  1. The agent sends its tenant_domain as an initial proof.
  2. The server validates the tenant domain and responds with a nonce challenge.
  3. The agent calls the IMDS /metadata/attested/document endpoint with the nonce, receiving a signed attested document. It also fetches the VM's resource ID from /metadata/instance as a hint.
  4. The server verifies the PKCS#7 signature, checks the nonce, enforces the subscription allowlist, and uses the resource ID to resolve additional VM details from the Azure Compute API.

Security Considerations

  • Certificate pinning: The Trust Domain Server pins the IMDS root certificate. Plan for server upgrades when Azure rotates these certificates.
  • Subscription restriction: Use restrictToSubscriptions to limit which Azure subscriptions can attest. Without this, any VM in the tenant can authenticate.
  • VM tag attributes: Only tags with keys in attributeVMTagKeys are emitted as attributes, preventing leakage of sensitive or irrelevant tags.
  • Nonce freshness: Each attestation uses a fresh nonce; replayed attested documents are rejected.

Troubleshooting

IMDS not reachable — The agent cannot reach 169.254.169.254. Verify the workload is running on an Azure VM or VMSS instance.

Tenant domain mismatch — If attestation fails with "tenant domain is not configured", verify that tenant_domain in the agent config exactly matches a key in the server's tenants map.

Subscription not allowed — Check that the VM's subscription ID is included in restrictToSubscriptions (or remove the restriction).

VM details not resolving — Ensure the Trust Domain Server has Azure credentials with read access to VM resources in the relevant subscriptions.

Cloud environment mismatch — If document verification fails with a SAN mismatch, ensure cloudEnvironment in the server config matches the actual Azure cloud where the VMs are running.