# Deployment Guide Kubernetes deployment of Guildhouse SPIRE plugins. ## Prerequisites - SPIRE Server and Agent deployed (v1.9+) - Guildhouse Quartermaster services running (GovernanceService, NotaryService) - Guildhouse Bascule services running (CeremonyService) - mTLS connectivity between SPIRE and Guildhouse services via SPIFFE ## Plugin Distribution Plugin binaries are packaged as a container image: ``` ghcr.io/guildhouse-cooperative/spire-plugins:latest ``` The image contains: ``` /plugins/ oidc-attestor ssh-credential-composer governance-notifier substrate-keymanager ``` ## Installation via Kustomize Apply the overlay in `deploy/kustomization.yaml` on top of your SPIRE deployment: ```bash kubectl apply -k deploy/ ``` This patches the SPIRE Server and Agent Deployments to: 1. Add an init container that copies plugin binaries to a shared volume 2. Mount the plugin directory into the SPIRE containers ## SPIRE Server Configuration Add plugin blocks to your SPIRE Server configuration (`server.conf`): ```hcl plugins { KeyManager "guildhouse_substrate" { plugin_cmd = "/opt/spire/plugins/substrate-keymanager" plugin_data { trust_domain = "guildhouse.example.org" governance_addr = "governance.quartermaster.svc.cluster.local:50051" notary_addr = "notary.quartermaster.svc.cluster.local:50051" cluster_id = "guildhouse-prod" } } CredentialComposer "guildhouse_ssh" { plugin_cmd = "/opt/spire/plugins/ssh-credential-composer" plugin_data { trust_domain = "guildhouse.example.org" governance_addr = "governance.quartermaster.svc.cluster.local:50051" default_cert_ttl = "5m" max_cert_ttl = "1h" } } Notifier "guildhouse_governance" { plugin_cmd = "/opt/spire/plugins/governance-notifier" plugin_data { governance_addr = "governance.quartermaster.svc.cluster.local:50051" ceremony_addr = "ceremony.bascule.svc.cluster.local:50052" notary_addr = "notary.quartermaster.svc.cluster.local:50051" cluster_id = "guildhouse-prod" trust_domain = "guildhouse.example.org" } } } ``` ## SPIRE Agent Configuration Add the OIDC attestor to your SPIRE Agent configuration (`agent.conf`): ```hcl plugins { WorkloadAttestor "guildhouse_oidc" { plugin_cmd = "/opt/spire/plugins/oidc-attestor" plugin_data { issuer = "https://keycloak.guildhouse.example.org/realms/platform" audience = "spire" token_path = "/var/run/secrets/oidc/token" } } } ``` ## RBAC The SPIRE Server ServiceAccount needs access to read Kubernetes Secrets (for webhook secrets) and ConfigMaps (for Accord policy): ```yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: spire-server-guildhouse rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get"] resourceNames: ["guildhouse-governance-certs"] - apiGroups: [""] resources: ["configmaps"] verbs: ["get", "list", "watch"] ``` ## mTLS Configuration Plugins authenticate to Guildhouse services using the SPIRE Server's own SVID. The plugin inherits the server's SPIFFE identity and uses it for mTLS. No additional certificate configuration is needed — the plugin obtains its mTLS credentials from the SPIRE Server's Workload API socket. ## Health Checks Each plugin logs its health status at startup. Monitor SPIRE Server logs for: ``` level=info msg="guildhouse_ssh: connected to GovernanceService" level=info msg="guildhouse_governance: connected to CeremonyService" level=info msg="guildhouse_substrate: key manager initialized" ``` Plugin failures surface as SPIRE Server errors during credential minting or event notification. ## Environment Variables Plugins read configuration from HCL `plugin_data` blocks. No environment variables are required. The SPIRE plugin framework passes configuration directly. ## Upgrading To upgrade plugins: 1. Build new plugin container image 2. Update image tag in `deploy/kustomization.yaml` 3. Restart SPIRE Server and Agent pods 4. SPIRE reloads plugins on startup ## Troubleshooting ### Plugin fails to load **Symptom:** SPIRE Server logs `plugin failed to start` or `plugin handshake failed`. **Checks:** 1. Verify plugin binary exists at the configured `plugin_cmd` path inside the container. 2. Ensure the init container completed successfully: `kubectl logs -c copy-plugins`. 3. Check that the binary is executable: `kubectl exec -- ls -la /opt/spire/plugins/`. 4. Verify the SPIRE version is v1.9+ (required for CredentialComposer support). ### GovernanceService unreachable **Symptom:** SPIRE Server logs `guildhouse_ssh: GovernanceService unavailable` or gRPC deadline exceeded errors. **Checks:** 1. Verify the GovernanceService address in `plugin_data` is correct and resolvable from the pod. 2. Check mTLS connectivity: the SPIRE Server SVID must be trusted by the GovernanceService. 3. Ensure the Quartermaster namespace services are running: `kubectl get pods -n quartermaster`. ### OIDC attestation returns no selectors **Symptom:** Workloads fail to receive SVIDs; agent logs show `oidc-attestor: no token found`. **Checks:** 1. Verify the projected token volume is mounted at the configured `token_path`. 2. Check token expiry: projected tokens rotate automatically but may be stale if the kubelet is unhealthy. 3. Verify the `issuer` and `audience` in plugin config match the actual token claims. ### Ceremony timeout **Symptom:** Credential issuance hangs and eventually fails with `ceremony timeout`. **Checks:** 1. Check that the CeremonyService is reachable at the configured `ceremony_addr`. 2. Verify that an approver is available for the ceremony type (SingleApproval requires one approver, QuorumApproval requires the configured quorum). 3. Review the `ceremony_timeout_seconds` setting in the Accord policy defaults.