guildhouse-spire-plugins/docs/architecture.md
Tyler King 420a4e2ea0 Remediate all 17 audit findings from AUDIT.md
Critical fixes:
- F-01: SatScope array form support (single pointer → slice with polymorphic JSON)
- F-02: Add governance-intent@guildhouse.dev as 10th Shellstream extension
- F-06: Replace os.Exit(1) stubs with go-plugin Serve() boilerplate in all cmd/
- F-13: Validate SatScope.ResourcePattern is non-empty

High priority:
- F-03: Add normative Accord policy syntax note to credential-governance.md §8.2
- F-04: Replace OID XXXXX placeholder with explicit PEN reference and IANA TODO
- F-05: Document CredentialComposer hook mapping in spec and plugin-types.md
- F-07/F-08: Commit CI pipeline (.github/workflows/ci.yaml)
- F-09: Add hashicorp/go-plugin v1.6.3 to go.mod

Medium priority:
- F-10: Wire sample-ssh-cert-extensions.json fixture into shellstream tests
- F-11: Cross-reference merkle proof depth limit (256 leaves) in governance spec
- F-12: Add YAML format clarification headers to deploy configs
- F-14: Expand README with project status, docs links, and quick-start

Low priority:
- F-15: Standardize "SSH SVID" → "SSH-SVID" terminology across docs
- F-16: Add GovernanceEpochSeconds to PluginConfig and deploy configs
- F-17: Add troubleshooting section to deployment.md, error handling to OIDC docs

Global: Rename all extension keys from @guildhouse.io to @guildhouse.dev

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 11:45:33 -05:00

114 lines
6.5 KiB
Markdown

# Architecture Overview
This document describes how the Guildhouse SPIRE plugins integrate SPIFFE workload identity with Guildhouse's governance platform.
## System Diagram
```
+----------------------------------------------------------+
| Kubernetes Cluster |
| |
| +--------------------+ +-------------------------+ |
| | SPIRE Agent | | SPIRE Server | |
| | | | | |
| | +----------------+ | | +---------------------+ | |
| | | oidc-attestor | | | | ssh-credential- | | |
| | | (WorkloadAttr) | | | | composer (CredComp) | | |
| | +----------------+ | | +---------------------+ | |
| | | | | |
| +--------|-----------+ | +---------------------+ | |
| | | | governance-notifier | | |
| | | | (Notifier) | | |
| | | +---------------------+ | |
| | | | |
| +--------v-----------+ | +---------------------+ | |
| | Workloads | | | substrate-keymanager| | |
| | (present OIDC | | | (KeyManager) | | |
| | tokens for | | +---------------------+ | |
| | attestation) | +------|--------|----------+ |
| +--------------------+ | | |
| gRPC | gRPC | |
| (mTLS) | | (mTLS) |
| +-----------------------------+ | +------------------+
| | Quartermaster |<--+ | Bascule |
| | | | |
| | - GovernanceService | | - CeremonyServ |
| | (MutationIntents) | | (multi-party |
| | - NotaryService | | approval) |
| | (Merkle anchoring) | | |
| +-----------------------------+ +------------------+
+----------------------------------------------------------+
```
## Components
### SPIRE Agent Plugins
**oidc-attestor** (WorkloadAttestor) runs inside the SPIRE Agent. When a workload calls the Workload API to request an SVID, the agent invokes oidc-attestor to identify the workload. The plugin discovers an OIDC token from the workload's environment (file path or environment variable), verifies it against a JWKS endpoint, and returns selectors derived from token claims.
### SPIRE Server Plugins
Three plugins run inside the SPIRE Server:
- **ssh-credential-composer** (CredentialComposer) intercepts credential minting. When the server issues an SSH-SVID, this plugin encodes Shellstream extensions into the SSH certificate's critical options, embedding governance metadata (intent ID, ceremony outcome, SAT hash) into the cert itself.
- **governance-notifier** (Notifier) receives SPIRE lifecycle events (bundle updates, registration entry changes, SVID rotations). On relevant events, it calls GovernanceService to create or update MutationIntents, and may trigger CeremonyService flows for operations requiring multi-stakeholder approval.
- **substrate-keymanager** (KeyManager) manages the signing keys used by the SPIRE Server. It stores key material with governance-aware lifecycle management, ensuring key rotations are captured as auditable intents.
## Guildhouse gRPC Services
All plugin-to-service communication uses mTLS via SPIFFE SVIDs. The plugins themselves hold SPIFFE identities and authenticate to Guildhouse services through mutual TLS.
| Service | Package | Plugin Consumers |
|---------|---------|-----------------|
| GovernanceService | `quartermaster.v1` | governance-notifier, ssh-credential-composer |
| NotaryService | `quartermaster.v1` | governance-notifier, ssh-credential-composer |
| CeremonyService | `bascule.v1` | governance-notifier |
## Data Flow: SSH Certificate Issuance
1. A workload calls the SPIRE Workload API requesting an SSH-SVID.
2. The SPIRE Agent invokes **oidc-attestor**, which discovers and verifies the workload's OIDC token and returns selectors.
3. The agent matches selectors against registration entries and forwards the request to the SPIRE Server.
4. The server invokes **ssh-credential-composer** during credential minting.
5. The composer calls **GovernanceService.CreateIntent** to record the SSH cert issuance as a MutationIntent.
6. If the intent requires approval, **CeremonyService.CreateCeremony** is called and the flow blocks until approval.
7. The composer constructs a MutationEnvelope (RFC 8785 JCS canonicalization, domain-separated SHA-256 hash), which becomes a merkle leaf.
8. **NotaryService.CreateAnchor** anchors the envelope hash into the merkle tree.
9. The composer encodes Shellstream extensions into the SSH certificate's critical options (intent ID, SAT hash, ceremony result).
10. The signed SSH certificate is returned to the workload through the agent.
## Package Map
```
guildhouse-spire-plugins/
cmd/
oidc-attestor/ # WorkloadAttestor plugin binary
ssh-credential-composer/ # CredentialComposer plugin binary
governance-notifier/ # Notifier plugin binary
substrate-keymanager/ # KeyManager plugin binary
pkg/
shellstream/ # Encode/decode SSH cert Shellstream extensions
oidc/ # OIDC token discovery and verification
governance/ # GovernanceService + CeremonyService client
sshcert/ # SSH certificate construction helpers
config/ # Shared plugin configuration loading
proto/
quartermaster/v1/ # governance.proto, notary.proto, credentials.proto
bascule/v1/ # ceremony.proto
specs/ # Formal specifications (read-only reference)
deploy/ # Kubernetes manifests and Helm values
test/ # Integration tests and fixtures
```
## Proto Dependencies
| Proto File | Service | Package |
|-----------|---------|---------|
| `governance.proto` | GovernanceService | `quartermaster.v1` |
| `notary.proto` | NotaryService | `quartermaster.v1` |
| `credentials.proto` | Credential types | `quartermaster.v1` |
| `ceremony.proto` | CeremonyService | `bascule.v1` |
Generated Go code from these protos lives alongside the `.proto` files or in a generated output directory. The `pkg/governance` package wraps the raw gRPC stubs with higher-level client logic (retries, circuit breaking, intent lifecycle management).