Skip to main content

Module 6: Working with SVIDs and the Workload API

How applications consume and use SPIFFE identities

3 hours. 3 hands-on labs. Free course module.

Learning Objectives

  • Use the SPIFFE Workload API programmatically
  • Integrate SPIFFE into Go, Python, and Java applications
  • Build mTLS connections between microservices
  • Implement automatic certificate rotation in applications

Why This Matters

A workload identity system is useless if applications cannot consume the identities. This module bridges the gap between infrastructure (SPIRE) and application code — the integration point where most real-world problems occur.

APPLICATION INTEGRATION PATTERNSGo Applicationgo-spiffe libraryDirect Workload APIAuto-rotation built inPython Applicationpy-spiffe libraryor SPIFFE HelperFile-based certsAny ApplicationSPIFFE Helper sidecarWrites certs to diskZero code changesSPIFFE Workload APISPIRE Agent (Unix Domain Socket)
Architecture diagram for Module 6: Working with SVIDs and the Workload API.

Lesson Content

A workload identity system is only useful if applications can actually use the identities. This module covers how to integrate SPIFFE into applications — from zero-code approaches (SPIFFE Helper) to native library integration (go-spiffe, py-spiffe).

Integration Approaches

There are three ways to consume SPIFFE identities:

  1. SPIFFE Helper (zero code changes): A sidecar that fetches SVIDs and writes them as certificate files. Your application reads the files like any TLS certificate. Works with any language.
  2. Native libraries (code integration): Use go-spiffe, py-spiffe, or java-spiffe to call the Workload API directly. Provides automatic rotation callbacks and richer integration.
  3. Envoy sidecar (proxy-based): Envoy handles mTLS transparently. Your application communicates in plain HTTP; Envoy adds the identity layer. Covered in Module 8.

Using go-spiffe

package main

import (
    "context"
    "net/http"
    "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
    "github.com/spiffe/go-spiffe/v2/workloadapi"
)

func main() {
    ctx := context.Background()

    // Connect to the Workload API
    source, err := workloadapi.NewX509Source(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer source.Close()

    // Create an mTLS server
    tlsConfig := tlsconfig.MTLSServerConfig(
        source,    // Serve our SVID
        source,    // Verify client SVIDs
        tlsconfig.AuthorizeAny(), // Or use AuthorizeID for specific SPIFFE IDs
    )

    server := &http.Server{
        Addr:      ":8443",
        TLSConfig: tlsConfig,
    }
    server.ListenAndServeTLS("", "") // Certs from SPIRE, not files
}

Using SPIFFE Helper

# spiffe-helper.conf
agent_address = "/run/spire/sockets/agent.sock"
cmd = "/app/server"            # Your application command
cert_dir = "/run/spire/certs"  # Where to write certificates
svid_file_name = "svid.pem"
svid_key_file_name = "svid_key.pem"
svid_bundle_file_name = "bundle.pem"
renew_signal = "SIGHUP"       # Signal to send when certs rotate

# Your app reads /run/spire/certs/svid.pem and svid_key.pem
# When certs rotate, your app gets SIGHUP to reload

Building mTLS Between Microservices

With SVIDs, two services can establish mTLS without manually managing certificates:

# Service A (client) connects to Service B (server):
# 1. Both services get SVIDs from SPIRE via Workload API
# 2. Service A presents its SVID as the client certificate
# 3. Service B presents its SVID as the server certificate
# 4. Both verify the other's SVID against the trust bundle
# 5. Connection established — both identities proven

# No manual certificate generation
# No certificate files to manage
# No expiration alerts — SPIRE handles rotation

Secure gRPC Communication

# gRPC with SPIFFE identity (Go):
# Server:
source, _ := workloadapi.NewX509Source(ctx)
creds := grpc.Creds(credentials.NewTLS(
    tlsconfig.MTLSServerConfig(source, source, authorize),
))
server := grpc.NewServer(creds)

# Client:
source, _ := workloadapi.NewX509Source(ctx)
creds := grpc.WithTransportCredentials(credentials.NewTLS(
    tlsconfig.MTLSClientConfig(source, source, authorize),
))
conn, _ := grpc.Dial("service-b:8443", creds)

Real-World Use Cases

  • Go microservices using go-spiffe for native mTLS
  • Legacy Java applications using SPIFFE Helper for zero-code integration
  • Python services using py-spiffe for Workload API access
  • gRPC services with SPIFFE TLS credentials for inter-service auth

Production Notes

  • For new services: use go-spiffe or py-spiffe for native integration. For legacy services: use SPIFFE Helper to write certs to disk with zero code changes.
  • Always configure a renewal signal (SIGHUP) with SPIFFE Helper so applications reload certificates on rotation.
  • In production, use the Envoy sidecar approach when you cannot modify application code and need mTLS transparently.

Common Mistakes

  • Not handling SVID rotation callbacks — applications crash when certs expire
  • Hardcoding socket paths instead of using the SPIFFE_ENDPOINT_SOCKET environment variable
  • Using SPIFFE Helper without configuring the renew_signal — certs rotate but the app keeps using old ones
  • Fetching SVIDs on every request instead of caching and watching for rotation

Design Tradeoffs

SPIFFE Helper (sidecar)

Pros

  • Zero application code changes
  • Works with any language
  • Writes standard PEM files

Cons

  • Requires sidecar management
  • Signal-based reload can miss rotations
  • Extra process per pod

go-spiffe (library)

Pros

  • Native API integration
  • Automatic rotation callbacks
  • Fine-grained control

Cons

  • Go-only
  • Requires code changes
  • Adds dependency

Envoy sidecar (proxy)

Pros

  • Transparent mTLS
  • No app changes
  • L7 features (routing, auth)

Cons

  • Resource overhead
  • Complex config
  • Latency from proxy hop

Key Terms

SPIFFE Helper
Sidecar that writes SVIDs as PEM files to disk
go-spiffe
Official Go library for Workload API integration
Workload API Socket
Unix domain socket at /run/spire/sockets/agent.sock
SIGHUP
Signal sent to applications to trigger certificate reload

Hands-On Labs

  1. Getting SVIDs with SPIFFE Helper

    Use SPIFFE Helper for zero-code SVID integration.

    • Deploy SPIFFE Helper as a sidecar container
    • Configure certificate file paths
    • Verify SVIDs are written to disk
    • Configure an Nginx server to use the SVID certificates

    View lab files on GitHub

  2. Building mTLS Between Microservices

    Establish mutual TLS between two Go services using go-spiffe.

    • Build a Go server that serves with its SVID
    • Build a Go client that authenticates with its SVID
    • Verify mTLS connection with both identities
    • Test that a service without a valid SVID is rejected

    View lab files on GitHub

  3. Secure gRPC Communication

    Secure gRPC services with SPIFFE identities.

    • Create a gRPC server with SPIFFE TLS credentials
    • Create a gRPC client with SPIFFE TLS credentials
    • Verify mutual authentication via SPIFFE IDs
    • Implement SPIFFE ID-based authorization in the server

    View lab files on GitHub

Key Takeaways

  • SPIFFE Helper enables zero-code integration — writes certs to files
  • go-spiffe provides native Workload API integration with auto-rotation
  • mTLS between services requires no manual certificate management with SPIRE
  • gRPC integrates natively with SPIFFE via TLS credentials
  • Choose your approach: sidecar (any language), library (Go/Python/Java), or proxy (Envoy)