How to Extend SPIFFE Beyond Kubernetes: Bring Zero Trust Identity to Your VMs

Table Of Contents
- The problem: Off-cluster calls shouldn’t force secret sprawl
- The solution: Separate identity issuance from identity consumption
- Why this is a stronger alternative to Istio’s internal CA
- What you get: Scalable policy, simpler operations, fewer secrets
- Controlling the new Teleport identity inside the mesh
- Extending identity beyond Kubernetes
Our previous post, How to Secure Microservices with SPIFFE and Istio, showed how to secure Kubernetes microservices using Istio policy and SPIFFE identities, with Teleport issuing the identities that the mesh trusts. The question teams face next is: How do you extend that identity-driven security model to workloads outside Kubernetes — such as VMs, edge gateways, and legacy services — without creating a massive certificate-management project?
This post explains what makes off-cluster identity challenging, and explores an alternative architectural model that can extend SPIFFE identities consistently across Kubernetes, VM, and other environments.
For complete, reproducible step-by-step instructions and configs, follow along on GitHub.
The problem: Off-cluster calls shouldn’t force secret sprawl
It's easy to get a VM to reach a Kubernetes service, but securing, auditing, and maintaining that connection is where things get tricky. The usual approach of copying a client cert onto the VM creates several problems, including:
- Long-lived credentials that outlive the workload that needed them.
- Manual rotation, brittle procedures, and the risk of outages when rotation is missed.
- Revocation is difficult and slow.
- Confusing identity (based on IP rules or shared certificates).
SPIFFE (Secure Production Identity Framework For Everyone) is an open standard that provides a universal, cryptographic identity for all software workloads. It is used to establish zero trust by shifting security from network location to a verifiable "passport,” known as an SVID. For a deeper dive, please see our SPIFFE documentation or our previous blog post.
The challenge, though, is delivery: how do you safely get these short-lived identities to VMs and other off-cluster workloads without distributing private keys as files?
The solution: Separate identity issuance from identity consumption
The solution is to separate identity issuance from identity consumption. Instead of copying certificates onto VMs, you let each workload request its own short-lived identity from a trusted authority and consume it through a local API.
In this demo, Envoy consumes identity via SDS (Secret Discovery Service) while Teleport manages the trust chain. This solution keeps responsibilities clear across multiple workload types.
Architecture overview
The architecture of this approach works like this:
- Teleport is the workload identity authority, issuing SPIFFE SVIDs and managing the trust chain.
- On the VM, tbot joins Teleport and exposes a local SPIFFE Workload API endpoint.
- Envoy runs as an outbound proxy and retrieves the SVID and trust bundle via SDS from the local Workload API socket, consuming the newly issued certificate.
- In Kubernetes, Istio continues to enforce mTLS and
AuthorizationPolicybased on the SPIFFE identity presented over mTLS.
The key property of this architecture is that Envoy does not read certificate files from disk. Instead, identity is delivered over a local socket and automatically rotated, reducing credential sprawl and operational overhead.
Why this is a stronger alternative to Istio’s internal CA
Istio’s built-in Certificate Authority (CA) is a great default when identity only lives inside Kubernetes. However, the trust anchor and issuance system live inside a single cluster control plane, which creates several challenges when extending identity off-cluster:
- Off-cluster workloads must bootstrap trust in (and depend on) a cluster-local CA because the trust anchor is locked in-cluster.
- Any upgrades, re-installs, or
DestinationRuleevents for that cluster’s control plane can impact identity and mTLS for callers outside the cluster. - Each cluster becomes an isolated environment, making it difficult to standardize identity across resources without additional federation/bridging complexity.
With Teleport managing the trust chain, identity is no longer “something the cluster hands out,” and instead becomes an organization-wide primitive. Kubernetes is just one place that consumes identities; VMs are another. This allows policies to remain consistent across resources because they’re enforced using workload identity (SPIFFE IDs) rather than IP addresses or cluster-local assumptions.
What you get: Scalable policy, simpler operations, fewer secrets
This approach with Teleport and Envoy also creates several operational and security benefits:
- No credentials on disk: Envoy fetches short-lived SVIDs via SDS over a local socket. There’s no “copy a private key to the VM” moment.
- Identity-driven access control: Istio
AuthorizationPolicycan allow/deny based on SPIFFE identity (the principal), not on IP ranges. - Consistent trust across platforms: The same trust domain can span multiple clusters and VMs because Teleport is the trust anchor.
- Standards-based integration: Envoy doesn’t need to be Teleport-aware. It consumes identity through standard SPIFFE/SDS interfaces.
Controlling the new Teleport identity inside the mesh
For example, an Istio AuthorizationPolicy to allow a specific VM's identity (the VM's auth-server) to read data from the in-cluster catalog service would look like this:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: catalogue-allow-vm-auth
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 the VM's specific Teleport SPIFFE ID
principals:
- "spiffe://ellinj.teleport.sh/vm/catalog-client"
to:
- operation: # 3. Only allow specific read-only operations
methods: ["GET"]
paths: ["/catalogue", "/catalogue/*", "/tags"]
This policy ensures that only workloads presenting the exact SPIFFE identity spiffe://ellinj.teleport.sh/vm/catalog-client can perform read operations on the catalogue service, demonstrating policy enforcement based on identity rather than network location.
Extending identity beyond Kubernetes
As detailed in our previous post, the security model for microservices inside Kubernetes doesn’t have to stop at the cluster boundary.
By anchoring the trust chain in Teleport and using Envoy + SDS to consume workload identity on VMs, you get a practical, scalable way to extend SPIFFE-based mTLS and policy across environments with fewer long-lived secrets and less operational friction.
Table Of Contents
- The problem: Off-cluster calls shouldn’t force secret sprawl
- The solution: Separate identity issuance from identity consumption
- Why this is a stronger alternative to Istio’s internal CA
- What you get: Scalable policy, simpler operations, fewer secrets
- Controlling the new Teleport identity inside the mesh
- Extending identity beyond Kubernetes
Teleport Newsletter
Stay up-to-date with the newest Teleport releases by subscribing to our monthly updates.
Teleport Newsletter
Stay up-to-date with the newest Teleport releases by subscribing to our monthly updates.
Related Articles

From Zero Trust to SPIFFE: How to Secure Microservices with Istio and Teleport
Learn how to deploy a secure microservices application, configure default-deny authorization policies, and rebuild service connectivity with explicit SPIFFE-based allow rules.

DevOps Credential Hygiene: How to Eliminate CI/CD Secrets with Teleport
Learn how to move from static DevOps secrets to short-lived certificates and workload identity — and secure CI/CD automation at scale with full audit visibility and no manual rotation.

Kubernetes for Agentic AI: Best Practices for Security and Observability
Discover 18 Kubernetes security, observability, and availability best practices for container-based agentic workloads.