Home - Teleport Blog - From Zero Trust to SPIFFE: How to Secure Microservices with Istio and Teleport
From Zero Trust to SPIFFE: How to Secure Microservices with Istio and Teleport

In this Guide:
This guide walks through how to deploy microservices with Zero Trust using SPIFFE identities, service mesh mTLS, and short-lived certificates. You’ll learn how to deploy a secure microservices application, configure default-deny authorization policies, and rebuild service connectivity with explicit SPIFFE-based allow rules.
The "who are you?" microservice problem
Imagine you're running a microservices architecture with dozens of services. You have a checkout service talking to a payment gateway, and an inventory service querying a database.
In this chaotic web of traffic, how do you ensure that the catalogue service is actually talking to the real database service, and not an imposter? How do you prevent a compromised frontend container from pivoting to access sensitive backend data it has no business seeing?
Traditional networks relied on rigid perimeters such as firewalls, IP allow lists, and network segmentation. Today’s world of cloud-native workloads and platforms like Kubernetes is different. Workloads are ephemeral, IPs change with every deployment, and services scale automatically; the concept of a “trusted IP address” no longer exists.
Why secrets management isn't enough
To secure these dynamic environments, many teams turn to long-lived certificates stored in Kubernetes Secrets. While better than nothing, this approach introduces significant management challenges and security risks across diverse environments, including legacy systems and multi-cloud setups.
These challenges and risks include:
- Secrets sprawl: Long-lived certificates — usually secrets stored in a vault — inevitably leak, are hardcoded into repositories, or are shared insecurely.
- Rotation complexity: Rotating certificates across hundreds of services without causing downtime is a logistical challenge.
- Identity crisis: A static key proves access, but it does not prove identity. The keys themselves do not indicate which software is running or where it’s running.
The better way to secure microservices
Solving these challenges requires shifting from implicit trust (based on network location) to explicit trust (based on cryptographic identity). It requires Zero Trust.
In this guide, we will build a practical, secure identity framework using three powerful tools — SPIFFE, Istio, and Teleport — so you can confidently implement Zero Trust in your microservices.
By the end of this guide, you will walk away understanding:
- The Concepts: What SPIFFE and SVIDs are and why they matter.
- The Architecture: How to issue SPIFFE credentials to Kubernetes workloads.
- The Practice: How these concepts work in action with a walkthrough of deploying the "Sock Shop" demo application.
Before we deploy the solution, we need to understand the standard that powers it.
Understanding how SPIFFE works
SPIFFE (Secure Production Identity Framework For Everyone) is an open standard (CNCF project) that provides a reliable way to identify software and establish trust between microservices with greater confidence.
To best connect with your existing security setup, you must first understand how SPIFFE can complement or replace your current identity and trust mechanisms.
SPIFFE ID: The "name"
A SPIFFE ID is a structured URI that uniquely identifies a container, much like a name.
SPIFFE IDs follow the format: spiffe://<trust-domain>/<path>.
For example: spiffe://acme.com/ns/payments/sa/backend
Because the ID is standardized, a service running in a Kubernetes cluster can easily distinguish between "Billing" and "Reporting," even if the other service is running on a legacy bare-metal server or a completely different cloud provider. In a Kubernetes environment, this standardized ID is typically composed of the namespace and the service account name.
SVID: The "passport"
If the SPIFFE ID is the container name, the SVID (SPIFFE Verifiable Identity Document) is its ID card or passport. The SVID provides cryptographic proof that the container is who it claims to be.
X.509-SVID is a standard TLS certificate with the SPIFFE ID encoded in the Subject Alternative Name (SAN) field. This is used for mTLS (mutual TLS).
Unlike static keys that last for years, SVIDs typically expire in minutes or hours and are automatically rotated, ensuring your system stays secure without manual intervention.
Workload API: The "delivery"
How does a container get this passport? It uses the Workload API.
- No Long-Lived Credentials: The workload starts with zero certificates stored as secrets.
- The Ask: It connects to a local Unix Domain Socket on the node.
- Attestation: The agent analyzes the process (PID, User ID, Kubernetes Service Account) to verify its identity.
- Issuance: If the process matches a policy, the agent issues a short-lived SVID.
Comparison: Traditional vs. SPIFFE
| Traditional Approach | SPIFFE Approach |
|---|---|
| Static Secrets: Certificates hardcoded or in Secrets. | Dynamic Credentials: Short-lived SVIDs. |
| Network Trust: "Allow if IP is 10.0.0.5" | Identity Trust: "Allow if the Authority verifies Identity." |
| Manual Rotation: Painful and rarely done. | Auto-Rotation: Automatic every few hours. |
| Fragmented Identity: Different IAM per platform. | Universal Standard: Works across AWS, on-prem, and K8s. |
Example flow: Teleport + Istio + Sock Shop SPIFFE
Sock Shop is a popular microservices demo application that simulates an e-commerce site. It is polyglot (Java, Go, Node.js) and includes stateful databases, making it the perfect testbed.
The following illustrates how identity flows from the Teleport Cluster, through the tbot agent, and finally to the Envoy sidecar next to your application.


From trigger to completion, the workflow looks like this:
- The Trigger: The application pod starts. Istio's Envoy sidecar needs a certificate.
- The Request: Envoy connects to the tbot socket on the node.
- The Attestation: tbot asks Kubernetes: "Who owns this socket connection?" The API confirms it is the catalogue service.
- The Issuance: tbot requests a certificate from the Teleport Cluster. Teleport logs the request, signs it, and returns it.
- The Result: The catalogue service can now communicate securely using mTLS.
Services in our demo:
front-end(Node.js) — Web UIcatalogue(Go) — Product servicecatalogue-db(MySQL) — Databasecarts(Java) — Shopping cartorders(Java) — Order management


Now that we have the architecture, we will need to perform the following tasks.
- Install Istio, the service mesh platform.
- Configure the Teleport access plane to mint SPIFFE identities.
- Install the multiple microservices that make up the sock shop.
- Integrate Istio and Teleport: We want to use SPIFFE to secure microservices and configure Istio sidecar proxies to use identities provided and managed by Teleport for mutual TLS (mTLS) and fine-grained access control within the microservice architecture.
- Configure policies to “default deny.”
- Configure explicit allow rules and rebuild the connectivity one link at a time.
About our implementation choice
You might ask: "Istio has a built-in Certificate Authority. Why add Teleport?"
While true, this implementation choice was made for several reasons.
While Istio handles traffic routing beautifully, its internal CA often creates an "identity silo." Upgrading to Teleport unifies human and machine identities, allowing us to see "Alice deployed the service" and "The Service accessed the Database" from a single audit log.
Secondly, Istio's CA is trapped inside the mesh. Teleport, however, can issue SPIFFE IDs to workloads outside of Kubernetes (such as legacy VMs or external databases), allowing them to join the mesh securely.
Finally, Teleport uses Kubernetes join tokens and validates pod identity via the Kubelet API, eliminating the need for long-lived certificates.
Teleport vs. reference implementations: Why choose Teleport?
If Istio's internal CA isn't sufficient, you may also be considering SPIRE, the current open-source reference architecture for implementing SPIFFE.
However, Teleport is still a stronger choice for enterprise-grade identity, not just a service-mesh add-on.
SPIRE vs Teleport comparison
| Category | SPIRE | Teleport |
|---|---|---|
| Standards alignment | Focused on SPIFFE identity implementation | Teleport is already an approved implementation of the standard |
| Platform scope | Excels at focusing solely on SPIFFE identity | Built to secure all of your infrastructure: humans, machines, AI agents, and any workload or piece of code that needs a defined identity to do work in your environments |
| Workload support | Handles primarily cloud-native stacks (Kubernetes) | Extends identity across the rest of your infrastructure and code, supporting attestation for Docker, SystemD, and services like CircleCI, GitHub, GitLab, and more |
| Cloud service & multi-region readiness | Requires self-managed deployment patterns | Offers single-region and multi-region Cloud services with built-in high SLAs (99.99%) and compliance, and is designed for commercially supported multi-region self-hosted deployments with multiple database backends |
| Federation & control plane | Requires manual federation setup for distributed deployments, creating administrative headaches and data silos | A single deployment covers all identities across infrastructure and code, federating seamlessly with centralized control |
| Visibility & audit | More limited visibility outside core identity issuance | Provides a status dashboard, inventory, and searchable audit events for all non-human identities |
| CI/CD and ephemeral use cases | Agents are designed to run as daemons, less suited to short-lived jobs | "One-shot" mode is ideal for ephemeral CI/CD and AI Agent environments, eliminating the need for long-lived static certificates in pipelines |
Learn more about how SPIRE compares to Teleport.
The Zero Trust model
By default, Kubernetes allows any pod to talk to any other pod. This is convenient for development, but dangerous for security.
That’s why we will flip this model to "default deny.” Here’s how.
Configuring “default deny”
First, we lock down the namespace. To do this, we apply a "catch-all" policy that blocks all traffic within the sock-shop namespace.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: sock-shop
spec: {} # Empty spec = deny all traffic
This immediately breaks all service communication. Now, the frontend cannot reach the catalogue, and the catalogue cannot reach the database.
Configuring explicit allow rules
Next, we will rebuild the connectivity one link at a time by strictly defining who can talk to whom.
The frontend service needs to query the catalogue to display products. We create a policy that permits this specific interaction only.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: catalogue-allow-frontend
namespace: sock-shop
spec:
selector:
matchLabels:
app: catalogue # 1. Apply this rule to the Catalogue service
action: ALLOW
rules:
- from:
- source: # 2. Only allow traffic from this specific Teleport SPIFFE ID
principals:
- "ellinj.teleport.sh/ns/sock-shop/sa/front-end"
to:
- operation: # 3. Only allow specific read-only operations
methods: ["GET"]
paths: ["/catalogue", "/catalogue/*", "/tags"]
What's happening under the hood
We've installed the mesh, deployed the app, and defined the policies. But what actually happens when a user clicks a button?
Let's trace the flow of a single request from the front-end service to the catalogue service.
- A user visits the Sock Shop website. Their browser sends a request to the
frontendservice. - The Envoy Proxy running inside the
frontendpod intercepts the outbound request and checks for a valid SVID. - An mTLS connection is initiated, and the client certificate is presented:
spiffe://ellinj.teleport.sh/ns/sock-shop/sa/front-end - The Envoy Proxy on the
catalogueside receives the request and validates the certificate against the Teleport CA, and then checks the AuthorizationPolicy to confirm access permissions. The policy says ALLOW. - Envoy forwards the request to the
cataloguecontainer.
The application code never deals with certificates, TLS, or authorization logic. Istio and Teleport handle it all transparently. Within the Teleport Audit log, we can see the certificates being issued.


Security benefits and real-world impact
We have moved from a fragile architecture with long-lived certificates to a robust, identity-first system, resulting in significant improvements in security and quality of life.
- Every service proves its identity with cryptographically secure, short-lived certificates.
- Even if an attacker compromises a pod, they can't pivot without the proper SPIFFE ID.
- With tbot, certificates can expire every 60 minutes (fully configurable) and auto-rotate, shrinking the window of opportunity for a compromised credential to near-zero.
- Teleport logs every certificate issuance. You can see exactly which workloads are communicating.
Comparison: Before and after this implementation
| Before (Kubernetes only) | After (with SPIFFE/Istio/Teleport) |
|---|---|
| Services trust any caller on the network | Services verify the caller's cryptographic identity |
| API keys stored in environment variables | No long-lived credentials |
| Network policies based on IPs/Labels | Authorization policies based on SPIFFE IDs |
| Manual credential rotation (painful) | Automatic certificate rotation (transparent) |
| No visibility into service traffic | Full audit trail and observability |
Conclusion
By combining Istio for the data plane, SPIFFE for the identity standard, and Teleport for the authority and audit layer, we've made significant progress on addressing the most challenging problem in microservices security — trust.
We no longer hope that the service calling our database is who it says it is. We know it is. That’s because it now holds a cryptographic passport issued and verified by our internal authority. And best of all, we achieved this without writing a single line of authentication code in our application.
Try it for yourself!
Follow the instructions in this GitHub repository to learn how to configure a fully working Sock Shop, complete with Istio policies that use SVIDs to determine which services can communicate.
Related Articles
→ Introduction to SPIFFE
→ Kubernetes Namespace Restriction and Separation
→ DevOps Credential Hygiene: How to Eliminate CI/CD Secrets
Table Of Contents
- The "who are you?" microservice problem
- Why secrets management isn't enough
- The better way to secure microservices
- Understanding how SPIFFE works
- Example flow: Teleport + Istio + Sock Shop SPIFFE
- About our implementation choice
- Teleport vs. reference implementations: Why choose Teleport?
- The Zero Trust model
- What's happening under the hood
- Security benefits and real-world impact
- Conclusion
- Related Articles
Teleport Newsletter
Stay up-to-date with the newest Teleport releases by subscribing to our monthly updates.
Tags
Subscribe to our newsletter

