Skip to content

Instantly share code, notes, and snippets.

@mohashari
Created July 11, 2026 00:42
Show Gist options
  • Select an option

  • Save mohashari/952a36072d5b874063840f95f5974a37 to your computer and use it in GitHub Desktop.

Select an option

Save mohashari/952a36072d5b874063840f95f5974a37 to your computer and use it in GitHub Desktop.
Designing an Automated Secret Zero Bootstrapping Pipeline in Kubernetes using TPM 2.0 and SPIFFE/SPIRE — code snippets
# SPIRE Server configuration snippet for TPM 2.0 node attestation
server {
bind_address = "0.0.0.0"
bind_port = "8081"
trust_domain = "prod.muklis.internal"
data_dir = "/run/spire/data"
log_level = "INFO"
ca_key_type = "rsa-2048"
ca_ttl = "24h"
default_svid_ttl = "1h"
}
plugins {
NodeAttestor "tpm" {
plugin_data {
ca_path = "/run/spire/config/tpm-vendor-cas.pem"
# Whitelist database mapped to physical machine inventories
endorsement_key_db_path = "/run/spire/config/ek_whitelist.json"
}
}
KeyManager "disk" {
plugin_data {
keys_path = "/run/spire/data/keys.json"
}
}
}
# SPIRE Agent configuration snippet for TPM 2.0 node attestation
agent {
data_dir = "/run/spire-agent/data"
log_level = "INFO"
server_address = "spire-server.spire.svc.cluster.local"
server_port = "8081"
socket_path = "/run/spire/sockets/agent.sock"
trust_domain = "prod.muklis.internal"
}
plugins {
NodeAttestor "tpm" {
plugin_data {
# Path to the TPM 2.0 resource manager device
tpm_device_path = "/dev/tpmrm0"
# Owner hierarchy password (empty by default on clean systems)
owner_auth = ""
}
}
KeyManager "memory" {
plugin_data {}
}
WorkloadAttestor "k8s" {
plugin_data {
kubelet_read_only_port = 10255
# Enforce secure connection to kubelet API for verification
use_https = true
kubelet_ca_path = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
token_path = "/var/run/secrets/kubernetes.io/serviceaccount/token"
}
}
}
# Pod spec mounting the SPIFFE workload API socket via CSI driver
apiVersion: apps/v1
kind: Deployment
metadata:
name: billing-service
namespace: payment-apps
labels:
app: billing-service
spec:
replicas: 3
selector:
matchLabels:
app: billing-service
template:
metadata:
labels:
app: billing-service
spec:
serviceAccountName: billing-sa
containers:
- name: application
image: billing-service:v2.1.0
env:
- name: SPIFFE_ENDPOINT_SOCKET
value: "unix:///run/spiffe/workload.sock"
- name: VAULT_ADDR
value: "https://vault.prod.muklis.internal:8200"
volumeMounts:
- name: spiffe-workload-api
mountPath: /run/spiffe
readOnly: true
resources:
limits:
cpu: "1"
memory: "1Gi"
requests:
cpu: "250m"
memory: "256Mi"
volumes:
- name: spiffe-workload-api
csi:
driver: "spiffe.csi.spiffe.io"
readOnly: true
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/spiffetls"
"github.com/spiffe/go-spiffe/v2/workload"
)
const socketPath = "unix:///run/spiffe/workload.sock"
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Connect to the SPIFFE Workload API via the Unix Domain Socket
client, err := workload.NewX509Source(ctx, workload.WithClientOptions(workload.WithAddr(socketPath)))
if err != nil {
log.Fatalf("Unable to create X.509 source from socket %s: %v", socketPath, err)
}
defer client.Close()
// Verify the SVID was retrieved successfully
svid, err := client.GetX509SVID()
if err != nil {
log.Fatalf("Failed to fetch SVID from source: %v", err)
}
fmt.Printf("Successfully retrieved SVID: %s\n", svid.ID.String())
// Set up an mTLS client configuration that trusts only specific workloads in our domain
targetAudience, err := spiffeid.FromString("spiffe://prod.muklis.internal/ns/payment-apps/sa/vault-sa")
if err != nil {
log.Fatalf("Invalid target SPIFFE ID: %v", err)
}
tlsConfig := spiffetls.NewTLSConfig(client, spiffetls.AuthorizeID(targetAudience))
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
Timeout: 5 * time.Second,
}
// This client is now ready to query protected services using hardware-backed TLS
_ = httpClient
}
# Configure HashiCorp Vault SPIFFE JWT Auth Method
# Enable the JWT auth engine at a dedicated path
vault auth enable -path=spiffe jwt
# Write the configuration containing the SPIRE OIDC discovery URL
vault write auth/spiffe/config \
oidc_discovery_url_query_parameter_supported=false \
oidc_discovery_url="https://spire-server-oidc.spire.svc.cluster.local:443" \
default_role="billing-role" \
bound_issuer="https://spire-server-oidc.spire.svc.cluster.local:443"
# Create a role that binds a specific SPIFFE ID subject to a Vault policy
vault write auth/spiffe/role/billing-role - <<EOF
{
"role_type": "jwt",
"policies": ["billing-secrets-policy"],
"token_ttl": "15m",
"token_max_ttl": "1h",
"bound_subject": "spiffe://prod.muklis.internal/ns/payment-apps/sa/billing-sa",
"user_claim": "sub"
}
EOF
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"time"
"github.com/spiffe/go-spiffe/v2/spiffeid"
"github.com/spiffe/go-spiffe/v2/workload"
)
const (
spiffeSocket = "unix:///run/spiffe/workload.sock"
vaultAddress = "https://vault.prod.muklis.internal:8200"
vaultRole = "billing-role"
)
type VaultLoginResponse struct {
Auth struct {
ClientToken string `json:"client_token"`
Accessor string `json:"accessor"`
LeaseDuration int `json:"lease_duration"`
} `json:"auth"`
}
func fetchSecretZero() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Initialize the JWT Source
jwtSource, err := workload.NewJWTSource(ctx, workload.WithClientOptions(workload.WithAddr(spiffeSocket)))
if err != nil {
return "", fmt.Errorf("failed to connect to SPIFFE workload API: %w", err)
}
defer jwtSource.Close()
// Request a signed JWT SVID with the 'vault' audience
aud := spiffeid.RequireTrustDomainFromString("prod.muklis.internal")
params := workload.JWTParameters{
Audience: "vault",
Subject: spiffeid.RequireFromString("spiffe://prod.muklis.internal/ns/payment-apps/sa/billing-sa"),
}
svid, err := jwtSource.GetJWTSVID(ctx, params)
if err != nil {
return "", fmt.Errorf("failed to fetch JWT SVID: %w", err)
}
// Payload for Vault login
payload := map[string]string{
"role": vaultRole,
"jwt": svid.Marshal(),
}
jsonPayload, err := json.Marshal(payload)
if err != nil {
return "", err
}
// Send POST request to Vault auth endpoint
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/v1/auth/spiffe/login", vaultAddress), bytes.NewBuffer(jsonPayload))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed sending request to Vault: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("vault login failed with status %d: %s", resp.StatusCode, string(body))
}
var vaultResp VaultLoginResponse
if err := json.NewDecoder(resp.Body).Decode(&vaultResp); err != nil {
return "", fmt.Errorf("failed to decode Vault response: %w", err)
}
return vaultResp.Auth.ClientToken, nil
}
func main() {
token, err := fetchSecretZero()
if err != nil {
log.Fatalf("Bootstrapping failed: %v", err)
}
fmt.Printf("Successfully acquired Vault Client Token: %s...\n", token[:8])
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment