When building distributed applications in Azure, service-to-service authentication is a critical aspect that demands careful consideration. Let’s explore a common scenario and discover how Azure Workload Identity transforms the authentication landscape.
Imagine you’re architecting a solution with two services:
- A Provider API: A secure backend service protected by Microsoft Entra ID
- A Consumer API: A client service that needs to authenticate and communicate with the Provider API
Traditional Authentication Approaches
1. Client Credentials Flow
Historically, developers have relied on the OAuth2 client credentials flow, where the Consumer API uses a client ID and client secret to obtain access tokens. While this approach works, it comes with significant challenges:
The Secret Management Burden:
- Secure storage and distribution of secrets
- Regular secret rotation to maintain security
- Risk of secret exposure in configuration files and logs
- Operational overhead in managing secrets across environments
- Complex coordination required during secret rotation
2. Certificate-Based Authentication
Some teams opt for certificate-based authentication, but this too presents its own set of challenges:
- Managing certificate lifecycles
- Ensuring secure certificate storage
- Handling certificate distribution across services
- Coordinating certificate renewals
- Additional infrastructure for certificate management
3. Managed Service Identity (MSI)
While MSI solves some challenges, it has limitations in Kubernetes environments:
- Limited to VM-level identity
- Lacks granular control at the pod level
- Challenging to implement in multi-tenant clusters
- Complex rotation mechanisms in containerized environments
4. Service Principal Authentication
Traditional service principal authentication presents several challenges:
- Complex secret rotation procedures
- Difficult access management across multiple environments
- Limited audit capabilities
- Challenging secret distribution in distributed systems
Enter Azure Workload Identity
Azure Workload Identity introduces a revolutionary approach to service authentication, eliminating the need for secrets or certificates entirely. It leverages the power of Kubernetes service accounts to establish secure service identities.
How It Works
Let’s explore the detailed authentication flow:
sequenceDiagram
participant CP as Consumer API Pod
participant K as Kubelet
participant SA as Service Account
participant OIDC as AKS OIDC Provider
participant AAD as Azure AD
participant MI as Managed Identity
participant PP as Provider API Pod
rect rgb(240, 220, 200)
Note over CP,PP: Service-to-Service Call Preparation
CP->>K: 1. Request Pod Identity Token
Note right of CP: Pod Identity Details:<br/>- Namespace: default<br/>- ServiceAccount: consumer-sa<br/>- Client ID: {managed-identity-client-id}
K-->>CP: 2. Return Projected Token
Note right of K: Token Location:<br/>- Path: /var/run/secrets/tokens<br/>- File: sa-token<br/>- Permissions: 600
CP->>OIDC: 3. Exchange for OIDC Token
Note right of CP: Request Headers:<br/>- x-pod-name: consumer-pod<br/>- x-namespace: default<br/>- x-service-account: consumer-sa
OIDC-->>CP: 4. OIDC Token Response
Note right of OIDC: OIDC Claims:<br/>- iss: https://aks-oidc.azure.com<br/>- sub: system:serviceaccount:default:consumer-sa<br/>- aud: api://AzureADTokenExchange
CP->>AAD: 5. Get Azure AD Token
Note right of CP: Federation Request:<br/>- Grant Type: urn:ietf:params:oauth:grant-type:token-exchange<br/>- Requested Token Type: urn:ietf:params:oauth:token-type:access_token
AAD->>MI: 6. Validate Federation
MI-->>AAD: 7. Confirm Trust
AAD-->>CP: 8. Azure AD Token
Note right of AAD: Token Details:<br/>- Type: Bearer<br/>- Scope: api://provider-api<br/>- Lifetime: 1 hour
end
rect rgb(220, 240, 200)
Note over CP,PP: API Call Execution
CP->>PP: 9. API Request with Token
Note right of CP: Headers:<br/>- Authorization: Bearer {token}<br/>- x-correlation-id: {trace-id}<br/>- x-request-id: {uuid}<br/>- x-caller-chain: consumer-api
PP->>AAD: 10. Validate Token
Note right of PP: Validation:<br/>- Signature<br/>- Expiry<br/>- Audience<br/>- Scope<br/>- Claims
AAD-->>PP: 11. Token Valid
PP->>PP: 12. Authorization Check
Note right of PP: Verify:<br/>- Required Scopes<br/>- API Permissions<br/>- Rate Limits
PP-->>CP: 13. API Response
Note right of PP: Response Headers:<br/>- x-correlation-id: {same-trace-id}<br/>- x-request-duration: {ms}<br/>- x-rate-limit-remaining: {n}
end
rect rgb(220, 220, 240)
Note over CP,PP: Error Handling
alt Token Expired
PP-->>CP: 401 Unauthorized
Note right of PP: Error Response:<br/>- error: token_expired<br/>- error_description: The token has expired
CP->>OIDC: 14. Retry Token Acquisition
else Invalid Token
PP-->>CP: 401 Unauthorized
Note right of PP: Error Response:<br/>- error: invalid_token<br/>- error_description: Signature validation failed
else Rate Limited
PP-->>CP: 429 Too Many Requests
Note right of PP: Headers:<br/>- Retry-After: {seconds}<br/>- X-RateLimit-Reset: {timestamp}
end
endIdentity Federation
The magic begins with establishing a trust relationship between your Kubernetes cluster and Microsoft Entra ID. This federation connects your Kubernetes service accounts with Azure AD applications through a series of automated steps:
- Trust Establishment
- Federation configuration between AKS and Azure AD
- Service account to managed identity mapping
- Automated OIDC provider setup
- Runtime Authentication
- Your Consumer API runs in a pod with an associated Kubernetes service account
- The workload identity system automatically injects the necessary identity configuration
- When your Consumer API needs to access the Provider API, it uses the mounted service account token
- This token is exchanged for an Azure AD token through a secure, automated process
- No secrets or certificates are stored in your application or configuration
The Benefits
1. Superior Security Posture
- Elimination of stored secrets and certificates
- Automatic rotation of service account tokens
- Reduced risk of credential exposure
- Granular access control through Kubernetes RBAC
- Zero-trust security model implementation
2. Simplified Operations
- Zero secret management overhead
- Automated token lifecycle management
- Native integration with Kubernetes primitives
- Streamlined deployment process
- Reduced operational complexity
3. Enhanced Developer Experience
- Clean application code
- Automated authentication handling
- Built-in error handling
- Clear debugging paths
- Simplified local development
{
"doe": "a deer, a female deer",
"ray": "a drop of golden sun",
"pi": 3.14159,
"xmas": true,
"french-hens": 3,
"calling-birds": [
"huey",
"dewey",
"louie",
"fred"
],
"xmas-fifth-day": {
"calling-birds": "four",
"french-hens": 3,
"golden-rings": 5,
"partridges": {
"count": 1,
"location": "a pear tree"
},
"turtle-doves": "two"
}
}
