Security
All control plane and container traffic encrypted end-to-end. No TLS certificates to manage — just keypairs.
Banyan authenticates all gRPC communication between components. Every RPC call carries credentials that the engine validates before processing the request.
Auth methods
| Method | Status | How it works |
|---|---|---|
| Public Key Whitelist | Default | Each component generates a WireGuard keypair. The engine validates public keys against a whitelist directory. |
| mTLS | Planned | Mutual TLS with client certificates |
| OIDC / SSO | Planned | Delegate authentication to an identity provider |
Public Key Whitelist
This is Banyan’s default authentication method. Each component generates an X25519 keypair during init. The same keypair is used for both authentication (control plane) and WireGuard overlay encryption (data plane).
How it works
There are two distinct phases: init time (one-time setup) and runtime (ongoing operation).
Init-time flow
During init, each component generates a WireGuard keypair. The admin then copies agent/CLI public keys to the engine’s whitelisted keys directory:
sequenceDiagram
participant Admin
participant Engine as banyan-engine
participant Agent as banyan-agent
participant CLI as banyan-cli
Note over Admin,Engine: Step 1: Engine init
Admin->>Engine: banyan-engine init
Engine->>Engine: Generate X25519 keypair
Engine->>Engine: Save private key + public key to config
Engine->>Engine: Create /etc/banyan/whitelisted-keys/
Note over Admin,Agent: Step 2: Agent init
Admin->>Agent: banyan-agent init
Agent->>Agent: Generate X25519 keypair
Agent->>Agent: Save private key + public key to config
Agent->>Agent: Display public key
Note over Admin,Engine: Step 3: Whitelist agent key
Admin->>Engine: Copy agent public key to engine
Note right of Admin: echo '<pubkey>' > /etc/banyan/whitelisted-keys/worker-1.pub
Note over Admin,CLI: Step 4: CLI init
Admin->>CLI: banyan-cli init
CLI->>CLI: Generate X25519 keypair
CLI->>CLI: Save private key + public key to config
CLI->>CLI: Display public key
Note over Admin,Engine: Step 5: Whitelist CLI key
Admin->>Engine: Copy CLI public key to engine
Note right of Admin: echo '<pubkey>' > /etc/banyan/whitelisted-keys/cli-1.pub
Note over Admin,Engine: Step 6: Start engine
Admin->>Engine: sudo systemctl start banyan-engine
Engine->>Engine: Load all *.pub from whitelisted-keys/
Engine->>Engine: Start gRPC server with pubkey auth
Runtime flow
After init, all communication uses the public key in gRPC metadata:
sequenceDiagram
participant Agent as banyan-agent
participant Engine as banyan-engine
Agent->>Engine: gRPC call + public key in x-banyan-public-key header
Engine->>Engine: Look up public key in whitelist
alt Key found in whitelist
Engine->>Engine: Process RPC
Engine-->>Agent: Response
else Key not found
Engine-->>Agent: Unauthenticated error
end
Config files
After initialization, each component stores its keypair:
Engine (/etc/banyan/banyan.yaml):
engine: wg_private_key: "base64-encoded-private-key" wg_public_key: "base64-encoded-public-key" whitelisted_keys_dir: "/etc/banyan/whitelisted-keys" grpc_port: "50051" store_backend: "etcd"Agent (/etc/banyan/banyan.yaml):
agent: engine_host: "192.168.1.10" engine_port: "50051" wg_private_key: "base64-encoded-private-key" wg_public_key: "base64-encoded-public-key"CLI (/etc/banyan/banyan.yaml):
cli: engine_host: "192.168.1.10" engine_port: "50051" wg_private_key: "base64-encoded-private-key" wg_public_key: "base64-encoded-public-key"Key management
- Generate: Running
initon any component generates a new X25519 keypair. - Whitelist: Copy the public key (displayed during init) to the engine’s whitelisted keys directory as a
.pubfile. - Revoke: Delete the
.pubfile from the engine’s whitelisted keys directory and restart the engine. - Rotate: Re-run
initon the component to generate a new keypair, then update the.pubfile on the engine.
Whitelisting keys
After running init on an agent or CLI, copy the displayed public key to the engine:
# On the agent machine (after banyan-agent init)cat /etc/banyan/banyan.yaml | grep wg_public_key# Output: wg_public_key: "abc123..."
# On the engine machinesudo banyan-engine add-client --name worker-1 --pubkey 'abc123...'Or copy directly between machines:
# From agent to enginessh engine-host "echo '$(grep wg_public_key /etc/banyan/banyan.yaml | awk '{print $2}')' > /etc/banyan/whitelisted-keys/worker-1.pub"The filename (minus .pub) becomes the agent’s display name in logs.
Non-interactive init
All init commands can be run non-interactively by pre-writing the config file:
# Write config firstcat > /etc/banyan/banyan.yaml <<EOFagent: engine_host: "192.168.1.10" engine_port: "50051"EOF
# Run init (generates keypair, skips prompts since config exists)sudo banyan-agent initWireGuard control tunnel
When the engine’s WireGuard public key is provided during agent/CLI init, Banyan creates a wg-control WireGuard interface that encrypts all gRPC traffic at the network layer. No TLS is needed — the tunnel handles encryption transparently.
Control plane tunnel (wg-control): Engine (10.200.0.1) <-> Agent (10.200.X.Y) # encrypted gRPC Engine (10.200.0.1) <-> CLI (10.200.X.Y) # encrypted gRPC
Data plane tunnel (banyan-wg): Agent <-> Agent # encrypted container trafficHow it works:
- Engine generates a keypair during
banyan-engine initand displays its public key. - Agents/CLI provide the engine’s public key during their
init. - On start, each component creates a
wg-controlinterface with a deterministic tunnel IP derived from its public key. - gRPC traffic routes through the tunnel automatically.
- If the tunnel is unavailable (e.g., WireGuard not installed), components fall back to direct TCP with public key metadata auth.
Port: 51821/UDP on the engine (agents/CLI connect to this port).
Config fields:
agent: engine_wg_public_key: "engine-public-key-base64" # enables control tunnel
cli: engine_wg_public_key: "engine-public-key-base64" # enables control tunnelSecurity properties
| Property | How |
|---|---|
| No passwords or shared secrets | Each component has a unique keypair. No cluster-wide password. |
| Keys are standard X25519 | Same format as WireGuard. 32 bytes, base64-encoded. |
| Dual-purpose keypair | Same key for gRPC auth (control plane) and WireGuard tunnels (data plane). |
| Per-component revocation | Delete a single .pub file to revoke access for one agent/CLI. |
| No token storage in etcd | Public keys are stored as flat files on the engine. No etcd dependency for auth. |
| Private keys never leave the machine | Only the public key is copied to the engine. |
| Control plane encryption | When enabled, all gRPC traffic is encrypted via WireGuard tunnel. |
mTLS (planned)
Mutual TLS authentication will allow components to authenticate using X.509 client certificates instead of public keys.
sequenceDiagram
participant CA as Certificate Authority
participant Engine as banyan-engine
participant Agent as banyan-agent
Note over CA,Agent: Setup (one-time)
CA->>Engine: Issue server cert + key
CA->>Agent: Issue client cert + key
Note over Engine,Agent: Runtime
Agent->>Engine: gRPC + TLS handshake (client cert)
Engine->>Engine: Verify client cert against CA
Engine-->>Agent: Authenticated connection
This will be suitable for environments with existing PKI infrastructure or stricter security requirements. See the roadmap for status.
OIDC / SSO (planned)
OpenID Connect integration will allow Banyan to delegate authentication to an external identity provider (e.g., Google, Okta, Keycloak).
sequenceDiagram
participant User
participant CLI as banyan-cli
participant IdP as Identity Provider
participant Engine as banyan-engine
User->>CLI: banyan-cli init --auth oidc
CLI->>IdP: Redirect to login
User->>IdP: Authenticate
IdP-->>CLI: ID token
CLI->>Engine: Authenticate with ID token
Engine->>IdP: Verify token
Engine-->>CLI: Whitelisted
CLI->>CLI: Save config
This will be suitable for teams with centralized identity management. See the roadmap for status.