Skip to content

필사 모드: SPIFFE/SPIRE 워크로드 아이덴티티 — 시크릿 없는 서비스 간 인증

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며 — 시크릿을 배포하지 않는 인증은 가능한가

서비스 간 인증의 전통적 해법은 시크릿 배포였습니다. API 키, 공유 패스워드, 정적 인증서를 만들어 각 서비스에 나눠주는 방식입니다. 그 결과가 오늘날의 **시크릿 스프롤(secret sprawl)** 입니다. 환경변수, CI 변수, 코드 저장소, 채팅 로그에 흩어진 자격 증명은 유출 사고의 단골 원인이며, 로테이션은 모두가 미루는 숙제가 되었습니다.

2026년의 흐름은 명확합니다. 머신, 서비스, 파이프라인, 그리고 AI agent까지 — **non-human identity가 사람 계정 수를 수십 배 이상 앞지른** 환경에서, 시크릿을 "나눠주는" 모델은 더 이상 운영 가능하지 않습니다. 대안은 워크로드가 자신의 속성(어디서 실행되는가, 누가 실행했는가)으로 신원을 **증명받고**, 짧은 수명의 암호학적 신원 문서를 **자동 발급**받는 모델입니다. 이 모델의 표준이 [SPIFFE](https://spiffe.io/docs/)(Secure Production Identity Framework For Everyone)이고, 레퍼런스 구현이 SPIRE입니다.

이 글에서는 SPIFFE ID와 SVID 개념부터 SPIRE 아키텍처, 쿠버네티스 배포 실전, Envoy SDS 통합을 통한 자동 mTLS, federation, Vault/cert-manager 비교, 그리고 transaction tokens와 AI agent identity로의 확장까지 다룹니다.

시크릿 스프롤 문제와 non-human identity 트렌드

전통적 시크릿 기반 인증의 구조적 문제를 먼저 정리합니다.

| 문제 | 내용 |

| -------------- | ---------------------------------------------------------------- |

| 부트스트랩 역설 | 시크릿을 안전하게 전달하려면 또 다른 시크릿(접근 자격)이 필요 |

| 로테이션 부담 | 수명이 길수록 유출 피해가 크지만, 로테이션은 수동이고 깨지기 쉬움 |

| 소유 불명 | 이 API 키를 누가 왜 만들었는지 6개월 후에는 아무도 모름 |

| 복제 용이 | 시크릿은 복사되는 순간 추적 불가, 어디서 쓰여도 구분 불가 |

| 감사 곤란 | "키를 가진 누군가"만 알 수 있을 뿐 워크로드 단위 식별 불가 |

여기에 non-human identity의 폭증이 겹칩니다. 마이크로서비스, 배치 잡, CI 러너, 서버리스 함수에 이어 AI agent가 추가되면서, 신원 관리의 무게중심이 사람에서 워크로드로 이동했습니다. 업계 조사들은 non-human identity가 사람 identity의 수십 배에 달한다고 보고하며, 이들의 자격 증명 관리가 침해 사고의 주요 원인으로 지목됩니다.

SPIFFE의 답은 발상의 전환입니다. **시크릿을 배포하지 말고, 신원을 발급하라.** 워크로드는 실행 환경의 속성으로 자신을 증명하고(attestation), 플랫폼은 짧은 수명의 신원 문서(SVID)를 자동으로 발급/갱신합니다. 사람이 만지는 시크릿이 사라집니다.

SPIFFE 핵심 개념 — SPIFFE ID와 SVID

SPIFFE ID

SPIFFE ID는 워크로드를 식별하는 URI입니다. 형식은 spiffe 스킴 + 신뢰 도메인 + 경로로 구성됩니다.

spiffe://prod.example.com/ns/orders/sa/orders-sa

└─┬──┘ └──────┬───────┘ └─────────┬──────────┘

스킴 신뢰 도메인 워크로드 경로

(trust domain) (예: 네임스페이스/서비스어카운트)

- **신뢰 도메인(trust domain)** 은 신원 발급의 권위 단위입니다. 보통 조직이나 환경(프로덕션/스테이징) 단위로 나눕니다.

- 경로는 조직이 자유롭게 설계합니다. 쿠버네티스라면 네임스페이스와 서비스어카운트를 인코딩하는 패턴이 일반적입니다.

SVID — 신원 문서

SVID(SPIFFE Verifiable Identity Document)는 SPIFFE ID를 담은 검증 가능한 문서로, 두 형식이 있습니다.

| 항목 | X.509-SVID | JWT-SVID |

| --------- | --------------------------------------- | ----------------------------------------- |

| 형식 | X.509 인증서 (SAN URI에 SPIFFE ID) | JWT (sub 클레임에 SPIFFE ID) |

| 용도 | mTLS 연결의 양방향 인증 | L7 프록시 경유 등 TLS가 끝나는 구간의 인증 |

| 수명 | 수 분~수 시간 (기본 1시간 수준) | 수 분 (audience 지정 필수) |

| 재전송 위험 | 낮음 (키 소유 증명) | 존재 (탈취 시 수명 내 재사용 가능) |

| 권장 | 기본 선택지 | mTLS가 불가능한 구간의 보조 수단 |

X.509-SVID가 기본이고, JWT-SVID는 mTLS를 끝까지 유지할 수 없는 구간(L7 로드밸런서 경유 등)의 보조 수단입니다. 두 형식 모두 핵심은 **짧은 수명 + 자동 갱신**으로, 유출되어도 피해 시간이 분 단위로 제한됩니다.

신뢰 번들

검증자는 신뢰 도메인별 CA 공개키 묶음인 **trust bundle**로 SVID를 검증합니다. 번들 배포와 갱신도 SPIRE가 자동화합니다.

SPIRE 아키텍처 — server, agent, attestation

SPIRE는 SPIFFE의 레퍼런스 구현으로, server와 agent의 2계층 구조입니다.

+--------------------------------------------------------------+

| SPIRE Server |

| - 등록 엔트리(registration entries) 저장 |

| - CA로서 SVID 서명 (또는 upstream CA에 위임) |

| - node attestation 검증 |

+------------------------------+-------------------------------+

| (1) node attestation

| "이 노드/에이전트는 진짜인가"

+------------------------------+-------------------------------+

| SPIRE Agent (노드마다 DaemonSet) |

| - Workload API (유닉스 소켓) 노출 |

| - workload attestation 수행 |

| - SVID 캐싱/갱신 |

+------------------------------+-------------------------------+

| (2) workload attestation

| "이 프로세스는 어떤 워크로드인가"

+------------------+------------------+

| | |

+----+----+ +----+----+ +----+----+

| Pod A | | Pod B | | Pod C |

| (orders)| | (pay) | | (envoy) |

+---------+ +---------+ +---------+

동작 흐름은 다음과 같습니다.

1. **Node attestation** — agent가 server에 "나는 정당한 노드에서 실행 중"임을 증명합니다. 쿠버네티스에서는 agent의 서비스어카운트 토큰을 server가 TokenReview API로 검증하는 k8s_psat 방식이 표준입니다. AWS/GCP/Azure에서는 인스턴스 신원 문서 기반의 attestor를 씁니다.

2. **Workload attestation** — 워크로드가 agent의 Workload API 소켓에 접속하면, agent는 호출 프로세스의 커널 수준 정보(쿠버네티스에서는 해당 파드의 네임스페이스, 서비스어카운트, 레이블 등)를 수집합니다.

3. **등록 엔트리 매칭** — 수집된 셀렉터가 server에 등록된 엔트리와 일치하면, 해당 SPIFFE ID의 SVID를 발급합니다.

4. **자동 갱신** — agent는 SVID 만료 전에 자동으로 재발급받아 워크로드에 푸시합니다.

핵심은 **워크로드가 어떤 시크릿도 미리 가질 필요가 없다**는 점입니다. 신원은 "무엇을 알고 있는가(시크릿)"가 아니라 "어디서 어떻게 실행되고 있는가(속성)"에서 도출됩니다.

쿠버네티스 배포 실전

프로덕션에서는 공식 [SPIRE Helm 차트](https://github.com/spiffe/helm-charts-hardened)를 권장하지만, 구조 이해를 위해 핵심 매니페스트를 직접 봅니다. 먼저 server 설정입니다.

apiVersion: v1

kind: ConfigMap

metadata:

name: spire-server

namespace: spire

data:

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"

}

plugins {

DataStore "sql" {

plugin_data {

database_type = "sqlite3"

connection_string = "/run/spire/data/datastore.sqlite3"

}

}

NodeAttestor "k8s_psat" {

plugin_data {

clusters = {

"prod-cluster" = {

service_account_allow_list = ["spire:spire-agent"]

}

}

}

}

KeyManager "disk" {

plugin_data {

keys_path = "/run/spire/data/keys.json"

}

}

Notifier "k8sbundle" {

plugin_data {

namespace = "spire"

}

}

}

apiVersion: apps/v1

kind: StatefulSet

metadata:

name: spire-server

namespace: spire

spec:

serviceName: spire-server

replicas: 1

selector:

matchLabels:

app: spire-server

template:

metadata:

labels:

app: spire-server

spec:

serviceAccountName: spire-server

containers:

- name: spire-server

image: ghcr.io/spiffe/spire-server:1.12.0

args: ['-config', '/run/spire/config/server.conf']

ports:

- containerPort: 8081

volumeMounts:

- name: spire-config

mountPath: /run/spire/config

readOnly: true

- name: spire-data

mountPath: /run/spire/data

volumes:

- name: spire-config

configMap:

name: spire-server

volumeClaimTemplates:

- metadata:

name: spire-data

spec:

accessModes: ['ReadWriteOnce']

resources:

requests:

storage: 1Gi

agent는 DaemonSet으로 모든 노드에 배포합니다.

apiVersion: v1

kind: ConfigMap

metadata:

name: spire-agent

namespace: spire

data:

agent.conf: |

agent {

data_dir = "/run/spire"

log_level = "INFO"

server_address = "spire-server.spire.svc.cluster.local"

server_port = "8081"

socket_path = "/run/spire/sockets/agent.sock"

trust_domain = "prod.example.com"

trust_bundle_path = "/run/spire/bundle/bundle.crt"

}

plugins {

NodeAttestor "k8s_psat" {

plugin_data {

cluster = "prod-cluster"

}

}

KeyManager "memory" {

plugin_data {}

}

WorkloadAttestor "k8s" {

plugin_data {

disable_container_selectors = false

}

}

}

apiVersion: apps/v1

kind: DaemonSet

metadata:

name: spire-agent

namespace: spire

spec:

selector:

matchLabels:

app: spire-agent

template:

metadata:

labels:

app: spire-agent

spec:

hostPID: true

serviceAccountName: spire-agent

containers:

- name: spire-agent

image: ghcr.io/spiffe/spire-agent:1.12.0

args: ['-config', '/run/spire/config/agent.conf']

volumeMounts:

- name: spire-config

mountPath: /run/spire/config

readOnly: true

- name: spire-bundle

mountPath: /run/spire/bundle

readOnly: true

- name: spire-agent-socket

mountPath: /run/spire/sockets

volumes:

- name: spire-config

configMap:

name: spire-agent

- name: spire-bundle

configMap:

name: spire-bundle

- name: spire-agent-socket

hostPath:

path: /run/spire/sockets

type: DirectoryOrCreate

마지막으로 워크로드를 등록합니다. orders 네임스페이스의 orders-sa 서비스어카운트로 실행되는 파드에 SPIFFE ID를 부여하는 엔트리입니다.

kubectl exec -n spire spire-server-0 -- \

/opt/spire/bin/spire-server entry create \

-spiffeID spiffe://prod.example.com/ns/orders/sa/orders-sa \

-parentID spiffe://prod.example.com/spire/agent/k8s_psat/prod-cluster/NODE_UUID \

-selector k8s:ns:orders \

-selector k8s:sa:orders-sa

수동 등록은 규모가 커지면 유지하기 어렵습니다. 실무에서는 **SPIRE Controller Manager**를 함께 배포해, CRD(ClusterSPIFFEID)로 등록을 선언적으로 관리합니다.

apiVersion: spire.spiffe.io/v1alpha1

kind: ClusterSPIFFEID

metadata:

name: default-workload-id

spec:

spiffeIDTemplate: 'spiffe://prod.example.com/ns/{{ .PodMeta.Namespace }}/sa/{{ .PodSpec.ServiceAccountName }}'

podSelector:

matchLabels:

spiffe.io/spire-managed-identity: 'true'

이렇게 하면 레이블이 붙은 모든 파드가 네임스페이스/서비스어카운트 기반 SPIFFE ID를 자동으로 받습니다.

Envoy SDS 통합 — 자동 mTLS

애플리케이션 코드를 바꾸지 않고 mTLS를 적용하는 표준 패턴은 Envoy 사이드카 + SPIRE agent의 SDS(Secret Discovery Service) 통합입니다. SPIRE agent는 SDS 서버 역할을 할 수 있어, Envoy가 인증서를 파일이 아닌 API로 받아 갑니다. 갱신도 무중단으로 일어납니다.

Envoy 사이드카 설정 (발췌) — orders 서비스

static_resources:

clusters:

SPIRE agent의 Workload API를 SDS 클러스터로 등록

- name: spire_agent

connect_timeout: 1s

http2_protocol_options: {}

load_assignment:

cluster_name: spire_agent

endpoints:

- lb_endpoints:

- endpoint:

address:

pipe:

path: /run/spire/sockets/agent.sock

업스트림: payments 서비스로의 mTLS 연결

- name: payments_upstream

connect_timeout: 2s

type: STRICT_DNS

load_assignment:

cluster_name: payments_upstream

endpoints:

- lb_endpoints:

- endpoint:

address:

socket_address:

address: payments.payments.svc.cluster.local

port_value: 8443

transport_socket:

name: envoy.transport_sockets.tls

typed_config:

'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext

common_tls_context:

내 신원(X.509-SVID)을 SDS로 받아온다

tls_certificate_sds_secret_configs:

- name: spiffe://prod.example.com/ns/orders/sa/orders-sa

sds_config:

api_config_source:

api_type: GRPC

transport_api_version: V3

grpc_services:

- envoy_grpc:

cluster_name: spire_agent

상대 검증: 신뢰 번들 + 기대하는 SPIFFE ID

combined_validation_context:

default_validation_context:

match_typed_subject_alt_names:

- san_type: URI

matcher:

exact: spiffe://prod.example.com/ns/payments/sa/payments-sa

validation_context_sds_secret_config:

name: spiffe://prod.example.com

sds_config:

api_config_source:

api_type: GRPC

transport_api_version: V3

grpc_services:

- envoy_grpc:

cluster_name: spire_agent

이 설정 한 벌로 다음이 자동화됩니다.

- orders 사이드카는 자신의 X.509-SVID를 SPIRE에서 받아 TLS 클라이언트 인증서로 사용합니다.

- payments 쪽 인증서가 신뢰 번들로 검증되고, SAN URI가 기대한 SPIFFE ID와 정확히 일치하는지 확인합니다. **CA가 같다고 통과시키는 것이 아니라 워크로드 단위로 인가**하는 것이 포인트입니다.

- 인증서 갱신(1시간 수명)은 SDS 푸시로 무중단 처리됩니다. 사람이 만지는 인증서 파일이 존재하지 않습니다.

사이드카 없이 애플리케이션에서 직접 쓰려면 [go-spiffe](https://github.com/spiffe/go-spiffe) 같은 SDK로 Workload API를 호출합니다.

// go-spiffe v2로 mTLS 클라이언트 만들기 (발췌)

source, err := workloadapi.NewX509Source(ctx)

if err != nil {

log.Fatal(err)

}

defer source.Close()

serverID := spiffeid.RequireFromString("spiffe://prod.example.com/ns/payments/sa/payments-sa")

tlsConfig := tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeID(serverID))

client := &http.Client{

Transport: &http.Transport{TLSClientConfig: tlsConfig},

}

resp, err := client.Get("https://payments.payments.svc.cluster.local:8443/healthz")

Istio와 SPIFFE 호환성

Istio의 mTLS 신원 체계는 처음부터 SPIFFE 형식입니다. 사이드카(또는 ambient의 ztunnel)가 받는 인증서의 SAN URI는 다음 형식입니다.

spiffe://cluster.local/ns/orders/sa/orders-sa

따라서 "Istio를 쓰면 SPIRE가 필요 없는가"라는 질문에는 다음과 같이 답할 수 있습니다.

- **메시 내부만 필요하다면** — Istio 내장 CA(istiod)로 충분합니다. 별도 SPIRE 없이 SPIFFE 형식의 워크로드 신원과 자동 mTLS를 얻습니다.

- **메시 밖(VM, 다른 클러스터, 메시 미적용 워크로드, CI 러너)까지 단일 신원 체계가 필요하다면** — SPIRE를 신원의 단일 소스로 두는 구성이 유효합니다. Istio는 SPIRE를 외부 CA로 통합할 수 있고(SDS 경유), 이 경우 메시 안팎의 워크로드가 같은 신뢰 도메인의 SVID로 상호 인증합니다.

- 주의점: Istio 기본 신뢰 도메인은 cluster.local이므로, 조직 차원의 신뢰 도메인 전략(예: prod.example.com)과 일치시키려면 meshConfig의 trustDomain 설정과 SPIRE의 trust_domain을 정렬해야 합니다.

Federation — 신뢰 도메인 간 인증

서로 다른 신뢰 도메인(다른 클러스터, 다른 조직, 다른 클라우드)의 워크로드가 상호 인증하려면 **trust bundle을 교환**해야 합니다. SPIRE의 federation 기능이 이를 자동화합니다.

SPIRE Server 설정에 federation 추가 (server.conf 발췌)

federates_with로 상대 도메인의 번들 엔드포인트를 지정

federation {

bundle_endpoint {

address = "0.0.0.0"

port = 8443

}

federates_with "partner.example.org" {

bundle_endpoint_url = "https://spire.partner.example.org:8443"

bundle_endpoint_profile "https_spiffe" {

endpoint_spiffe_id = "spiffe://partner.example.org/spire/server"

}

}

}

등록 엔트리에도 federation 대상을 명시합니다.

spire-server entry create \

-spiffeID spiffe://prod.example.com/ns/orders/sa/orders-sa \

-selector k8s:ns:orders -selector k8s:sa:orders-sa \

-federatesWith spiffe://partner.example.org

이렇게 하면 orders 워크로드는 자기 SVID와 함께 상대 도메인의 trust bundle을 받아, partner 도메인의 워크로드와 mTLS를 맺을 수 있습니다. 번들 갱신은 양쪽 server가 주기적으로 동기화합니다. 멀티 클러스터, 하이브리드 클라우드, 조직 간 B2B 연동에서 "공유 CA 없이" 상호 인증을 구성하는 표준 방법입니다.

Vault / cert-manager와의 비교

"인증서를 자동 발급한다"는 점에서 비슷해 보이는 도구들과의 역할 구분을 정리합니다.

| 항목 | SPIRE | HashiCorp Vault | cert-manager |

| ------------ | -------------------------------------- | ---------------------------------------- | --------------------------------------- |

| 본질 | 워크로드 신원 발급 플랫폼 | 시크릿 관리 + PKI 발급 엔진 | 쿠버네티스 인증서 라이프사이클 관리 |

| 신원 증명 | attestation (무자격 부트스트랩) | 인증 방법 필요 (k8s auth 등) | 직접 증명 없음 (리소스 권한 기반) |

| 발급 대상 | 워크로드 단위 SVID (X.509/JWT) | 범용 시크릿, PKI 인증서 | 주로 TLS 서버 인증서 (Ingress 등) |

| 수명 철학 | 분~시간 단위, 완전 자동 갱신 | 설정에 따름 (짧게도 길게도) | 보통 수십 일, 자동 갱신 |

| 표준 | SPIFFE (CNCF graduated) | 독자 API | ACME 등 인증서 표준 |

| 상호 보완 | Vault의 인증 수단으로 SVID 사용 가능 | SPIRE upstream CA로 Vault PKI 사용 가능 | 메시 외부 인증서와 병행 사용 |

요점은 경쟁이 아니라 조합입니다. 자주 쓰는 구성은 다음과 같습니다.

- **SPIRE가 신원을, Vault가 시크릿을** — 워크로드가 SVID로 Vault에 로그인(JWT/cert auth)해 DB 비밀번호 같은 잔존 시크릿을 받습니다. "시크릿에 접근하기 위한 시크릿"이 사라져 부트스트랩 역설이 풀립니다.

- **Vault PKI를 SPIRE의 UpstreamAuthority로** — 조직 PKI 체계 안에 SPIRE CA를 종속시켜 거버넌스를 유지합니다.

- **cert-manager는 엣지 TLS를** — 외부 노출 도메인의 서버 인증서(Let’s Encrypt 등)는 cert-manager가, 내부 워크로드 간 mTLS는 SPIRE가 담당하는 분업이 자연스럽습니다.

워크로드 identity와 사용자 identity의 연결

실제 요청에는 두 신원이 공존합니다. "orders 서비스(워크로드)가 user-1234(사용자)를 대신해 payments를 호출한다"를 어떻게 표현할까요?

- **전송 계층** — mTLS(X.509-SVID)로 호출자 워크로드를 인증합니다.

- **요청 계층** — 사용자 컨텍스트는 JWT로 운반합니다. 앞 글에서 다룬 token exchange([RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693))가 위임 체인을 기록합니다.

- **transaction tokens** — OAuth WG에서 논의 중인 [Transaction Tokens 드래프트](https://datatracker.ietf.org/doc/draft-ietf-oauth-transaction-tokens/)는 이 패턴을 표준화합니다. 외부 토큰을 신뢰 경계 진입 시점에 짧은 수명(분 단위)의 내부 전용 토큰으로 교환하고, 거기에 사용자 신원 + 요청 컨텍스트 + 호출 체인을 담아 내부 호출 전체에 전파합니다. 이때 transaction token 서비스에 교환을 요청하는 주체의 인증이 바로 워크로드 identity(SVID)입니다.

[사용자 JWT] --> Gateway --(exchange)--> [Txn-Token: 사용자 + 컨텍스트 + 체인]

|

v

orders (SVID로 mTLS) --> payments (SVID로 mTLS)

요청마다: Txn-Token 검증 + 호출자 SPIFFE ID 확인

워크로드 신원(SPIFFE)과 사용자 신원(OIDC)이 별개 체계가 아니라 한 요청 안에서 결합되는 것 — 이것이 2026년 Zero Trust 아키텍처의 완성형입니다.

AI agent identity로의 확장

non-human identity의 최신 변곡점은 AI agent입니다. agent는 전통적 서비스보다 동적으로 생성/소멸하고, 사용자를 대신해 행동하며, 도구(tool) 호출로 권한을 행사합니다. SPIFFE 관점에서의 적용 방향은 다음과 같습니다.

- **agent 런타임도 워크로드입니다.** agent를 실행하는 프로세스/파드에 SVID를 부여하면, "어떤 agent 런타임이 이 도구를 호출했는가"가 암호학적으로 식별됩니다. 정적 API 키를 agent에 심는 관행을 대체합니다.

- **위임 체인의 결합** — agent가 사용자를 대신해 행동할 때, 워크로드 신원(SVID) + 사용자 위임(token exchange의 act 클레임 또는 transaction token)을 함께 검증합니다. "이 agent가, 이 사용자를 대신해, 이 범위 안에서"가 모두 토큰과 인증서로 증명됩니다.

- **MCP 생태계와의 접점** — MCP(Model Context Protocol) 서버가 OAuth 보호 리소스로 표준화되면서(Keycloak 26.6의 CIMD 실험 지원 등), agent의 도구 접근에도 표준 토큰 흐름이 적용되고 있습니다. 도구 서버 간 mTLS에는 SPIFFE가 자연스러운 짝입니다.

- **짧은 수명의 가치 극대화** — agent는 행동 반경이 넓어 자격 증명 유출의 파급이 큽니다. 분 단위 SVID와 audience가 좁은 JWT-SVID의 조합은 agent 환경에서 특히 효과적입니다.

도입 시 운영 과제

SPIRE 도입에서 실제로 마주치는 과제와 대응을 정리합니다.

1. **SPIRE 자체의 가용성** — SVID 수명이 1시간이면 SPIRE가 1시간 이상 죽었을 때 갱신이 멈춥니다. server를 다중화(공유 데이터스토어 + 다중 레플리카)하고, agent 캐시로 단기 장애를 흡수하며, SVID 수명과 장애 허용 시간을 함께 설계해야 합니다.

2. **등록 엔트리 거버넌스** — 셀렉터를 느슨하게 잡으면(예: 네임스페이스만) 의도보다 넓은 워크로드가 같은 신원을 받습니다. ClusterSPIFFEID 템플릿을 코드 리뷰 대상으로 관리하고, 신원 부여 기준을 명문화합니다.

3. **점진적 적용 경로** — 전 서비스 동시 전환은 불가능합니다. permissive(평문+mTLS 병행) 단계를 거쳐 STRICT로 조이는 경로, 그리고 mTLS 적용률을 측정하는 대시보드가 필요합니다.

4. **비SPIFFE 시스템과의 경계** — 레거시 DB, 외부 SaaS는 여전히 패스워드/API 키를 요구합니다. 이 잔존 시크릿은 Vault로 모으고, Vault 접근을 SVID로 인증하는 식으로 "시크릿의 뿌리"를 하나로 줄입니다.

5. **관측성** — SVID 발급/갱신 실패, attestation 실패, 번들 동기화 지연을 메트릭으로 보고 알람을 겁니다. 인증서 만료로 인한 연쇄 장애는 조용히 시작되므로 만료 임박 SVID 비율이 좋은 선행 지표입니다.

6. **시계 동기화와 키 보호** — 짧은 수명 인증서는 클럭 스큐에 민감합니다. NTP 모니터링은 필수이고, server의 서명 키는 KMS/HSM 백엔드(KeyManager 플러그인)로 보호하는 것이 권장됩니다.

마치며

SPIFFE/SPIRE가 제시하는 전환을 한 문장으로 요약하면 이렇습니다. **시크릿을 옮기지 말고, 신원을 발급하라.** attestation으로 부트스트랩 역설을 풀고, 짧은 수명의 SVID로 로테이션을 무의미하게 만들며, SPIFFE ID라는 표준 네이밍으로 워크로드 단위 인가와 federation을 가능하게 합니다. Envoy SDS나 Istio 통합을 쓰면 애플리케이션 코드 수정 없이도 자동 mTLS에 도달할 수 있습니다.

그리고 이 기반은 워크로드를 넘어 확장되고 있습니다. 사용자 신원(OIDC), 위임(token exchange, transaction tokens), AI agent identity가 SPIFFE 워크로드 신원과 한 요청 안에서 결합되는 것이 2026년 Zero Trust 스택의 표준 형태입니다. 시크릿 스프롤에 지친 조직이라면, 신원 기반 인증으로의 전환을 더 미룰 이유가 없습니다.

참고 자료

- [SPIFFE 공식 문서](https://spiffe.io/docs/)

- [SPIRE 공식 문서](https://spiffe.io/docs/latest/spire-about/)

- [SPIFFE ID / SVID 표준 명세 (GitHub)](https://github.com/spiffe/spiffe/tree/main/standards)

- [SPIRE Helm Charts (hardened)](https://github.com/spiffe/helm-charts-hardened)

- [go-spiffe v2 SDK](https://github.com/spiffe/go-spiffe)

- [Envoy SDS와 SPIRE 통합 가이드](https://spiffe.io/docs/latest/microservices/envoy/)

- [Istio Security 개념 문서](https://istio.io/latest/docs/concepts/security/)

- [RFC 8693 — OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693)

- [OAuth Transaction Tokens 드래프트](https://datatracker.ietf.org/doc/draft-ietf-oauth-transaction-tokens/)

- [RFC 7519 — JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)

- [RFC 9700 — Best Current Practice for OAuth 2.0 Security](https://datatracker.ietf.org/doc/html/rfc9700)

- [NIST SP 800-207 Zero Trust Architecture](https://csrc.nist.gov/pubs/sp/800/207/final)

- [HashiCorp Vault 문서](https://developer.hashicorp.com/vault/docs)

- [cert-manager 문서](https://cert-manager.io/docs/)

- [Keycloak 공식 문서](https://www.keycloak.org/documentation)

현재 단락 (1/383)

서비스 간 인증의 전통적 해법은 시크릿 배포였습니다. API 키, 공유 패스워드, 정적 인증서를 만들어 각 서비스에 나눠주는 방식입니다. 그 결과가 오늘날의 **시크릿 스프롤(se...

작성 글자: 0원문 글자: 14,596작성 단락: 0/383