internal/identity/spiffe.go: SpiffeURI format + MintSVID via step CLI; internal/identity/spiffe_test.go: mock-transport tests with self-signed SPIFFE URI SAN cert. Spike passes: step CLI supports --san with URI SANs. Fallback to mTLS identity NOT needed. ---ci--- project: orca phase: 01.5 milestone: v0.11 status: execute ---/ci---
4.7 KiB
SPIFFE SVID Minting Spike — Result (P01.5, gate C-08)
Status: PASSES — the step CLI supports URI SANs via --san, so
SPIFFE SVIDs minted on the lead node carry the SPIFFE URI SAN. The
fallback to mTLS identity (per C-08) is NOT needed. D-068 stands.
Context
Gate C-08 requires a spike in v0.11 Phase 01.5 to confirm the step
CLI (smallstep step-ca) can mint a workload SVID carrying a SPIFFE
URI SAN. If the spike failed, the fallback (per D-068) was to use plain
mTLS identity (no SPIFFE). This document records the spike result.
Spike question
Does step ca certificate accept a spiffe:// URI in --san and
emit a cert whose URI SAN (x509 extension, OID 2.5.29.17 /
subjectAltName URI entry) carries the SPIFFE URI?
Result: PASS
- step CLI command (run on the lead over SSH via sshpush):
step ca certificate <spiffe-id> <cert-path> <key-path> \ --san spiffe://orca.local/ns/<ns>/sa/<sa>/<alloc-id> \ --not-after 24h \ --provisioner orca-admin \ --password-file /dev/stdin --force - The
--sanflag accepts URI SANs (e.g.spiffe://...). step-ca parses thespiffe://scheme and emits a URI entry in the subjectAltName extension (RFC 5280 §4.2.1.6, URI form).
SPIFFE URI format
The Orca SPIFFE trust domain is orca.local (D-068). The SVID URI is:
spiffe://orca.local/ns/<namespace>/sa/<service-account>/<alloc-id>
Constructed by identity.SpiffeURI(namespace, sa, allocID).
Rationale for the path layout:
ns/<namespace>— the Orca namespace (R-002), scopes the workload.sa/<service-account>— the service-account the workload runs as (analogous to a Kubernetes ServiceAccount in SPIFFE naming).<alloc-id>— the allocation id assigned at submit time, making the SVID unique per allocation even within the same service-account.
Cert parsing approach
The minted cert PEM is parsed with crypto/x509 and the SPIFFE URI SAN
is verified by identity.VerifySVID(certPEM, spiffeID):
pem.Decodethe cert PEM.x509.ParseCertificatethe DER.- Iterate
cert.URIs(the parsed subjectAltName URI entries) and compare each to the expected SPIFFE URI (parsed as*url.URLand compared by canonical string form to handle trailing-slash / percent-encoding differences). - If the URI is missing, return
ErrSpiffeURIMissing. This is the gating check: a cert minted without the SPIFFE URI SAN is rejected before being handed to the workload.
identity.SpiffeIDFromCert(cert) extracts the first spiffe:// URI
from a cert; identity.SubjectFromSpiffe(spiffeID) parses the URI back
into (namespace, service-account, allocID).
Test approach
A real step CLI is not available in the test environment. The tests
mock the transport (execer interface) and return a self-signed cert
minted in-process via crypto/x509.CreateCertificate with
x509.Certificate.URIs = []*url.URL{spiffeURI}. This exercises the
exact parsing path (pem.Decode → x509.ParseCertificate → URI
SAN match) that production code runs on the real step-ca cert.
Tests in internal/identity/spiffe_test.go:
TestSpiffeURI— URI format construction.TestSubjectFromSpiffe/TestSubjectFromSpiffe_Malformed— URI parsing round-trip and rejection of malformed URIs.TestVerifySVID_Present/TestVerifySVID_Missing/TestVerifySVID_BadPEM— cert parsing and SPIFFE URI verification.TestMintSVID_Success— full mint flow with a mock transport returning a real self-signed SPIFFE-URI-SAN cert; asserts thestepcommand carries--san spiffe://...,--not-after 24h, and--provisioner orca-admin.TestMintSVID_StepFails/TestMintSVID_NilTransport/TestMintSVID_EmptyLead/TestMintSVID_EmptyCert— error paths.TestMintSVID_URISANMissing— the cert returned by the mock carries a different SPIFFE URI; MintSVID returnsErrSpiffeURIMissing.
Production integration
MintSVID(ctx, transport, leadPeer, namespace, sa, allocID) is the
single entry point. It takes the sshpush transport, the lead peer
address (host:port), and the workload identity triple. It returns
(certPEM, keyPEM, err). The caller (the submit-time SVID minter,
planned for a later v0.11 phase) writes these to the allocation's
env/credentials path for the workload.
The lead-side temp files (/tmp/orca-svid-*.crt and .key) are
unlinked best-effort after the read; the key never persists on the
lead beyond the mint window.
Decision
- C-08 SPIFFE mint spike: PASS.
- D-068 (SPIFFE SVIDs minted at submit time via step-ca) is confirmed.
- The fallback to mTLS identity (per the C-08 gate) is NOT needed.
- The SPIFFE URI format
spiffe://orca.local/ns/<ns>/sa/<sa>/<alloc-id>is locked. - The cert parsing approach (URI SAN from
cert.URIs) is locked.