Secrets, Identity, Runtime

Workload Identity

How services prove who they are without static passwords, copied keys, or machine-bound trust.

Workload identity is the practice of assigning a verifiable, cryptographically-bound identity to each running service or job rather than relying on shared credentials. This allows the infrastructure itself to prove who a workload is, eliminating the need to distribute and manage long-lived secrets for service-to-service authentication.

Learning objectives

What you should be able to do after reading.
  • Explain how service accounts and workload identity reduce secret sprawl.
  • Describe how federation and OIDC let external systems obtain cloud access.
  • Recognize why least privilege and short-lived credentials matter together.

At a glance

Fast mental model before you dive in.
Identity source
  • Service accounts
  • Workload identity
  • Trust boundary
Trust bridge
  • Federation
  • OIDC in cloud
  • Token exchange
Security outcome
  • Short-lived credentials
  • Least privilege
  • Traceability

Why Workload Identity Matters

Traditional service authentication relies on shared secrets, a service is given a username and password, API key, or static token to authenticate to other services. These long-lived credentials must be stored somewhere accessible to the service, distributed to every environment where the service runs, and rotated manually. Each of these steps is a potential failure point that leads to credential exposure or credential sprawl.

Workload identity solves this by assigning a cryptographically verifiable identity to each workload based on its position in the infrastructure rather than on a secret it possesses. A pod in Kubernetes, a function in AWS Lambda, or a virtual machine in GCP can prove its identity to other services by presenting a token issued by the platform itself, not a stored password.

The security benefit is significant. There is no long-lived credential to steal, rotate, or accidentally commit to source control. The workload identity token is short-lived, tied to the specific workload, and verifiable by any service that trusts the issuing authority. Compromising the token only provides access until it expires, which may be as short as one hour.

Cloud Provider Workload Identities

Every major cloud provider offers workload identity. AWS IAM Roles for EC2, ECS, and Lambda allow workloads to assume a role and receive temporary STS credentials via the instance metadata service (IMDS) at http://169.254.169.254. Azure Managed Identities assign a service principal to a VM, container, or function, with token retrieval through the Azure IMDS. GCP Service Accounts bound to instances and Cloud Run services receive tokens through the GCP metadata server.

The mechanism is consistent across providers. The workload makes a local HTTP request to the metadata endpoint (accessible only from within the compute resource), receives a short-lived token, and presents that token to cloud APIs. The cloud provider validates the token against the workload's assigned identity and evaluates whether the identity's policies permit the requested action.

The attack surface of this model is the metadata endpoint itself. If an SSRF vulnerability in the application allows an attacker to make requests to the metadata service, they can steal the current credential token. Mitigations include requiring IMDSv2 (which uses a session-oriented protocol that is harder to exploit via SSRF), enforcing strict network policies, and using short token lifetimes.

Kubernetes Workload Identity

Kubernetes issues a ServiceAccount token to every pod at startup, mounted at a well-known path. Modern Kubernetes versions support projected service account tokens with configurable audiences and TTLs, replacing the older tokens that were long-lived and had no audience restriction. These tokens allow pods to authenticate to the Kubernetes API server itself.

To authenticate to external cloud services, Kubernetes clusters use workload identity federation. AWS EKS supports IAM Roles for Service Accounts (IRSA), which maps a Kubernetes ServiceAccount to an AWS IAM role. The pod's projected token is exchanged for temporary AWS STS credentials via the AWS STS AssumeRoleWithWebIdentity API. GCP GKE and Azure AKS have equivalent mechanisms.

Using workload identity correctly in Kubernetes requires binding each deployment to a dedicated ServiceAccount, binding that ServiceAccount to an IAM role with only the permissions that workload needs, and not using the default ServiceAccount (which is shared by all pods in the namespace). Many security incidents involving Kubernetes workloads trace back to over-privileged default ServiceAccounts.

SPIFFE and SPIRE

SPIFFE (Secure Production Identity Framework for Everyone) is an open standard for workload identity that works across clouds, on-premises, and hybrid environments. It defines a URI-based identity format (SPIFFE ID) and two document types for carrying it. X.509 SVIDs (certificates) and JWT SVIDs (JSON Web Tokens). Any service that understands SPIFFE can verify the identity of another SPIFFE-enabled workload regardless of where it runs.

SPIRE (SPIFFE Runtime Environment) is the reference implementation of the SPIFFE standard. It consists of a SPIRE Server (which acts as a certificate authority and manages identity registrations) and SPIRE Agents (which run on each node and attest workload identity using node-level selectors like Kubernetes pod labels or AWS instance metadata). Agents deliver SVIDs to workloads through a Unix domain socket.

The value of SPIFFE/SPIRE is uniform workload identity across heterogeneous environments. A workload running in Kubernetes on AWS can present the same SPIFFE identity to a service running on bare metal in a data center, enabling mTLS authentication without requiring any shared secrets or pre-provisioned certificates. This makes SPIFFE particularly valuable in multi-cloud and hybrid architectures.

Service Mesh Identity

Service meshes like Istio and Linkerd use mutual TLS (mTLS) to authenticate workloads to each other at the network layer. Each sidecar proxy is issued a certificate by the mesh's certificate authority, typically a SPIFFE X.509 SVID. When two services communicate, their sidecars perform a mutual TLS handshake, verifying each other's certificates before allowing the connection to proceed.

The certificates are rotated automatically by the mesh control plane, typically on a schedule of hours or days, without any application-level involvement. This means service-to-service authentication is continuous and based on short-lived credentials without any developer needing to manage certificate files or secret rotation.

Service mesh identity enables fine-grained authorization policies. Services can declare exactly which other services are permitted to call them by identity, not by network address. This is far more robust than network-based controls because it remains correct even if network segmentation is misconfigured. Authorization is verified at the proxy level before the request ever reaches the application.

Signals to watch for

Patterns worth investigating further.
  • Applications rely on manually copied access keys or shared service passwords.
  • Cloud roles are broader than the workload needs to complete its job.
  • A compromised host or pipeline can reuse the same identity far beyond its intended scope.

DEEP DIVE

Service Accounts

A service account is a non-human identity used by an application, service, or automated process to authenticate to other services and APIs. Unlike user accounts, service accounts are managed programmatically, are associated with a workload rather than a person, and in modern systems do not require a stored password. They represent the workload's identity in access control decisions.

In traditional environments, service accounts were associated with long-lived passwords or API keys stored in configuration files or environment variables. This created significant security risk. The credentials were static, often shared across multiple services and environments, difficult to rotate without causing outages, and easily forgotten in source code. A single compromised service account password could persist for years.

In cloud and Kubernetes environments, service accounts have evolved to be passwordless. Cloud-managed service accounts (AWS IAM roles, GCP service accounts, Azure Managed Identities) work through platform-native mechanisms. The cloud platform attests that a compute resource is running with a particular identity and automatically provides short-lived credentials when the workload requests them. No password is stored, distributed, or rotated manually.

The most common mistake with service accounts is over-privileging them. A service account for a read-only reporting service should not have write access to the production database. A service account for an image build pipeline should not have permission to modify IAM policies. Following least privilege strictly means creating a dedicated service account for each workload with precisely the permissions that workload requires and nothing more. Over time, unused permissions accumulate on service accounts, regular permission audits remove this drift.

Workload Identity

Workload identity is the concept of assigning a unique, verifiable, cryptographically-backed identity to each running workload (application, service, container, or job), rather than to a person. This identity is derived from properties of the workload's execution environment and attested by a trusted authority such as the cloud provider or the Kubernetes control plane. The workload does not possess a secret to prove its identity, instead, the platform attests the identity on its behalf.

The key distinction from traditional service accounts is that workload identity does not rely on a secret the workload holds. A pod running in a specific Kubernetes namespace with a specific ServiceAccount gets an identity because the Kubernetes API server attests that fact and issues a signed token. An EC2 instance in a specific IAM role gets credentials because the AWS IMDS provides them based on the instance's configured role. No credential is stored, the identity is a property of the deployment.

Workload identity tokens follow a common pattern. The trusted authority issues a signed JSON Web Token (JWT) with claims describing the workload (the namespace, service account, pod name, or cloud instance ID). The workload presents this token to other services, which validate the signature using the authority's published public keys. Because the token is short-lived and bound to specific claims, it cannot be reused by an attacker after expiry.

Workload identity is foundational for zero-trust architectures. When every service can cryptographically prove its identity, access control decisions can be based on 'which service is making this call' rather than 'which network address is the call coming from.' This enables secure service-to-service communication even in flat, shared networks where network-based segmentation is impractical.

Federation

Identity federation is the mechanism that allows a workload to present an identity from one system (such as Kubernetes or GitHub Actions) and exchange it for credentials in another system (such as AWS or GCP), without requiring the source system to store any long-lived credentials from the target system. Federation is built on mutual trust. The target system trusts the source system's identity assertions, validated through published public keys.

The most common federation pattern in DevSecOps is CI/CD pipeline to cloud provider. A GitHub Actions workflow authenticates to AWS using OIDC federation without storing any AWS credentials in GitHub. The workflow requests a GitHub-issued OIDC token, presents it to AWS STS, and receives temporary AWS credentials valid for the duration of the job. AWS validates the token by fetching GitHub's JWKS endpoint (the published public keys) and verifying the token's signature.

Federation is built on open standards. OIDC (OpenID Connect) and SAML are the two dominant federation protocols. OIDC is preferred for modern workload identity because it uses compact JWTs, is lighter weight than SAML, and is natively supported by all major cloud providers and many CI/CD platforms. OIDC tokens carry structured claims (key-value pairs in the token payload) that the target system uses to make authorization decisions.

A common mistake is setting overly broad trust conditions in federation policies. When configuring GitHub OIDC federation with AWS, teams should restrict the trust to specific repositories, specific branches (especially the main or release branch, not all branches), and specific environments. A policy that trusts any workflow from any repository in a GitHub organization means any contributor to any repository in that organization can obtain cloud credentials.

OIDC in Cloud

OpenID Connect (OIDC) is an identity layer built on top of OAuth 2.0. In the context of cloud workload identity, OIDC allows workloads to authenticate to cloud services by presenting a signed JWT issued by a trusted identity provider (the Kubernetes API server, GitHub Actions, CircleCI, GitLab, etc.) and exchanging it for cloud-native temporary credentials.

The exchange works as follows the workload requests a token from its local OIDC provider (for example, a Kubernetes pod requests a projected service account token from the Kubernetes API server), presents this token to the cloud provider's Security Token Service (STS), and the cloud provider validates the token's signature using the OIDC provider's published public keys (the JWKS endpoint). If valid, the cloud provider issues temporary credentials associated with the mapped IAM role.

OIDC tokens carry structured claims that describe the workload. A Kubernetes pod token carries claims for the namespace, service account name, pod name, and cluster. A GitHub Actions token carries claims for the repository, branch, workflow name, and environment. Cloud IAM policies use these claims as conditions in the trust policy stating 'trust tokens from this OIDC provider where the sub claim matches this service account in this namespace.'

The security properties of OIDC federation are strong because tokens are short-lived (typically 15 minutes to one hour), cryptographically signed by a known key, and bound to specific structured claims about the workload. There is no persistent credential to steal and reuse indefinitely. If a token is intercepted, it expires quickly. If the claims in a token are forged, the signature verification against the published keys fails.

Short-Lived Credentials

Short-lived credentials are authentication tokens or secrets that automatically expire after a brief period, typically minutes to hours. By limiting credential lifetime, the organization limits the damage from credential theft, an attacker who obtains a credential that expires in 15 minutes has a very narrow window to exploit it. This is a fundamental improvement over long-lived API keys or passwords that may remain valid for months or years.

AWS STS, GCP's OAuth token service, and Azure AD all generate temporary credentials with configurable expiration times. Applications that use these services never hold a long-lived credential, they request fresh temporary credentials when needed, using their workload identity to authenticate. AWS SDK credential providers handle this automatically. They cache credentials and proactively refresh them before expiry without any application code involvement.

The operational challenge with short-lived credentials is refresh handling. Applications must be designed to obtain new credentials before the current ones expire. Most cloud SDKs handle this transparently for cloud API calls, but applications that cache credentials in application-level caches (such as database connection pools) may hold expired credentials. Connection pool refresh strategies and credential expiry awareness in application code must be considered.

A common anti-pattern is creating 'long-lived tokens' by setting artificially long expiration times on what is technically a short-lived credential mechanism. Teams sometimes do this to avoid handling token refresh logic, but this defeats the purpose entirely. The goal is credentials that expire in minutes to hours. Credentials set to expire in 365 days are functionally equivalent to permanent credentials from a security risk perspective.

Least Privilege

The principle of least privilege states that every identity should have access to only the minimum set of permissions required to perform its intended function. Applied to workload identity, this means each service gets its own identity with exactly the permissions it needs, scoped to exactly the resources it needs, for the duration it needs them. Over-privileged workload identities are one of the most common cloud security misconfigurations.

Least privilege in cloud IAM is achieved through fine-grained policy definitions. Instead of granting a service the Administrator role or broad access to all resources in an account, a properly privileged service account might have permission to read objects from one specific S3 bucket prefix, write to one specific DynamoDB table, and publish to one specific SNS topic. This level of precision requires understanding the service's actual data access requirements.

Privilege analysis tools help teams identify and close the gap between permissions granted and permissions actually used. AWS IAM Access Analyzer with its last-accessed information, GCP Policy Analyzer, and similar tools analyze CloudTrail or Audit Logs to determine which permissions a role actually exercises in practice. This makes it practical to tighten existing over-privileged roles without manually auditing every permission by examining call patterns.

A common mistake is granting wildcard permissions because it is easier than determining the exact requirements. Writing 'Action: *' or 'Resource: *' in an IAM policy is a significant red flag. Another common mistake is granting permissions at the account level when they should be scoped to specific resources (using resource ARNs or equivalent in other providers). Both patterns create far more access than any single workload should ever need.