Module 6 of 13

Working with SVIDs and the Workload API

How applications consume and use SPIFFE identities

3 hours3 labsFree

Start here

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
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)

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

Where this shows up

  • 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

Keep these close

  • 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

What usually breaks

  • 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

Tradeoffs

Design choices you should be able to defend

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

Vocabulary used in this module

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

Labs

Hands-on labs

Getting SVIDs with SPIFFE Helper

Use SPIFFE Helper for zero-code SVID integration.

  1. Deploy SPIFFE Helper as a sidecar container
  2. Configure certificate file paths
  3. Verify SVIDs are written to disk
  4. Configure an Nginx server to use the SVID certificates
View lab on GitHub

Building mTLS Between Microservices

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

  1. Build a Go server that serves with its SVID
  2. Build a Go client that authenticates with its SVID
  3. Verify mTLS connection with both identities
  4. Test that a service without a valid SVID is rejected
View lab on GitHub

Secure gRPC Communication

Secure gRPC services with SPIFFE identities.

  1. Create a gRPC server with SPIFFE TLS credentials
  2. Create a gRPC client with SPIFFE TLS credentials
  3. Verify mutual authentication via SPIFFE IDs
  4. Implement SPIFFE ID-based authorization in the server
View lab on GitHub

Recap

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)

Related resources

Keep learning across CodersSecret