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 end
Identity 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"
}
}