Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français
Lire en français

Machine identity and workload identity

By updated

Improve this page

When service A needs to call service B, the traditional method is to share a secret: password, token, API key. This secret gets copied, leaks and lasts too long. Machine identity, or workload identity, offers something else: the service proves who it is with a short-lived cryptographic document, issued by an authority the recipient knows how to verify. This lesson is for the DevOps engineer who wants to know when this approach replaces a secret, and when it cannot.

The mechanisms were measured. On SPIRE 1.15.3, an X509-SVID lasts 1 hour and a JWT-SVID 5 minutes. On a kind cluster (Kubernetes 1.37), a projected ServiceAccount token carries the sts.amazonaws.com audience, lasts one hour, and is invalidated as soon as its pod disappears. On the cloud side, the GKE documentation no longer requires the ServiceAccount annotation, and AKS demands a pod label that many tutorials forget.

What you will learn

  • Distinguish a machine identity from a shared secret
  • Separate the two families: internal identity (SPIFFE/SPIRE) and cloud federation (OIDC)
  • Decode a projected ServiceAccount token and what the cloud checks in it
  • Configure federation on GKE, EKS and AKS with each cloud's real prerequisites
  • Choose between machine identity, dynamic secret and static secret depending on the target system
  • Link this approach to requirement SOCLE-SEC-GEN-5 (in French) on short-lived identities

The shared secret problem

Before looking at solutions, you need to see what breaks in the usual model. The shared secret is not only a confidentiality problem: it also makes traceability impossible and rotation costly. These three flaws go together, and it is together that they justify changing approach.

Classic scenario

The payment-api service needs to call user-api to validate a user. The traditional approach puts a common API key in the configuration on both sides. The table after the file sums up what this shared key costs in security and operations.

# ❌ payment-api/config.yaml
user_api:
url: https://user-api.internal
api_key: "shared-secret-between-services"
ProblemConsequence
Shared secretIf one service is compromised, so is the other
Copied everywhereConfigurations, environment variables, backups
No attributionImpossible to know which service made which request
Painful rotationChanging the secret means redeploying every service

The alternative: proving your identity

Instead of sharing a secret, each service proves who it is with a cryptographic document, an X.509 certificate or a signed JWT. The target service checks three things, in this order. The third one is about authorisation, distinct from identity, as a later section shows.

  1. The document is valid: signed by a trusted authority, not expired.
  2. The identity matches the expected service.
  3. The service has the right to call this API.

There is no longer a long-lived shared application secret. Each service has its own identity, short-lived and verifiable. It is not "impossible to copy": a stolen token remains usable until its expiry, hence the importance of durations in minutes or hours.

What is a machine identity

The term covers a precise reality, not to be confused with a simple service account with a password. A machine identity is defined by what it contains, by what sets it apart from a secret, and by the mechanism that issues it.

Definition

A machine identity (or workload identity) is a cryptographic document that identifies a workload (pod, VM, service, function) in a verifiable way. It is not a password: it is the result of an attestation, "this workload really is who it claims to be, and here is the signed proof".

Components of a machine identity

Four elements are always present, whatever the technology. The most often neglected is the last one: without attestation, a workload could simply claim an identity that does not belong to it, and the whole edifice collapses.

ComponentRole
Unique identifierName of the workload (for instance spiffe://example.org/payment-api)
Cryptographic documentX.509 certificate or signed JWT
Short lifetimeMinutes or hours, not months
AttestationProof that the workload really runs where it claims to

Difference from a secret

The distinction is fundamental. A shared secret is a value that anyone who holds it can present, anywhere, for months. A machine identity is issued for an attested workload, carries its name and expires quickly.

AspectShared secretMachine identity
NatureSensitive value to protectSigned, verifiable document
IssuanceCreated once, copied by handIssued for an attested workload
DurationOften longShort (1 h for an X509-SVID by default)
AttributionDifficultDirect, one identity per workload
End of lifeManual revocation, often incompleteAutomatic expiry, renewal

Two families of workload identity

When talking about machine identity, you need to distinguish two sub-models that share the same principle but meet different needs. The diagram puts them side by side: on the right, services that authenticate with each other; on the left, a pod that accesses a cloud API, with the cloud IAM in red at the centre of the decision.

Two families of workload identity. Internal identity: the SPIRE Server issues X.509-SVIDs to services A and B, which communicate over mTLS. Cloud federation: the pod presents a JWT token to the cloud IAM, which checks the signature with the cluster's OIDC issuer, returns temporary credentials, and the pod accesses the cloud API.Cloud federationJWT tokenchecks the signaturetemporary credentialsauthorised accessPod(ServiceAccount)Cloud IAM(AWS, GCP, Azure)Cluster OIDCissuerCloud API(S3, GCS)Internal identity (M2M)SVIDSVIDmTLSSPIRE Server(authority)Service A(X.509-SVID)Service B(X.509-SVID)
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

Internal identity (M2M)

The identity is used to authenticate services with each other, inside an infrastructure, what is called M2M (machine to machine). This is the domain of SPIFFE/SPIRE and service meshes (Istio, Linkerd, Cilium). X.509 certificates or JWTs are signed by an authority specific to the organisation, and are used for mTLS (mutual TLS, where both sides present a certificate).

This family is independent of the cloud provider. On the other hand, it requires a local agent (SPIRE Agent) or a sidecar proxy (Envoy) to deliver and use the identity.

Identity federation to the cloud

The identity is used to access cloud services (S3, GCS, Azure Key Vault) from a workload, without a static key. This is the domain of Workload Identity Federation for GKE, IRSA and EKS Pod Identity at AWS, and Microsoft Entra Workload ID on AKS.

The most widespread principle relies on the cluster's OIDC issuer: the cloud checks the pod's token and returns temporary credentials. Each cloud has its own prerequisites, and AWS offers a variant, EKS Pod Identity, that does without an OIDC provider.

Identity and authorisation: two separate questions

Identity answers "who is this workload?", never "what can it do?". They are two separate mechanisms, configured in two places. The table puts them side by side with their usual tools.

QuestionMechanismExamples
Who am I?Identity (attestation)SPIFFE SVID, OIDC token
What can I do?Authorisation (policy)IAM policies, Istio AuthorizationPolicy, Vault policies

A workload can have a valid identity and be refused access if the policy does not allow it. The reverse is more dangerous: an overly broad policy, of the "any authenticated workload" kind, makes the identity useless. Each layer therefore carries its own policy:

  • Service mesh: AuthorizationPolicy (Istio) or identity-based network policy (Cilium)
  • Vault or OpenBao: policies tied to the SPIFFE ID or the Kubernetes role
  • Cloud IAM: role associated with the ServiceAccount (GKE, IRSA, EKS Pod Identity, AKS)
  • Application: check of the JWT's sub or the certificate's SAN

How attestation works

The attestation mechanism varies by family. SPIRE itself attests the node and then the workload; cloud federation relies on the token that Kubernetes has already signed. Both flows are detailed below, with what the measurement shows.

Attestation with SPIRE

SPIRE works in two phases: it first attests the node, then the workload running on it. The diagram follows the exchange between the workload, the agent and the server, up to the delivery of an automatically renewed SVID.

SPIRE attestation: the agent attests the node to the server (join token, instance document, TPM) and receives its own SVID; the workload requests an identity through the Workload API on a Unix socket; the agent collects the selectors (uid, namespace, ServiceAccount) and matches them against the registered entries; the server signs the SVID, which the agent delivers to the workload: a one-hour X509-SVID or a five-minute JWT-SVID, renewed before expiry.SPIRE ServerSPIRE Agent(on the node)WorkloadCollects the selectors(uid, namespace, ServiceAccount)Automatic renewal before expiry1. Node attestation(join token, instance document, TPM)Agent SVID2. Identity request(Workload API, Unix socket)Matches against registered entriesSVID signed for this workloadX509-SVID (1 h) or JWT-SVID (5 min)
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %
  1. Node attestation

    The SPIRE Agent proves its node's identity to the SPIRE Server. Depending on the environment, the proof is a cloud instance identity document, a TPM certificate, a Kubernetes ServiceAccount token, or a single-use join token.

  2. Workload attestation

    When a process calls the Workload API (a Unix socket), the agent identifies the caller by its PID and derives selectors from it: unix:uid, Kubernetes namespace and ServiceAccount, labels. These selectors are matched against the server's registration entries.

  3. SVID issuance

    If an entry matches, the workload receives an SVID. Measured on SPIRE 1.15.3, with a unix:uid:0 entry: an X509-SVID valid for 1 hour (default_x509_svid_ttl) and a JWT-SVID of 5 minutes (default_jwt_svid_ttl), renewed automatically.

$ spire-agent api fetch x509 -socketPath /tmp/agent.sock
SPIFFE ID: spiffe://example.org/payment-api
SVID Valid After: 2026-10-01 13:44:19 +0000 UTC
SVID Valid Until: 2026-10-01 14:44:29 +0000 UTC
CA #1 Valid Until: 2026-10-02 13:44:21 +0000 UTC

The server's intermediate CA lasts 24 hours by default (ca_ttl): even the signing authority turns over quickly. It is this chain of short durations, more than the encryption, that limits the value of a stolen SVID.

Cloud flow: OIDC federation

Cloud solutions follow a different flow, based on the cluster's OIDC issuer. The diagram shows the four steps: the kubelet projects a token into the pod, the pod exchanges it with the cloud IAM, which checks the signature with the issuer's public keys, then returns temporary credentials.

OIDC federation for a pod: the kubelet projects a JWT with a dedicated audience valid for one hour; the pod exchanges it with the cloud IAM (AWS STS, Google, Entra), which reads the public keys of the cluster's OIDC issuer, checks signature, audience, subject and trust relationship, then returns temporary credentials; the pod calls the cloud service within the limits of the IAM policy.Cloud serviceOIDC issuerCloud IAMPodKubeletChecks signature,aud, sub and trust1. Projects a JWT(dedicated aud, 1 h, renewed)2. Exchanges the JWT(AWS STS, Google, Entra)Reads the publickeys (JWKS)3. Temporary credentials4. API calls allowedby the IAM policy
Source · SVG
Esc to close, + and − to zoom, scroll to move around. 100 %

What the projected token contains: measured

The projected token is a JWT signed by the cluster API. To see it, a payment-api pod mounts a projected volume serviceAccountToken with a dedicated audience, sts.amazonaws.com, and a duration of 3600 seconds. Measured on kind 0.33 with Kubernetes 1.37, by decoding the middle part of the token:

# Pod excerpt: projected volume with audience and duration
volumes:
- name: cloud-token
projected:
sources:
- serviceAccountToken:
path: token
audience: sts.amazonaws.com
expirationSeconds: 3600
{
"aud": ["sts.amazonaws.com"],
"iss": "https://kubernetes.default.svc.cluster.local",
"sub": "system:serviceaccount:payment:payment-api",
"exp": 1790865974,
"iat": 1790862374,
"kubernetes.io": {
"namespace": "payment",
"pod": { "name": "payment-api", "uid": "22baa468-7e25-4636-9220-51caa006d630" },
"serviceaccount": { "name": "payment-api", "uid": "960d1fb7-2b94-4d0f-bdee-fa36a5f4ff50" }
}
}

Three fields make federation secure. The audience (aud) prevents the token from being replayed against another service, the subject (sub) designates the namespace and the ServiceAccount precisely, and the gap exp - iat is 3600 seconds. The cloud checks the signature with the keys published at /.well-known/openid-configuration then /openid/v1/jwks.

Two measurements complete the picture. A duration under 10 minutes is rejected by the API: expirationSeconds: 300 gives may not specify a duration less than 10 minutes. And the default token mounted in the same pod (Kubernetes API audience) showed one year of validity, an effect of the API server's --service-account-extend-token-expiration option, enabled by default for compatibility. Hence the value of a dedicated token, short-lived and with a precise audience, for any federation.

SPIFFE: a standard for workload identity

SPIFFE (Secure Production Identity Framework For Everyone) is a CNCF standard, where the project and its SPIRE implementation have reached graduated status. It defines the format of identities and how they are delivered, independently of the cloud and the orchestrator.

SPIFFE ID

The SPIFFE ID is a unique identifier per workload, written as a URI. Its first part, the trust domain, designates the authority that guarantees the identity; the path that follows describes the workload according to a convention you choose, often modelled on the Kubernetes namespace and ServiceAccount.

spiffe://trust-domain/path/to/workload
# Examples
spiffe://example.org/payment-api
spiffe://example.org/ns/production/sa/frontend
spiffe://mycompany.com/region/eu-west-3/service/checkout

SVID (SPIFFE Verifiable Identity Document)

The SVID is the cryptographic document that carries the SPIFFE ID and proves it belongs to this workload. It comes in two formats, and this is no detail: the format determines what the target system must be able to verify.

FormatUse
X.509-SVIDCertificate for mTLS between services
JWT-SVIDToken for APIs and proxies that do not handle mTLS

SPIRE

SPIRE (SPIFFE Runtime Environment) is the reference implementation of the SPIFFE APIs. It consists of three elements, the first of which becomes a critical infrastructure component: without it, no SVID is issued or renewed any more.

ComponentRole
SPIRE ServerCentral authority, signs SVIDs, checks attestations
SPIRE AgentRuns on each node, attests workloads, delivers SVIDs
Workload APIUnix socket through which workloads retrieve their SVIDs

The SPIRE Server is operated with the requirements of a central service: high availability, shared database, monitoring of attestation failures. An outage does not cut everything immediately, the agents keep their SVIDs in cache; but without renewal, these one-hour SVIDs expire one after another.

Cloud Workload Identity

The three major clouds offer their own identity federation between Kubernetes and their IAM. The principle is common, but the prerequisites differ, and that is where deployments fail: an annotation alone, without the configuration on the cluster and IAM side, has no effect.

Workload Identity Federation for GKE

On GKE, federation is enabled at cluster level with an identity pool, then IAM roles are granted directly to the Kubernetes ServiceAccount through a principal identifier. This is the best practice stated by the Google documentation, which then requires no annotation.

Terminal window
# Enable federation on the cluster
gcloud container clusters update CLUSTER_NAME \
--location=LOCATION \
--workload-pool=PROJECT_ID.svc.id.goog
# Grant a role directly to the Kubernetes ServiceAccount payment/payment-api
gcloud projects add-iam-policy-binding projects/PROJECT_ID \
--role=roles/storage.objectViewer \
--member=principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/payment/sa/payment-api

The older method remains possible when a Google API cannot yet recognise this principal: you link the Kubernetes ServiceAccount to an IAM service account, which requires both a policy granting roles/iam.workloadIdentityUser and the iam.gke.io/gcp-service-account annotation on the ServiceAccount.

AWS: IRSA or EKS Pod Identity

AWS offers two mechanisms. IRSA (IAM Roles for Service Accounts) requires an IAM OIDC provider for the cluster, a trust relationship on the role with a StringEquals condition on the token's sub, and the ServiceAccount annotation. The AWS account has 12 digits:

apiVersion: v1
kind: ServiceAccount
metadata:
name: payment-api
namespace: payment
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/payment-api

EKS Pod Identity is the alternative the AWS documentation presents as simpler: no OIDC provider, an association declared in EKS between a role and a ServiceAccount, an agent (EKS Pod Identity Agent) as a DaemonSet, and a single trusted principal, pods.eks.amazonaws.com, for all clusters. It only works on EKS, with Linux EC2 nodes: neither Fargate nor EKS Anywhere.

Microsoft Entra Workload ID on AKS

On AKS Standard, you need to enable the OIDC issuer and Workload ID on the cluster, then create a federated identity credential that links the ServiceAccount to the managed identity. On the Kubernetes side, two elements are needed, and the second is the one people forget:

apiVersion: v1
kind: ServiceAccount
metadata:
name: payment-api
namespace: payment
annotations:
azure.workload.identity/client-id: 00000000-0000-0000-0000-000000000000
---
# In the pod template: without this label, the webhook injects nothing
metadata:
labels:
azure.workload.identity/use: "true"

The Microsoft documentation is explicit: only pods carrying the azure.workload.identity/use: "true" label are modified by the webhook, which injects the projected token and the AZURE_FEDERATED_TOKEN_FILE variable. The Kubernetes token lasts 3600 seconds by default, adjustable from 3600 to 86,400. On AKS Automatic, the OIDC issuer and Workload ID are preconfigured.

Identity is not enough: you need an integration point

Having an identity is useless if the workload does not know how to use it. The identity must be consumed by an integration layer, and the choice of this layer often decides the effort: changing the code, or entrusting the identity to the infrastructure.

Integration pointHow it works
Envoy sidecar proxyThe proxy handles mTLS and presents the certificate
Service mesh (Istio, Linkerd, Cilium)Identity injected through a sidecar proxy or eBPF
Cloud SDK (AWS SDK, Google Cloud, Azure Identity)The SDK detects the federated credentials
Vault agent or CSI driverExchanges the identity for a dynamic secret
Application libraryThe application loads the certificate or JWT itself

If your applications do not handle mTLS, start with a proxy or a service mesh: the identity is managed without changing the code. Recent cloud SDKs read federated credentials on their own; an SDK that is too old keeps looking for a static key.

You do not remove all initial trust

Machine identity removes the long-lived shared application secret. It does not remove all initial trust: a chain of elements remains necessary, and each becomes an attack surface to protect, audit and maintain.

Element of trustRole
Trust anchor (root CA)Signs the SPIFFE certificates
Trust bundleDistributed to workloads to verify SVIDs
OIDC issuerPublishes the keys the cloud uses to verify tokens
Federation configurationLinks the ServiceAccount to the cloud role or identity
Attestation pluginVerifies the node's identity at startup

You therefore replace a long-lived shared secret with a more robust cryptographic trust infrastructure. The lesson on secret zero explains why this root, and not a password, becomes the critical point.

Use cases

The following four situations cover most of what you meet in production. Two are pure: identity is enough from start to finish. The other two are hybrid: identity is used to obtain something else, a dynamic secret or temporary cloud credentials.

Service to service (mTLS)

Two microservices communicate with SPIFFE certificates: each checks the other's identity, without a shared secret. In practice, mTLS goes through a proxy (Envoy, managed by a mesh) or a library that loads the X.509-SVIDs from the Workload API.

Pod to database

PostgreSQL, MySQL and most relational databases cannot verify an SVID: they expect a username and a password. Machine identity therefore does not replace the credential, it is used to obtain it from a vault, instead of a static password.

  1. The pod has an identity (SPIFFE or Kubernetes token).
  2. It presents it to Vault or OpenBao.
  3. The vault checks it and generates dynamic database credentials.
  4. The pod connects with these temporary credentials.

This is a hybrid use, and the best tooled today: the lesson on the lifecycle measures these dynamic credentials, a distinct PostgreSQL user lasting one hour per read.

CI/CD to cloud

This is the quickest case to set up: GitHub Actions issues an OIDC token that describes the repository and the branch, and AWS as well as GCP can verify it. Instead of keys stored in the repository secrets, the job obtains temporary credentials. The following workflow passes actionlint, zizmor 1.30.0 and poutine 1.1.6 with no findings.

.github/workflows/deploy.yml
name: deploy
on:
push:
branches: [main]
permissions: {}
jobs:
deploy:
runs-on: ubuntu-24.04
environment: production
permissions:
id-token: write # issuance of the job's OIDC token
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Obtenir des identifiants AWS temporaires
uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0
with:
role-to-assume: arn:aws:iam::123456789012:role/github-deploy
aws-region: eu-west-3
role-duration-seconds: 900
- name: Vérifier l'identité obtenue
run: aws sts get-caller-identity

Without role-duration-seconds, the action requests one hour, the default in its action.yml. The lesson on secrets in CI/CD details the trust relationship on the AWS side, which must constrain the token's sub to the repository and the environment.

Proxy or service mesh

This is the path to favour when you cannot modify the applications: identity is managed outside the code, by the infrastructure. Each pod receives a sidecar proxy or an eBPF agent that carries the identity, traffic between pods is encrypted with mTLS, and authorisation is based on identity, not on secrets.

Identity, dynamic secret or static secret?

To choose, only one question matters: can the target system verify a certificate or a JWT, or does it expect a password? The table spells out the answer per situation; the detailed comparison of the other two models is in static or dynamic secrets (in French).

NeedRecommended approachWhy
Kubernetes pod to cloud API (S3, GCS)Native federation (GKE, IRSA or EKS Pod Identity, AKS)No secret, token verified by the cloud
Internal service to internal serviceSPIFFE/SPIRE or service meshmTLS with identity, no M2M secret
Service to classic databaseDynamic secret (Vault, OpenBao)The database does not understand SPIFFE certificates
Third-party API with a fixed keyStatic secret in a vaultThe API imposes a key
Short SSH accessSigned SSH certificate (Vault SSH)No permanent SSH key
CI/CD to cloudOIDC federation (GitHub to AWS or GCP)No stored access key
Legacy application without mTLSDynamic secret or static in a vaultThe application cannot consume a certificate

The decision rule fits in three cases. Machine identity when the target verifies a certificate or a JWT; dynamic secret when it expects a password but tolerates rotation; static secret in a vault when no alternative exists.

When not to use machine identity

Machine identity is not always the right starting point. It can be the right answer in the long run without being the immediate priority, and a SPIRE project launched too early ties up a team while secrets remain in the code.

SituationWhy postponeStart with
Legacy application that cannot be modifiedCannot reload a certificateDynamic secret or static in a vault
External API with a fixed keyThe API imposes its modelKey stored in a vault
Team without PKI or OIDC cultureLearning curveVault and automatic rotation
Secrets still in the codeThe priority is to get them outDetection and vault
Infrastructure outside KubernetesLess native attestationVault with a suitable auth method

If the team has not yet moved its secrets out of the source code, deploying SPIFFE/SPIRE is premature. Secret detection (in French) and migration to a vault are prior steps.

Technical prerequisites

Before deploying a machine identity solution, check that your infrastructure is ready. The two families do not cost the same: SPIRE amounts to running an internal PKI, cloud federation delegates most of it to the provider.

For SPIFFE/SPIRE

Deploying SPIRE amounts to running an internal public key infrastructure. The two most underestimated rows are trust bundle distribution, without which workloads cannot verify their peers, and time synchronisation, which silently invalidates one-hour certificates when it drifts.

PrerequisiteDetail
Trust anchorRoot CA or upstream authority to sign SVIDs
Highly available SPIRE ServerReplication, shared database (PostgreSQL, MySQL)
SPIRE Agent on each nodeKubernetes DaemonSet or system agent
Attestation pluginSuited to the environment (Kubernetes, AWS, GCP, TPM)
ObservabilityMetrics and logs of attestation failures
Trust bundle distributionMechanism to deliver and renew the bundle
Time synchronisationNTP monitored on all nodes

For cloud federation

The list is shorter, because the cloud runs most of it. Your work is limited to exposing the OIDC issuer (except with EKS Pod Identity), creating the role and describing the trust relationship. Mind the last row of the table: an old SDK cannot read federated credentials.

PrerequisiteDetail
Cluster OIDC issuerConfiguration specific to each cloud
IAM role or managed identityCreated with minimal permissions
Federation linkPrincipal identifier (GKE), OIDC trust (IRSA), association (EKS Pod Identity), federated credential (AKS)
Compatible SDKVersion that detects federated credentials

Common pitfalls

These six mistakes come up in first deployments. The first two are the most costly, because they give a false sense of security: the workload authenticates, the logs are clean, and protection is nil because authorisation is too broad or the cluster-side configuration was never enabled.

PitfallConsequenceHow to avoid it
Believing identity replaces authorisationWorkloads authenticated but over-authorisedFine-grained authorisation policies
Thinking an annotation is enoughWithout cluster and IAM configuration, no effectCheck the prerequisites (OIDC issuer, pool, AKS label)
Assuming every application handles mTLSThe application ignores the certificateSidecar proxy or service mesh
Ignoring renewalThe certificate expires, the application goes downMonitor TTLs, test renewals
Multiplying identities without governanceExplosion of SPIFFE IDs and policiesNaming convention, policies as code
Not monitoring the SPIRE ServerNo SVID renewed any moreAlerts on SPIRE metrics

Limits and challenges

Where pitfalls are configuration mistakes, the limits below are structural: they have to be budgeted for. Two often decide the schedule: the applications' real ability to use a certificate, and the identity control plane becoming one more critical service.

LimitReal effectMitigation
Application integrationThe application cannot use a certificate or a JWTProxy, service mesh or SDK
Critical control planeSPIRE outage: renewals failHigh availability, local cache, monitoring
Harder debuggingAuthentication, authorisation or transport failure hard to isolateStructured logs per layer
Partial compatibilitySome systems speak neither mTLS nor OIDCDynamic or static secret in a vault
Identity governanceExplosion of identities and policiesNaming convention, policies as code
Clock driftShort certificates rejectedMonitored NTP
Hybrid casesThe whole information system does not speak SPIFFE or OIDCProgressive approach

Progressive migration

A big-bang switch is not realistic: the six steps below describe a path where each flow migrates independently and remains reversible. The order matters, especially the last step: as long as the old secrets exist, they remain usable and the attack surface has not shrunk.

  1. Inventory the M2M flows

    List the communications between services that use shared secrets, and spot the most sensitive ones.

  2. Prioritise by criticality and feasibility

    Start with sensitive flows (payment, personal data) and compatible ones (services already in Kubernetes, mTLS possible through the mesh).

  3. Deploy the identity infrastructure

    SPIRE for internal M2M, native federation for cloud access. The two coexist.

  4. Migrate service by service

    Replace each shared secret with identity-based mTLS or OIDC federation, and validate each migration on its own.

  5. Keep the dynamic secret for the existing estate

    Systems that speak neither mTLS nor OIDC stay on Vault or OpenBao, with dynamic credentials.

  6. Revoke the old secrets

    Once the migration has been observed in production, revoke then delete the secrets that are no longer needed.

Decision table

This summary condenses the page into one entry per situation, to keep at hand when deciding. The criterion is always the same: can the target system verify a certificate or a JWT, or does it expect a password?

SituationRecommended approach
Internal Kubernetes communicationSPIFFE/SPIRE or service mesh
Pod to cloud (AWS, GCP, Azure)Native federation (GKE, IRSA or EKS Pod Identity, AKS)
CI/CD to cloudOIDC federation
Service to classic databaseDynamic secret (Vault, OpenBao)
Third-party API with a fixed keyStatic secret in a vault
Legacy application without mTLS or OIDCDynamic secret
Short SSH accessSigned SSH certificate

Resources

These official documentations were used to verify the prerequisites in this lesson. They change quickly, especially on the cloud side: reread them before a deployment, in particular for the required annotations and labels.

Key points

  • A machine identity is a signed document, issued for an attested workload, and short-lived: 1 hour for an X509-SVID, 5 minutes for a JWT-SVID (SPIRE 1.15.3).
  • Two families: internal identity (SPIFFE/SPIRE, mTLS) and cloud federation (OIDC), complementary.
  • Identity does not replace authorisation: an overly broad policy makes the identity useless.
  • A projected token carries an audience, a subject and a duration; measured, it is invalidated when its pod is deleted.
  • The real prerequisites: pool and principal on GKE (no annotation), OIDC provider or EKS Pod Identity on AWS, azure.workload.identity/use label on AKS.
  • Identity needs an integration point: proxy, mesh, SDK or vault agent.
  • It is not always the priority: getting secrets out of the code and adopting a vault come first.
  • The evidence expected by SOCLE-SEC-GEN-5 is the use of short-lived or ephemeral identities (OIDC) rather than long-lived secrets.

Knowledge check

Check that you have the essentials of this lesson. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn