Workload Identity with SPIFFE/SPIRE
Supported Versions: SPIRE 1.12+, Kubernetes 1.31, 1.32, 1.33 最終更新: February 25, 2026
SPIFFE (Secure Production Identity Framework For Everyone) と SPIRE (the SPIFFE Runtime Environment) は、cloud-native 環境における workload identity への標準ベースのアプローチを提供します。CNCF Graduated プロジェクトとして、SPIFFE/SPIRE は、アプリケーションコードの変更を必要とせずに、暗号学的に検証可能な identity を workload に提供することで、Zero Trust security を実現します。
Table of Contents
- The Zero Trust Identity Problem
- SPIFFE Specification Overview
- Core Concepts
- SPIRE Architecture
- Installation
- Node Attestation
- Workload Attestation
- Kubernetes Integration
- Service Mesh Integration
- Federation
- EKS Integration
- Best Practices
- Troubleshooting
- Summary and References
The Zero Trust Identity Problem
従来の perimeter-based security model では、ネットワーク境界内の workload は信頼できるものと仮定します。このアプローチは、次のような現代の分散システムではうまく機能しません。
- Microservices communicate across network boundaries — Service は複数の cluster、cloud、data center にまたがります
- Dynamic infrastructure — Container と pod は一時的で、IP address が絶えず変化します
- Lateral movement attacks — 攻撃者が perimeter を突破すると、ネットワーク内を自由に移動できます
- Shared tenancy — 複数のチームとアプリケーションが同じ infrastructure を共有します
Zero Trust security では、ネットワーク上の場所に関係なく、すべての workload が通信前に identity を証明する必要があります。SPIFFE は次の機能を提供することでこれに対応します。
- Universal identity standard — 異種環境全体で workload を識別するための一貫した方法
- Cryptographic verification — ネットワークを信頼せずに検証できる identity
- Automatic rotation — 侵害された場合の blast radius を最小化する短命の credential
- No application changes — アプリケーションに透過的な identity 注入
SPIFFE Specification Overview
SPIFFE は、3 つの中核コンポーネントを定義するオープン仕様です。
| Component | Description |
|---|---|
| SPIFFE ID | A URI that uniquely identifies a workload |
| SVID | SPIFFE Verifiable Identity Document — a cryptographic document that proves a workload's identity |
| Trust Bundle | A set of CA certificates used to verify SVIDs |
| Workload API | A local API that workloads use to obtain their SVIDs |
CNCF Graduation Status
SPIFFE/SPIRE は 2022 年に CNCF を卒業し、production-readiness と業界での広範な採用を示しています。主な採用組織は次のとおりです。
- Bloomberg
- ByteDance
- GitHub
- Square
- Uber
Core Concepts
SPIFFE ID
SPIFFE ID は、trust domain 内で workload を一意に識別する URI です。
spiffe://trust-domain/workload-identifier構成要素:
| Part | Description | Example |
|---|---|---|
spiffe:// | URI scheme (always "spiffe") | spiffe:// |
trust-domain | Administrative domain of trust | prod.example.com |
workload-identifier | Path identifying the workload | /ns/payments/sa/api-server |
SPIFFE ID の例:
# Kubernetes workload by namespace and service account
spiffe://prod.example.com/ns/payments/sa/api-server
# Workload by cluster and deployment
spiffe://example.com/cluster/us-east-1/deployment/frontend
# Legacy application by hostname
spiffe://example.com/host/db-server-01/app/mysqlSVID (SPIFFE Verifiable Identity Document)
SVID は、workload の SPIFFE ID を保持する暗号学的 document です。SPIFFE は 2 つの SVID 形式を定義しています。
X.509-SVID vs JWT-SVID Comparison
| Feature | X.509-SVID | JWT-SVID |
|---|---|---|
| Format | X.509 certificate | JSON Web Token |
| Transport | TLS client certificates | HTTP headers, gRPC metadata |
| Verification | Certificate chain validation | Signature verification |
| Use Case | mTLS connections | API authentication, proxies |
| Audience | Not applicable | Required (prevents replay) |
| Typical TTL | 1 hour (configurable) | 5 minutes (short-lived) |
| Key Storage | Private key file | Private key for signing |
| Revocation | Short TTL (no CRL/OCSP) | Short TTL |
X.509-SVID の構造:
┌─────────────────────────────────────────────────────────────┐
│ X.509-SVID │
├─────────────────────────────────────────────────────────────┤
│ Subject: CN=<workload-identifier> │
│ URI SAN: spiffe://trust-domain/workload-identifier │
│ Issuer: SPIRE Server CA │
│ Not Before: 2026-02-25T10:00:00Z │
│ Not After: 2026-02-25T11:00:00Z (1 hour TTL) │
│ Public Key: [workload's public key] │
│ Signature: [signed by SPIRE Server CA] │
└─────────────────────────────────────────────────────────────┘JWT-SVID の構造:
{
"alg": "RS256",
"kid": "abcd1234",
"typ": "JWT"
}
.
{
"sub": "spiffe://prod.example.com/ns/payments/sa/api",
"aud": ["spiffe://prod.example.com/ns/orders/sa/processor"],
"exp": 1708858200,
"iat": 1708857900
}
.
[signature]Trust Bundle
Trust bundle には、trust domain の root CA certificate が含まれます。workload は trust bundle を使用して、同じ trust domain 内の他の workload からの SVID を検証します。
# Trust bundle structure
trust_domain: "prod.example.com"
root_certificates:
- |
-----BEGIN CERTIFICATE-----
MIIBzDCCAVKgAwIBAgIJAJR2...
-----END CERTIFICATE-----
jwt_signing_keys:
- kid: "key-1"
public_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEF...
-----END PUBLIC KEY-----Trust Domain
Trust domain は、信頼の管理境界です。trust domain 内のすべての workload は、同じ root of trust (SPIRE Server CA) を共有します。
Trust Domain の設計上の考慮事項:
| Pattern | Example | Use Case |
|---|---|---|
| Single domain | example.com | Simple deployments |
| Environment-based | prod.example.com, staging.example.com | Environment isolation |
| Region-based | us-east.example.com, eu-west.example.com | Regional isolation |
| Cluster-based | cluster-a.example.com | Multi-cluster with separate CAs |
SPIRE Architecture
SPIRE は server-agent architecture で SPIFFE 仕様を実装します。
SPIRE Server
SPIRE Server は次の役割を持つ中央 authority です。
| Function | Description |
|---|---|
| CA Operations | Signs X.509-SVIDs and JWT-SVIDs |
| Registration API | Manages workload registration entries |
| Node Attestation | Verifies agent identity during bootstrap |
| Data Store | Persists registration entries and CA state |
| Key Management | Manages signing keys (supports HSM/KMS) |
Server Configuration Example:
# server.conf
server {
bind_address = "0.0.0.0"
bind_port = "8081"
trust_domain = "prod.example.com"
data_dir = "/run/spire/data"
log_level = "INFO"
ca_ttl = "24h"
default_x509_svid_ttl = "1h"
default_jwt_svid_ttl = "5m"
ca_subject {
country = ["US"]
organization = ["Example Corp"]
common_name = "SPIRE Server CA"
}
}
plugins {
DataStore "sql" {
plugin_data {
database_type = "postgres"
connection_string = "dbname=spire host=postgres user=spire"
}
}
NodeAttestor "k8s_psat" {
plugin_data {
clusters = {
"production" = {
service_account_allow_list = ["spire:spire-agent"]
}
}
}
}
KeyManager "disk" {
plugin_data {
keys_path = "/run/spire/data/keys.json"
}
}
UpstreamAuthority "disk" {
plugin_data {
key_file_path = "/run/spire/conf/ca.key"
cert_file_path = "/run/spire/conf/ca.crt"
}
}
}SPIRE Agent
SPIRE Agent は各 node 上で実行され、次を行います。
| Function | Description |
|---|---|
| Node Attestation | Proves node identity to the server |
| Workload Attestation | Identifies workloads requesting SVIDs |
| Workload API | Serves SVIDs to workloads via Unix socket |
| SVID Caching | Caches and rotates SVIDs automatically |
| SDS Server | Provides Envoy SDS API for service meshes |
Agent Configuration Example:
# agent.conf
agent {
data_dir = "/run/spire/data"
log_level = "INFO"
server_address = "spire-server"
server_port = "8081"
socket_path = "/run/spire/sockets/agent.sock"
trust_domain = "prod.example.com"
}
plugins {
NodeAttestor "k8s_psat" {
plugin_data {
cluster = "production"
}
}
KeyManager "memory" {
plugin_data {}
}
WorkloadAttestor "k8s" {
plugin_data {
skip_kubelet_verification = true
}
}
}SVID Issuance Flow
次の図は、workload が SVID を取得する方法を示しています。
Installation
Prerequisites
- Kubernetes cluster 1.31+
- Helm 3.10+
- cluster access が設定された kubectl
- Cluster admin permission
Helm Installation (Recommended)
SPIRE は、workload registration を自動化する SPIRE Controller Manager を含む Helm chart を提供しています。
# Add the SPIFFE Helm repository
helm repo add spiffe https://spiffe.github.io/helm-charts-hardened/
helm repo update
# Create namespace
kubectl create namespace spire-system
# Install SPIRE with Controller Manager
helm install spire spiffe/spire \
--namespace spire-system \
--set global.spire.trustDomain="prod.example.com" \
--set global.spire.clusterName="production" \
--set spire-server.replicaCount=3 \
--set spire-server.persistence.enabled=true \
--set spire-server.persistence.size=1GiNamespace Layout
一般的な SPIRE deployment では、次の namespace 構造を使用します。
┌─────────────────────────────────────────────────────────────┐
│ Namespace Layout │
├─────────────────────────────────────────────────────────────┤
│ │
│ spire-system/ │
│ ├── spire-server (StatefulSet, 3 replicas for HA) │
│ ├── spire-server-0, spire-server-1, spire-server-2 │
│ ├── spire-controller-manager (Deployment) │
│ └── spire-bundle-configmap │
│ │
│ spire-agents/ │
│ └── spire-agent (DaemonSet, one per node) │
│ │
│ spiffe-csi-driver/ │
│ └── spiffe-csi-driver (DaemonSet) │
│ │
└─────────────────────────────────────────────────────────────┘High Availability Configuration
production deployment では、高可用性のために SPIRE Server を構成します。
# values-ha.yaml
spire-server:
replicaCount: 3
persistence:
enabled: true
size: 5Gi
storageClass: gp3
dataStore:
sql:
databaseType: postgres
connectionString: "host=spire-postgres dbname=spire sslmode=verify-full"
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: spire-server
topologyKey: kubernetes.io/hostname
spire-agent:
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi# Install with HA values
helm install spire spiffe/spire \
--namespace spire-system \
-f values-ha.yamlVerify Installation
# Check SPIRE Server status
kubectl -n spire-system get pods -l app.kubernetes.io/name=spire-server
# Check SPIRE Agent status
kubectl -n spire-system get pods -l app.kubernetes.io/name=spire-agent
# Verify server health
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server healthcheck
# List registered entries
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry showNode Attestation
Node attestation は、SPIRE Agent と SPIRE Server の間に信頼を確立します。agent は workload の代理で SVID を要求する前に、自身の identity を証明する必要があります。
Attestation Flow
Kubernetes PSAT (Projected Service Account Token)
Kubernetes で推奨される attestation method です。自動的に rotation される projected service account token を使用します。
Server Configuration:
# In server.conf plugins section
NodeAttestor "k8s_psat" {
plugin_data {
clusters = {
"production" = {
service_account_allow_list = ["spire-system:spire-agent"]
audience = ["spire-server"]
}
}
}
}Agent Configuration:
# In agent.conf plugins section
NodeAttestor "k8s_psat" {
plugin_data {
cluster = "production"
token_path = "/var/run/secrets/tokens/spire-agent"
}
}Agent DaemonSet with PSAT:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: spire-agent
namespace: spire-system
spec:
selector:
matchLabels:
app: spire-agent
template:
metadata:
labels:
app: spire-agent
spec:
serviceAccountName: spire-agent
containers:
- name: spire-agent
image: ghcr.io/spiffe/spire-agent:1.12.0
volumeMounts:
- name: spire-token
mountPath: /var/run/secrets/tokens
volumes:
- name: spire-token
projected:
sources:
- serviceAccountToken:
path: spire-agent
expirationSeconds: 7200
audience: spire-serverAWS Instance Identity Document (IID)
EKS または EC2-based Kubernetes cluster では、AWS IID により、AWS の暗号学的に署名された instance metadata を使った強力な node attestation が提供されます。
Server Configuration:
NodeAttestor "aws_iid" {
plugin_data {
access_key_id = "AKIAIOSFODNN7EXAMPLE" # Or use IRSA
secret_access_key = "wJalrXUtnFEMI/K7MDENG" # Or use IRSA
skip_block_device = true
account_ids_for_local_validation = ["123456789012"]
}
}Agent Configuration:
NodeAttestor "aws_iid" {
plugin_data {}
}Join Token (Bootstrap)
初期セットアップまたは non-cloud 環境向けです。使用後に期限切れになる one-time token です。
# Generate a join token on the server
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server token generate \
-spiffeID spiffe://prod.example.com/agent/node-01 \
-ttl 3600
# Output: Token: abc123-def456-ghi789
# Use the token when starting the agent
spire-agent run -joinToken abc123-def456-ghi789Node Attestor Comparison
| Attestor | Security | Automation | Use Case |
|---|---|---|---|
| k8s_psat | High | Fully automatic | Kubernetes clusters |
| aws_iid | High | Fully automatic | AWS EC2/EKS |
| gcp_iit | High | Fully automatic | GCP GKE |
| azure_msi | High | Fully automatic | Azure AKS |
| join_token | Medium | Manual | Bootstrap, air-gapped |
| x509pop | High | Semi-automatic | Existing PKI integration |
Workload Attestation
Workload attestation は、SPIRE Agent に SVID を要求している特定の workload を識別します。agent は attestor を使用して、呼び出し元 process に関する情報を収集します。
Kubernetes Workload Attestor
Kubernetes attestor は kubelet に問い合わせて pod を識別します。
# In agent.conf
WorkloadAttestor "k8s" {
plugin_data {
kubelet_read_only_port = 10255 # Or use secure port
skip_kubelet_verification = false
node_name_env = "MY_NODE_NAME"
}
}Selectors Available:
| Selector | Description | Example |
|---|---|---|
k8s:ns | Namespace | k8s:ns:payments |
k8s:sa | Service Account | k8s:sa:api-server |
k8s:pod-label | Pod label | k8s:pod-label:app:frontend |
k8s:pod-owner | Owner reference | k8s:pod-owner:Deployment:web |
k8s:pod-owner-uid | Owner UID | k8s:pod-owner-uid:abc123 |
k8s:pod-name | Pod name | k8s:pod-name:web-abc123 |
k8s:pod-uid | Pod UID | k8s:pod-uid:def456 |
k8s:container-name | Container name | k8s:container-name:app |
k8s:container-image | Container image | k8s:container-image:nginx:1.25 |
k8s:node-name | Node name | k8s:node-name:node-01 |
Registration Entry Examples
Registration entry は workload selector を SPIFFE ID に対応付けます。
# Register a workload by namespace and service account
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://prod.example.com/ns/payments/sa/api-server \
-parentID spiffe://prod.example.com/agent/k8s-node \
-selector k8s:ns:payments \
-selector k8s:sa:api-server
# Register with pod labels
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://prod.example.com/app/frontend \
-parentID spiffe://prod.example.com/agent/k8s-node \
-selector k8s:ns:web \
-selector k8s:pod-label:app:frontend
# Register with container image (for supply chain security)
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://prod.example.com/verified/nginx \
-parentID spiffe://prod.example.com/agent/k8s-node \
-selector k8s:container-image:nginx:1.25-alpineUnix Workload Attestor
non-Kubernetes workload または追加の process-level attestation 向けです。
WorkloadAttestor "unix" {
plugin_data {
discover_workload_path = true
}
}Unix Selectors:
| Selector | Description |
|---|---|
unix:uid | Process user ID |
unix:gid | Process group ID |
unix:user | Username |
unix:group | Group name |
unix:path | Executable path |
unix:sha256 | Binary SHA256 hash |
Kubernetes Integration
SPIFFE CSI Driver
SPIFFE CSI Driver は、アプリケーション変更を必要とせずに SVID を pod filesystem に直接 mount します。
# Install SPIFFE CSI Driver
helm install spiffe-csi-driver spiffe/spiffe-csi-driver \
--namespace spiffe-csi-driver \
--create-namespace \
--set spire.agentSocketPath=/run/spire/sockets/agent.sockUsing CSI Driver in Pods:
apiVersion: v1
kind: Pod
metadata:
name: my-workload
namespace: payments
spec:
serviceAccountName: api-server
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: spiffe
mountPath: /run/spiffe
readOnly: true
env:
- name: SVID_PATH
value: /run/spiffe/svid.pem
- name: KEY_PATH
value: /run/spiffe/key.pem
- name: BUNDLE_PATH
value: /run/spiffe/bundle.pem
volumes:
- name: spiffe
csi:
driver: csi.spiffe.io
readOnly: trueFiles Mounted by CSI Driver:
/run/spiffe/
├── svid.pem # X.509-SVID certificate
├── key.pem # Private key
├── bundle.pem # Trust bundle (CA certificates)
└── svid.jwt # JWT-SVID (if configured)SPIRE Controller Manager
SPIRE Controller Manager は Kubernetes CRD を使用して workload registration を自動化します。
# Controller Manager is included in the main SPIRE Helm chart
# Verify it's running
kubectl -n spire-system get pods -l app.kubernetes.io/name=spire-controller-managerClusterSPIFFEID Custom Resource:
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: payments-api
spec:
spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
podSelector:
matchLabels:
app: payments-api
namespaceSelector:
matchLabels:
spiffe-enabled: "true"
ttl: 1h
dnsNameTemplates:
- "{{ .PodMeta.Name }}.{{ .PodMeta.Namespace }}.svc.cluster.local"
workloadSelectorTemplates:
- "k8s:ns:{{ .PodMeta.Namespace }}"
- "k8s:sa:{{ .PodSpec.ServiceAccountName }}"Label Namespaces for Auto-Registration:
apiVersion: v1
kind: Namespace
metadata:
name: payments
labels:
spiffe-enabled: "true"Advanced ClusterSPIFFEID Examples:
# Identity based on deployment and container
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: deployment-identity
spec:
spiffeIDTemplate: >-
spiffe://{{ .TrustDomain }}/cluster/{{ .ClusterName }}/ns/{{ .PodMeta.Namespace }}/deploy/{{ index .PodMeta.Labels "app" }}
podSelector:
matchExpressions:
- key: app
operator: Exists
ttl: 30m
federatesWith:
- "partner.example.com"
---
# Identity for jobs with short TTL
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: batch-jobs
spec:
spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/job/{{ .PodMeta.Namespace }}/{{ index .PodMeta.Labels \"job-name\" }}"
podSelector:
matchLabels:
workload-type: batch
ttl: 5mEnvoy SDS Integration
SPIRE Agent は Envoy-based proxy 向けに SDS (Secret Discovery Service) API を公開します。
# Agent configuration for SDS
agent {
# ... other config ...
# Enable SDS for Envoy
sds {
default_svid_name = "default"
default_bundle_name = "ROOTCA"
}
}Envoy Configuration Using SPIRE SDS:
static_resources:
listeners:
- name: mtls_listener
address:
socket_address:
address: 0.0.0.0
port_value: 8443
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificate_sds_secret_configs:
- name: "spiffe://prod.example.com/ns/web/sa/frontend"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: spire_agent
validation_context_sds_secret_config:
name: "ROOTCA"
sds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: spire_agent
clusters:
- name: spire_agent
connect_timeout: 1s
type: STATIC
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: spire_agent
endpoints:
- lb_endpoints:
- endpoint:
address:
pipe:
path: /run/spire/sockets/agent.sockService Mesh Integration
Istio + SPIRE Integration
SPIRE は Istio の組み込み CA (Citadel) を置き換え、より強力な workload identity の保証を提供できます。
Architecture:
┌─────────────────────────────────────────────────────────────┐
│ Istio + SPIRE Integration │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ istiod │ │ SPIRE Server│ │ SPIRE │ │
│ │ (disabled │ │ (CA) │ │ Agent │ │
│ │ CA) │ │ │ │ │ │
│ └─────────────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ │ SVID │ SDS │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Envoy Sidecar (istio-proxy) │ │
│ │ Receives SVID via SPIRE Agent SDS │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘Configure Istio to Use SPIRE:
# IstioOperator configuration
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio-spire
spec:
profile: default
meshConfig:
trustDomain: prod.example.com
values:
global:
caAddress: "" # Disable Citadel
pilot:
env:
PILOT_CERT_PROVIDER: spiffe
SPIFFE_BUNDLE_ENDPOINTS: "prod.example.com|https://spire-server.spire-system:8443"
components:
pilot:
k8s:
env:
- name: PILOT_ENABLE_WORKLOAD_ENTRY_AUTOREGISTRATION
value: "true"Sidecar Injection with SPIRE:
apiVersion: v1
kind: ConfigMap
metadata:
name: istio-sidecar-injector
namespace: istio-system
data:
values: |
{
"global": {
"caAddress": "spire-agent.spire-system:8081",
"pilotCertProvider": "spiffe"
}
}Cilium + SPIRE Mutual Authentication
Cilium は Service 間の mutual authentication に SPIRE を使用できます。
# CiliumNetworkPolicy with SPIFFE identity
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: payments-api-policy
namespace: payments
spec:
endpointSelector:
matchLabels:
app: payments-api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
authentication:
mode: required
egress:
- toEndpoints:
- matchLabels:
app: database
authentication:
mode: requiredCilium SPIRE Configuration:
# Cilium Helm values
authentication:
enabled: true
mutual:
spire:
enabled: true
serverAddress: spire-server.spire-system:8081
trustDomain: prod.example.comLinkerd Identity Trust Anchors
Linkerd は SPIRE が発行した certificate を信頼するよう構成できます。
# Export SPIRE trust bundle
kubectl -n spire-system exec spire-server-0 -- \
/opt/spire/bin/spire-server bundle show -format spiffe > spire-bundle.json
# Install Linkerd with SPIRE trust anchor
linkerd install \
--identity-trust-anchors-file spire-bundle.json \
--identity-issuer-certificate-file spire-ca.crt \
--identity-issuer-key-file spire-ca.key \
| kubectl apply -f -Federation
Federation により、異なる trust domain の workload が相互信頼を確立できます。これは multi-cluster、multi-cloud、cross-organization communication に不可欠です。
Federation Trust Establishment
Configuring Federation
Server A Configuration (us-east.example.com):
server {
trust_domain = "us-east.example.com"
federation {
bundle_endpoint {
address = "0.0.0.0"
port = 8443
}
federates_with "eu-west.example.com" {
bundle_endpoint_url = "https://spire-server-eu.example.com:8443"
bundle_endpoint_profile "https_spiffe" {
endpoint_spiffe_id = "spiffe://eu-west.example.com/spire/server"
}
}
}
}Server B Configuration (eu-west.example.com):
server {
trust_domain = "eu-west.example.com"
federation {
bundle_endpoint {
address = "0.0.0.0"
port = 8443
}
federates_with "us-east.example.com" {
bundle_endpoint_url = "https://spire-server-us.example.com:8443"
bundle_endpoint_profile "https_spiffe" {
endpoint_spiffe_id = "spiffe://us-east.example.com/spire/server"
}
}
}
}Federated Registration Entries
# Register a workload that can communicate with federated domain
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://us-east.example.com/ns/payments/sa/api \
-parentID spiffe://us-east.example.com/agent/node \
-selector k8s:ns:payments \
-selector k8s:sa:api \
-federatesWith "spiffe://eu-west.example.com"ClusterSPIFFEID with Federation:
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: cross-region-api
spec:
spiffeIDTemplate: "spiffe://{{ .TrustDomain }}/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
podSelector:
matchLabels:
federation-enabled: "true"
federatesWith:
- "eu-west.example.com"
- "ap-south.example.com"Multi-Cloud Federation Example
┌─────────────────────────────────────────────────────────────┐
│ Multi-Cloud Federation │
├─────────────────────────────────────────────────────────────┤
│ │
│ AWS (us-east-1) GCP (us-central1) │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Trust Domain: │ │ Trust Domain: │ │
│ │ aws.corp.com │◄────────►│ gcp.corp.com │ │
│ │ │ HTTPS │ │ │
│ │ EKS Cluster │ Bundle │ GKE Cluster │ │
│ └─────────────────┘ Exchange └─────────────────┘ │
│ ▲ ▲ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ On-Prem DC │ │ Azure (eastus) │ │
│ │ Trust Domain: │ │ Trust Domain: │ │
│ │ dc.corp.com │◄────────►│ azure.corp.com │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘EKS Integration
IRSA vs SPIFFE Comparison
| Feature | IRSA | SPIFFE/SPIRE |
|---|---|---|
| Scope | AWS services only | Universal (any service) |
| Identity Format | IAM Role ARN | SPIFFE ID (URI) |
| Token Type | OIDC JWT (AWS STS) | X.509-SVID, JWT-SVID |
| Trust Boundary | Single AWS account (or cross-account) | Any trust domain (multi-cloud) |
| Rotation | Pod restart required | Automatic (no restart) |
| mTLS | Not supported | Native support |
| Service Mesh | Not integrated | Native integration |
| Use Case | AWS API access | Service-to-service auth |
Pod Identity vs SPIRE
| Feature | EKS Pod Identity | SPIRE |
|---|---|---|
| Setup Complexity | Low (AWS managed) | Medium (self-managed) |
| Cloud Lock-in | AWS only | Cloud agnostic |
| Custom Identity | No (IAM only) | Yes (any identity) |
| Federation | Cross-account IAM | Any trust domain |
| On-premises | Not supported | Fully supported |
| Hybrid Cloud | Limited | Full support |
Hybrid Use Cases
Scenario 1: AWS API + Service-to-Service
AWS API access には IRSA を使用し、service-to-service authentication には SPIRE を使用します。
apiVersion: v1
kind: Pod
metadata:
name: hybrid-workload
annotations:
# IRSA for AWS API access
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/my-role
spec:
serviceAccountName: my-service-account
containers:
- name: app
image: myapp:latest
volumeMounts:
# SPIRE for service-to-service mTLS
- name: spiffe
mountPath: /run/spiffe
readOnly: true
env:
# AWS credentials from IRSA
- name: AWS_ROLE_ARN
value: arn:aws:iam::123456789012:role/my-role
- name: AWS_WEB_IDENTITY_TOKEN_FILE
value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
# SPIRE certificates for mTLS
- name: SVID_PATH
value: /run/spiffe/svid.pem
volumes:
- name: spiffe
csi:
driver: csi.spiffe.io
readOnly: trueScenario 2: Cross-Cloud with EKS
# EKS cluster federates with GKE and on-premises
apiVersion: spire.spiffe.io/v1alpha1
kind: ClusterSPIFFEID
metadata:
name: eks-cross-cloud
spec:
spiffeIDTemplate: "spiffe://eks.example.com/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}"
podSelector:
matchLabels:
cross-cloud: "true"
federatesWith:
- "gke.example.com"
- "onprem.example.com"EKS-Specific Node Attestation
EKS では、より強力な node identity のために AWS IID attestation を使用します。
# Server plugin configuration for EKS
NodeAttestor "aws_iid" {
plugin_data {
skip_block_device = true
disable_instance_profile_selectors = false
# Allow specific EKS node groups
agent_path_template = "/eks/{{ .ClusterName }}/{{ .NodeGroupName }}/{{ .InstanceID }}"
}
}
NodeResolver "aws_iid" {
plugin_data {
# Resolve AWS-specific selectors
# tag:kubernetes.io/cluster/my-cluster = owned
# tag:eks:nodegroup-name = my-nodegroup
}
}Best Practices
Trust Domain Naming
| Guideline | Example | Rationale |
|---|---|---|
| Use DNS-like names | prod.example.com | Globally unique, familiar |
| Environment separation | prod.corp.com, staging.corp.com | Prevent cross-env access |
| Avoid IP addresses | Never use IPs | IPs change, names don't |
| Plan for federation | aws.corp.com, gcp.corp.com | Easier multi-cloud setup |
SVID TTL Tuning
# Recommended TTL values
server {
# Root CA certificate - long lived
ca_ttl = "168h" # 7 days
# X.509-SVID for workloads
default_x509_svid_ttl = "1h" # Balance security vs performance
# JWT-SVID for API calls
default_jwt_svid_ttl = "5m" # Short for stateless auth
}TTL Guidelines:
| Workload Type | Recommended TTL | Rationale |
|---|---|---|
| Long-running services | 1h | Balance rotation overhead |
| Batch jobs | 5-15m | Match job duration |
| API gateways | 30m | Frequent rotation acceptable |
| CI/CD jobs | 5m | Short-lived, high security |
High Availability Deployment
# Production HA configuration
spire-server:
replicaCount: 3
# Use external PostgreSQL for HA
dataStore:
sql:
databaseType: postgres
connectionString: "host=spire-postgres-cluster..."
# Pod anti-affinity for spread
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: spire-server
topologyKey: topology.kubernetes.io/zone
# Resource limits
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2000m
memory: 4Gi
# Persistent storage for CA keys
persistence:
enabled: true
storageClass: gp3
size: 10GiKey Rotation
SPIRE は expiration 前に SVID を自動的に rotation します。CA key rotation については次のとおりです。
# Prepare new upstream CA (if using disk-based upstream authority)
# 1. Generate new CA key pair
# 2. Update server configuration
# 3. Restart servers one at a time
# For AWS KMS-based key management
UpstreamAuthority "aws_kms" {
plugin_data {
region = "us-east-1"
key_arn = "arn:aws:kms:us-east-1:123456789012:key/abc123"
}
}Security Hardening
# Agent security configuration
agent {
# Restrict socket access
socket_path = "/run/spire/sockets/agent.sock"
# Require attestation for all workloads
authorized_delegates = []
# Log all workload API requests
log_level = "INFO"
}
# Network policies for SPIRE
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: spire-server-policy
namespace: spire-system
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: spire-server
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: spire-agent
ports:
- port: 8081
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- port: 5432Troubleshooting
Common Issues
Issue: Agent Cannot Connect to Server
# Check agent logs
kubectl -n spire-system logs -l app.kubernetes.io/name=spire-agent
# Verify server is reachable
kubectl -n spire-system exec -it spire-agent-xxxxx -- \
nc -zv spire-server 8081
# Check node attestation
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server agent listIssue: Workload Cannot Get SVID
# Verify registration entry exists
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server entry show
# Check workload attestation from agent
kubectl -n spire-system exec -it spire-agent-xxxxx -- \
/opt/spire/bin/spire-agent api fetch x509 -socketPath /run/spire/sockets/agent.sock
# Debug workload selectors
kubectl -n spire-system exec -it spire-agent-xxxxx -- \
/opt/spire/bin/spire-agent api fetch x509 -socketPath /run/spire/sockets/agent.sock -debugIssue: CSI Driver Not Mounting SVIDs
# Check CSI driver pods
kubectl -n spiffe-csi-driver get pods
# Verify CSI driver registration
kubectl get csidrivers csi.spiffe.io
# Check events on failing pod
kubectl describe pod <pod-name> -n <namespace>Health Checks
# Server health
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server healthcheck
# Agent health
kubectl -n spire-system exec -it spire-agent-xxxxx -- \
/opt/spire/bin/spire-agent healthcheck
# Bundle status
kubectl -n spire-system exec -it spire-server-0 -- \
/opt/spire/bin/spire-server bundle showSummary and References
Key Takeaways
SPIFFE provides universal workload identity — cloud、cluster、platform を横断して機能する標準ベースのアプローチ
SPIRE implements SPIFFE at scale — 自動化された attestation と SVID management を備えた production-ready な実装
Zero-code integration — CSI driver と service mesh integration により、アプリケーション変更は不要
Federation enables multi-cluster/multi-cloud — Trust domain は cross-boundary authentication のために federation できます
Complements cloud-native identity — SPIFFE は包括的な identity management のために IRSA/Pod Identity と併用できます
Architecture Decision Guide
| Requirement | Recommendation |
|---|---|
| AWS-only, AWS APIs | Use IRSA or Pod Identity |
| Multi-cloud services | Use SPIFFE/SPIRE |
| Service mesh mTLS | Use SPIFFE/SPIRE |
| Hybrid cloud | Use SPIFFE/SPIRE |
| Cross-organization trust | Use SPIFFE Federation |
| Simple setup, single cluster | Start with cloud-native (IRSA), add SPIRE later |
References
Official Documentation:
Integration Guides:
CNCF Resources: