All skills
lukemurraynz avatar

/identity-managed-identity

@2cc2455

Azure service-to-service (workload) identity: managed identity, user-assigned identity, Azure RBAC, passwordless Azure SDK connections, AKS workload identity, Azure DevOps Workload Identity Federation, GitHub Actions OIDC to Azure, and federated credential troubleshooting. Use when the user says "use managed identity", "passwordless Azure auth", "remove connection strings or keys", "federated credential", "workload identity federation", "GitHub Actions OIDC to Azure", "AKS workload identity", or "DefaultAzureCredential". Do NOT use for human sign-in, MFA, Conditional Access, or B2C / External ID consumer login ; use a human-identity (Entra) skill instead.

Use this Skill: https://skilld.dev/gh/lukemurraynz/hve-agent-skills/identity-managed-identity

This session only. Nothing lands on disk.

referencesaks-workload-identity.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

AKS Microsoft Entra Workload ID

For new AKS workloads, use Microsoft Entra Workload ID. Do not use the deprecated Microsoft Entra pod-managed identity for new workloads.

Required components

  1. AKS OIDC issuer enabled.
  2. User-assigned managed identity for the workload.
  3. Federated identity credential on the managed identity.
  4. Kubernetes service account annotated with the managed identity client ID.
  5. Pod uses the annotated service account.
  6. Azure SDK uses WorkloadIdentityCredential or a constrained credential chain that includes workload identity.

Federated credential

oidc_issuer=$(az aks show \
  --resource-group "$aks_resource_group" \
  --name "$aks_name" \
  --query "oidcIssuerProfile.issuerUrl" -o tsv)

az identity federated-credential create \
  --name "fic-${namespace}-${service_account_name}" \
  --identity-name "$identity_name" \
  --resource-group "$identity_resource_group" \
  --issuer "$oidc_issuer" \
  --subject "system:serviceaccount:${namespace}:${service_account_name}" \
  --audiences "api://AzureADTokenExchange"

Kubernetes service account

apiVersion: v1
kind: ServiceAccount
metadata:
  name: api
  namespace: production
  annotations:
    azure.workload.identity/client-id: "<managed-identity-client-id>"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
  namespace: production
spec:
  template:
    metadata:
      labels:
        azure.workload.identity/use: "true"
    spec:
      serviceAccountName: api
      containers:
        - name: api
          image: <image>

Bicep federated credential shape

resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' existing = {
  name: identity_name
}

resource federated_credential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2024-11-30' = {
  name: 'fic-${namespace}-${service_account_name}'
  parent: identity
  properties: {
    issuer: oidc_issuer_url
    subject: 'system:serviceaccount:${namespace}:${service_account_name}'
    audiences: [
      'api://AzureADTokenExchange'
    ]
  }
}

Code

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

var credential = new WorkloadIdentityCredential();
var client = new SecretClient(new Uri("https://<vault>.vault.azure.net"), credential);

Setup ordering (silent-failure trap)

Workload Identity token injection happens at pod admission via a mutating webhook. The order of operations matters, getting it wrong produces pods with no AZURE_CLIENT_ID / AZURE_FEDERATED_TOKEN_FILE env vars and they silently fall back to the kubelet identity (or fail with 403). Correct sequence:

  1. Enable OIDC issuer on the cluster (--enable-oidc-issuer).
  2. Enable Workload Identity on the cluster (--enable-workload-identity).
  3. Create the federated identity credential with subject system:serviceaccount:<ns>:<sa> matching the EXACT namespace + service-account name.
  4. Annotate the ServiceAccount (azure.workload.identity/client-id) AND add the pod template label (azure.workload.identity/use: "true").
  5. Only then start or restart the pods, the webhook injects the projected token volume and env vars at admission.

If pods are already running before step 4, they will NOT pick up the annotation retroactively. You must restart them (kubectl rollout restart deployment/<d> -n <ns>). This is the most common silent failure when retrofitting Workload Identity onto an already-deployed workload, including operator-installed platforms like Drasi.

Common failures

Failure Likely cause Fix
Token exchange fails Issuer, subject, or audience mismatch Compare FIC values to AKS OIDC issuer and service account
SDK uses managed identity IMDS path Old SDK or wrong credential Update SDK and use WorkloadIdentityCredential
Pod has no injected token Missing label, service account annotation, or webhook Check workload identity webhook and pod labels
Azure 403 Forbidden Federation works but target role missing Assign target data-plane role to managed identity principal
Bicep error: principalId cannot be used in role assignment name principalId is a runtime value, not available at deployment start Use identity.id (known at plan time) in guid() for the role assignment name: guid(resource.id, identity.id, roleDefinitionId). Use identity.properties.principalId only in properties.principalId.
PostgreSQL "access token has invalid format" Plain password sent to a server requiring Entra auth, or managed identity not registered as a PostgreSQL Entra admin Add the managed identity as a PostgreSQL Flexible Server Entra admin: az postgres flexible-server microsoft-entra-admin create --resource-group <rg> --server-name <server> --type ServicePrincipal --object-id <principal-id> --display-name <display-name>. Set user in the source to the identity's display name; omit password.
Drasi for Kubernetes source pods have no AZURE_CLIENT_ID env var Wrong service account annotated. Drasi creates a per-source SA named source.<source-name> (e.g. source.cosmos-matches), NOT default kubectl annotate sa source.<source-name> -n <drasi-namespace> azure.workload.identity/client-id=<clientId> --overwrite and kubectl label sa source.<source-name> -n <drasi-namespace> azure.workload.identity/use=true --overwrite. The federated credential subject must be system:serviceaccount:<drasi-namespace>:source.<source-name>. The SA does not exist until after drasi apply creates the source — annotate after apply, then restart source pods. Existing pods need a restart to pick up the change.
Drasi EventHub source: ResourceNotFound for hub name Drasi uses Cypher node labels as Event Hub entity names The Event Hub name MUST match the label in MATCH (m:Label). If queries use MATCH (m:Match), the hub must be named Match, not match-events.
Drasi drasi init points at wrong cluster Stale environment config from a previous cluster Run drasi env kube to register the current kubectl context as the Drasi environment before drasi init.
AKS Bicep kubelet identity AcrPull role fails Role assignment targets wrong identity property Use aksCluster.properties.identityProfile.kubeletIdentity.objectId for the role assignment principalId, NOT aksCluster.identity.principalId (which is the control-plane identity, not the kubelet).

Source: SKILL.md on GitHub

No alerts8d3 checks · Risk SAFE
  • Gen Agent Trust Hub8d

    The skill is a professional toolset for managing Azure identities and promotes security best practices such as passwordless authentication. It includes utility scripts for diagnostic purposes. A low-risk surface for indirect prompt injection exists due to the processing of user-supplied identifiers into shell and cloud management commands.

  • Socket8d

    No alerts

  • Snyk8d

    Risk: LOW · No issues

Signed by skilld at 2cc2455. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated last month
cowork
{
  "category": "automation"
}
metadata
{
  "last_verified": "2026-08-25"
}
Other metadata
compatibility
Azure CLI, Bicep or Terraform, Azure Identity SDK, Microsoft Entra workload identity federation

README badge

README badge for lukemurraynz/hve-agent-skills/identity-managed-identity