6 KiB
SPIRE Plugin Types
This document describes the four SPIRE plugin interfaces implemented by this repository, their callback methods, invocation timing, and the Guildhouse plugin that implements each.
Overview
SPIRE's plugin architecture uses the go-plugin (hashicorp/go-plugin) framework. Plugins are compiled as separate binaries and loaded by the SPIRE Agent or Server at startup via the plugin configuration in server.conf or agent.conf.
| Interface | Side | Guildhouse Plugin | Purpose |
|---|---|---|---|
| WorkloadAttestor | Agent | oidc-attestor | Identify workloads by OIDC token |
| CredentialComposer | Server | ssh-credential-composer | Modify credentials during minting |
| Notifier | Server | governance-notifier | React to SPIRE lifecycle events |
| KeyManager | Server | substrate-keymanager | Manage server signing keys |
WorkloadAttestor
Side: SPIRE Agent
Plugin: cmd/oidc-attestor
Interface methods:
Attest(ctx context.Context, pid int32) ([]*common.Selector, error)
When called: Every time a workload calls the Workload API (typically FetchX509SVID or FetchJWTSVID). The agent identifies the calling process by PID, then passes that PID to all registered WorkloadAttestor plugins. Each plugin returns zero or more selectors.
What oidc-attestor does: Given the workload PID, it discovers an OIDC token associated with that process (via a projected volume path or environment variable), validates the token signature against a JWKS endpoint, and returns selectors derived from token claims (issuer, subject, audience, custom claims).
Selector format:
oidc_attestor:iss:<issuer>
oidc_attestor:sub:<subject>
oidc_attestor:aud:<audience>
oidc_attestor:claim:<key>:<value>
CredentialComposer
Side: SPIRE Server
Plugin: cmd/ssh-credential-composer
Interface methods:
ComposeServerX509CA(ctx context.Context, attributes X509CAAttributes) (X509CAAttributes, error)
ComposeServerX509SVID(ctx context.Context, attributes X509SVIDAttributes) (X509SVIDAttributes, error)
ComposeAgentX509SVID(ctx context.Context, attributes X509SVIDAttributes) (X509SVIDAttributes, error)
ComposeWorkloadX509SVID(ctx context.Context, attributes X509SVIDAttributes) (X509SVIDAttributes, error)
ComposeWorkloadJWTSVID(ctx context.Context, attributes JWTSVIDAttributes) (JWTSVIDAttributes, error)
When called: During credential minting on the server. After the server decides to issue a credential (X.509 SVID, JWT SVID, or CA certificate), it passes the proposed attributes through all registered CredentialComposer plugins. Each plugin may modify the attributes before the credential is signed.
What ssh-credential-composer does: Intercepts ComposeWorkloadX509SVID (and potentially future SSH-specific hooks). It reads the SPIFFE ID and registration entry metadata, calls GovernanceService to create a MutationIntent for the issuance, constructs a MutationEnvelope, anchors it via NotaryService, then encodes the governance metadata as Shellstream extensions in the SSH certificate's critical options using the pkg/shellstream encoder.
Key detail: The composer does not modify X.509 SVIDs for non-SSH use cases. It checks registration entry selectors or hints to determine if the credential is destined for SSH usage before injecting extensions.
Notifier
Side: SPIRE Server
Plugin: cmd/governance-notifier
Interface methods:
Notify(ctx context.Context, event *NotifyRequest) (*NotifyResponse, error)
NotifyAndAdvise(ctx context.Context, event *NotifyAndAdviseRequest) (*NotifyAndAdviseResponse, error)
When called:
Notify: After a bundle update or registration entry change has been committed. This is fire-and-forget; the server does not block on the response.NotifyAndAdvise: Before certain operations where the plugin can influence the outcome. The server waits for the response.
Event types the plugin handles:
BundleUpdated— A trust bundle was rotated.EntryUpdated— A registration entry was created, updated, or deleted.
What governance-notifier does: On bundle rotation events, it creates a MutationIntent via GovernanceService to record the rotation as an auditable governance event. For sensitive entry changes (e.g., high-privilege SPIFFE IDs), it triggers a CeremonyService flow requiring multi-stakeholder approval. All events are anchored in the merkle tree via NotaryService.
KeyManager
Side: SPIRE Server
Plugin: cmd/substrate-keymanager
Interface methods:
GenerateKey(ctx context.Context, req *GenerateKeyRequest) (*GenerateKeyResponse, error)
GetPublicKey(ctx context.Context, req *GetPublicKeyRequest) (*GetPublicKeyResponse, error)
GetPublicKeys(ctx context.Context, req *GetPublicKeysRequest) (*GetPublicKeysResponse, error)
SignData(ctx context.Context, req *SignDataRequest) (*SignDataResponse, error)
When called:
GenerateKey: When the server needs a new signing key (initial startup, key rotation).GetPublicKey/GetPublicKeys: When the server needs to retrieve existing key material.SignData: Every time the server signs a credential (SVID, CA cert).
What substrate-keymanager does: Manages the SPIRE Server's signing keys with governance-aware lifecycle. Key generation and rotation events are recorded as MutationIntents. The plugin stores keys in a configured backend (filesystem, Kubernetes Secret, or remote KMS) and ensures every key operation is traceable through the governance audit trail.
Plugin Loading Order
SPIRE loads plugins in the order they appear in configuration. For correctness:
- substrate-keymanager must load first (server needs signing keys before issuing anything).
- ssh-credential-composer loads next (must be present before any credential minting).
- governance-notifier loads last (reacts to events that other plugins may trigger).
On the agent side, oidc-attestor is loaded alongside any other workload attestors (e.g., the built-in k8s attestor). Multiple attestors can coexist; their selectors are unioned.