Skip to content

SVID 三层配置 · 逐项实战手册(Step-by-Step,含真实 A/B 与负向)

配套 SVID.md。这里把每个配置项到底影响 SVID 的什么,用能亲手跑的正向/负向/AB 实验一条条钉死。 所有 实测 段落是在本 lab 真跑出来的输出(server VM 192.168.71.159、agent VM 192.168.71.126、K3S 192.168.71.3)。

0. 实验沙箱与统一观测口径

为不污染文档里那两条正式 entry(/vm/web/ns/demo/sa/svc),实验都在一条沙箱条目 /lab/exp 上做,挂在 VM agent 下、默认用 uid 1002(用户 other)——因为 uid 1002 平时不匹配任何 entry,观测最干净。

两个小工具(已在仓库 demos/,也已放到对应 VM 的 /opt/spire/):

工具在哪跑作用
exp-entry.sh "<selectors>" "<dns>" "<ttl>"server/lab/exp 重置成给定形态(先删后建)
observe-svid.sh <uid>VM agent以该 uid 取一次 SVID,打印 URI/Subject/DNS/NotAfter/公钥类型;取不到就报"负向命中"
bash
# server 上(root),设 VM agent 的 SPIFFE ID 为 parent:
export EXP_PARENT="spiffe://spire.qstarstar.com/spire/agent/join_token/049212fc-…"   # spire-server agent list 里查
sh /opt/spire/exp-entry.sh "unix:uid:1002" "" 3600     # 建基线

# agent 上(root),观测:
sh /opt/spire/observe-svid.sh 1002
#   ✔ URI SAN : URI:spiffe://spire.qstarstar.com/lab/exp
#     Subject : C = US, O = SPIRE
#     NotAfter: … (+1h)   PubKey: id-ecPublicKey (256bit)

entry动态的(agent 几秒内自动同步,无需重启);改 server.conf / agent.conf重启对应进程才生效。下面每条会标注。

通用查看命令:

bash
spire-server entry show   -socketPath /tmp/spire-server/private/api.sock     # 看所有 entry
spire-server agent  list  -socketPath /tmp/spire-server/private/api.sock     # 看 agent 身份/认证方式
openssl x509 -in svid.pem -noout -text                                       # 解 X.509 全字段

层① server.conf(全局)—— 定 CA 与"默认/上限",改后需 systemctl restart spire-server

1.1 trust_domain —— 信任域(所有身份的根)

  • 影响什么:所有 SPIFFE ID 的前缀 spiffe://<trust_domain>/…;CA 证书的 URI SAN;换域=换一整套信任根。
  • 怎么查看:openssl x509 -in captured/trust-bundle.pem -noout -ext subjectAltNameURI:spiffe://spire.qstarstar.com
  • 实验:改它是破坏性的(旧 SVID/agent 全失效,要清库重认证),本 lab 不实跑。预期:改成 example.org 重启+清 data/ 后,新签的一切都变 spiffe://example.org/…

1.2 ca_ttl —— CA 寿命,封顶所有下游 SVID 【实测·最重要】

  • 影响什么:CA 证书自身寿命;并且 SVID 到期时间被"CA 到期"死死封顶——SVID TTL ≤ CA 剩余寿命
  • AB / 负向实验:给 /lab/exp 一个超过 CA 剩余寿命-x509SVIDTTL(48h),看它不会真活 48h。
text
参考:CA 到期 = Jul 10 15:31 GMT(ca_ttl=24h);实验时 now = Jul 9 17:06 GMT
── -x509SVIDTTL 3600 (1h)   → NotAfter Jul 9 18:06:35   (now+1h,正常)
── -x509SVIDTTL 300  (5min) → NotAfter Jul 9 17:11:45   (now+5min,正常)
── -x509SVIDTTL 172800(48h) → NotAfter Jul 10 15:31:04  ← 不是 +48h!被 CA 到期封顶

结论:要 SVID 能签长,先得 ca_ttl 够长。这是排查"我 TTL 配了很大却没生效"的头号原因。

1.3 default_x509_svid_ttl / default_jwt_svid_ttl —— 默认 TTL(entry 没配时用)【实测】

  • 影响什么:entry 没写 -x509SVIDTTL/-jwtSVIDTTL 时,SVID 用这个默认值。
  • AB 实验:建一条不带 -x509SVIDTTL/lab/exp,改 server 默认值,看它跟着变。
text
default_x509_svid_ttl = "1h" 时:  entry 不写 TTL → NotAfter = now+1h   (now 17:11 → 18:11)
改成          "10m" 重启后:      entry 不写 TTL → NotAfter = now+10m  (now 17:12 → 17:22)
  • JWT 默认:抓到的 JWT exp-iat = 1783617389-1783617089 = 300s = default_jwt_svid_ttl 默认 5m。

1.4 jwt_issuer —— 给 JWT-SVID 加 iss claim 【实测】

  • 影响什么:JWT-SVID payload 里是否有 iss(OIDC 场景常需要)。对 X.509 无影响。
  • AB 实验(注意 JWT 按 (spiffeID,audience) 缓存,验证要换新 audience 绕缓存):
text
未配 jwt_issuer:  {"aud":["test-aud"], "sub":"spiffe://…/lab/exp", "exp":…, "iat":…}          ← 无 iss
配 jwt_issuer="https://spire.qstarstar.com" 重启,换新 audience 现签:
                  {"aud":["aud-withiss"], "iss":"https://spire.qstarstar.com", "sub":"…"}      ← 出现 iss

顺带证明:同 audience 第二次取 JWT 是缓存命中(exp 一模一样);换 audience 才会回源现签。

1.5 ca_subject —— CA 证书主体(= 每张 SVID 的 Issuer)

  • 影响什么:CA 证书的 Subject,也就是所有 SVID 的 Issuer 字段。
  • 怎么查看:openssl x509 -in captured/vm-workload-svid.pem -noout -issuerC=CN, O=qstarstar-homelab, CN=spire.qstarstar.com(正是本 lab 配的)。
  • 实验:改它要 CA 重签(清 data/ 重启),本 lab 不实跑。预期:新 CA 生效后,新 SVID 的 Issuer 跟着变。

1.6 ca_key_type —— CA 签名密钥类型

  • 影响什么:CA 私钥算法(ec-p256/ec-p384/rsa-2048/rsa-4096),进而 SVID 的签名算法
  • 怎么查看:openssl x509 -in <svid> -noout -text | grep "Signature Algorithm"(本 lab 默认 ecdsa-with-SHA256)。
  • 实验:同样需 CA 重生成,不实跑。预期:改 rsa-2048 重启清库后,签名算法变 sha256WithRSAEncryption

层② 注册条目 entry(spire-server entry create)—— 定单个身份的形态,动态生效

2.1 -spiffeID —— 这条身份的名字(写进 URI SAN)

  • 影响什么:签出的 SVID 唯一 URI SAN = 这个值。工作负载改不了它,只能拿到 entry 规定的这个。
  • 查看/实验:exp-entry.sh 固定用 /lab/exp;把脚本里 spiffeID 换成 /lab/fooobserve,URI SAN 立刻变 …/lab/foo

2.2 -selector(可重复)—— 决定"谁能拿到",多个是 AND 【实测·灵魂】

  • 影响什么:工作负载实测 selector 必须 ⊇ entry 的所有 selector(entry.Selectors ⊆ workload.Selectors)才发。这不是形状、是准入
  • 负向实验(单 selector):
text
selector = unix:uid:1002  → uid 1002 取:  ✔ 拿到 /lab/exp
selector = unix:uid:1003  → uid 1002 取:  ✘ 无 SVID(uid 不匹配,负向命中)
  • 负向实验(多 selector = AND,必须全中)(用户 other = uid 1002 / gid 1002):
text
{unix:uid:1002, unix:gid:1002} → uid 1002 取:  ✔ 拿到(两个都中)
{unix:uid:1002, unix:gid:9999} → uid 1002 取:  ✘ 无 SVID(gid 不中 → AND 失败)

2.3 unix:sha256 —— 用二进制指纹当身份门槛 【实测·最震撼】

  • 影响什么:selector 可以是调用二进制的 SHA-256。身份门槛 = "你必须是这段字节",改一个字节就换了个"人"。
  • 正向 + 负向实验:
text
/tmp/sa-good  sha256=8ef49b0b…  →  entry selector 用它  →  用 /tmp/sa-good 取:  ✔ 拿到 /lab/exp
cp sa-good sa-bad && 追加 1 字节  sha256=2df16746…      →  用 /tmp/sa-bad  取:  ✘ 无 SVID(指纹变了)

这是"主体不能自证身份、身份由平台能证明的事实决定"的最强演示——连"你是不是那段代码"都由内核实测,不由你说。

2.4 -x509SVIDTTL / -jwtSVIDTTL —— 覆盖全局默认 TTL 【实测】

  • 见 1.2/1.3 的真实数据:3600→+1h300→+5min172800→被 CA 封顶注意仍受 ca_ttl 上限

2.5 -dns(可重复)—— 给 X509-SVID 加 DNS SAN;第一个还当 CN 【实测】

  • 影响什么:X.509 的 DNS SAN;且 CN = 第一个 -dns(没配则无 CN)。对 JWT 无影响。
  • AB 实验:
text
无 -dns          → Subject: C=US, O=SPIRE          DNS SAN: (空)
-dns web.exp.lab → Subject: C=US, O=SPIRE, CN=web.exp.lab   DNS SAN: DNS:web.exp.lab

多个 -dns a -dns b:CN=a,SAN 里 a、b 都在。用途:让传统只认 DNS/CN 的 TLS 客户端也能校验这张 SVID。

2.6 -parentID —— 这条身份由哪个 agent 代领 【实测(建 entry 时已用)】

  • 影响什么:只有 SPIFFE ID = 该 parentID 的 agent 才会同步/下发这条 entry。跨 agent 拿不到(防越权,LookupAuthorizedEntries)。
  • 实证:/vm/web 的 parent 是 VM agent,/ns/demo/sa/svc 的 parent 是 K3S agent——所以 K3S 里永远取不到 /vm/web。可用 spire-server entry show 看每条的 Parent ID。

2.7 其余 entry flag(影响 + 怎么验,按需实验)

flag影响什么怎么查看 / 预期
-federatesWith <td>下发 SVID 时附带该外域的 bundle(跨信任域 mTLS)需两套 trust domain + bundle set;fetch x509 结果里会多出联邦 bundle
-hint同一 SPIFFE ID 有多条 entry 时给消费者消歧的标签fetch x509 的 SVID 上带 hint;不影响证书字段
-admin该 SPIFFE ID 可调 server 管理 API用该 SVID 连 -socketPath 管理端不被拒
-downstream标记为下游 SPIRE server,可领中间 CA(Nested)NewDownstreamX509CA 能签出 CA:TRUE 的中间 CA
-storeSVIDSVID 经 SVIDStore 插件落地(不走 Workload API)结果写到配置的 store(如云 secret),fetch 取不到
-node该条作用于节点(node alias),而非工作负载用于按节点 selector 归组 agent

层③ agent.conf(agent 全局)—— 定本地私钥与轮换,改后需 systemctl restart spire-agent

3.1 workload_x509_svid_key_type —— workload 私钥类型 【实测】

  • 影响什么:agent 为工作负载本地生成的私钥算法 → SVID 的公钥类型。身份(URI)不变,密钥材料变。
  • AB 实验:
text
默认(ec-p256)          → PubKey: id-ecPublicKey (256bit)
改 "rsa-2048" 重启 agent → PubKey: rsaEncryption (2048bit)
还原重启                 → PubKey: id-ecPublicKey (256bit)

私钥永远在 agent 本地生成、永不出机;CSR 里甚至不含 SPIFFE ID(身份由 server 定)。

3.2 其余 agent 关键项

配置影响什么怎么查看
socket_pathWorkload API 的 Unix socket 路径(工作负载来这取 SVID)本 lab VM=/run/spire/agent.sock,K3S=/run/spire/sockets/agent.sock
trust_bundle_path启动时的信任根(先信任 server,才能安全 attest)指向 captured/trust-bundle.pem
WorkloadAttestor "unix" { discover_workload_path }是否额外产出 unix:path/unix:sha256 selector关掉则 2.3 的 sha256 实验无法做
availability_targetSVID 轮换提前量(高可用)影响轮换时机,不改证书字段

4. 速查表:改哪、影响啥、怎么看、要不要重启

配置项影响 SVID 的…怎么查看生效方式
trust_domainserverURI 前缀 / 信任根openssl … -ext subjectAltName重启(破坏性)
ca_ttlserverSVID 到期上限对比 SVID 与 CA 的 NotAfter重启
default_x509/jwt_svid_ttlserver默认 TTLopenssl … -enddate / JWT exp-iat重启
jwt_issuerserverJWT 的 iss解 JWT payload(换 audience)重启
ca_subjectserverIssueropenssl … -issuer重启(重签 CA)
ca_key_typeserver签名算法openssl … Signature Algorithm重启(重签 CA)
-spiffeIDentryURI SAN(名字)openssl … -ext subjectAltName动态
-selector(多=AND)entry谁能拿到(准入)observe 有/无动态
unix:sha256entry二进制指纹准入换二进制 observe动态
-x509SVIDTTLentry该身份 TTL(≤ca_ttl)openssl … -enddate动态
-dnsentryDNS SAN + CNopenssl … -ext subjectAltName -subject动态
-parentIDentry哪个 agent 能领spire-server entry show动态
workload_x509_svid_key_typeagent公钥算法openssl … -text(Public Key)重启 agent

5. 收尾

本手册所有实验做完已还原SVID.md 记录的干净态(default_x509_svid_ttl=1h、无 jwt_issuer、2 条正式 entry、agent 默认 EC)。自己做完实验后:

bash
# 删沙箱 entry(server 上)
spire-server entry show -socketPath $SOCK -spiffeID spiffe://spire.qstarstar.com/lab/exp   # 取 Entry ID
spire-server entry delete -socketPath $SOCK -entryID <id>
# 若改过 server.conf / agent.conf,改回后 systemctl restart 对应服务

整套 lab 清除:bash teardown.sh

内容基于 SPIFFE/SPIRE 官方开源资料整理与翻译,仅供学习交流;商标与版权归各自所有者。SPIFFE 与 SPIRE 是 CNCF 项目。