Authentication¶
pgway’s Control Plane authenticates operators (users / pgctl) and, in distributed mode, agents (pgway-dp). These use different tokens — do not mix them up.
flowchart TB
subgraph users [Operators]
Log[CP log bootstrap_token] --> Init[pgctl init]
Init --> Cred[~/.pgctl/credentials]
Login[pgctl login] --> Cred
Cred --> Apply[pgctl apply / get / user / agent]
end
subgraph agents [Data Plane agents]
RegTok[pgctl agent token create] --> DP[pgway-dp first start]
DP --> State[agent_state_path]
State --> HB[Heartbeat / Watch]
end
Apply --> CP[Control Plane gRPC]
HB --> CP
Hands-on bootstrap: First run. Config TTLs: Configuration. Planes: Binaries & planes.
gRPC vs REST¶
| Surface | Auth today |
|---|---|
| gRPC (primary) | Bearer token on almost every RPC |
| REST (dashboard) | Not enforced yet — experimental; do not expose publicly |
gRPC RPCs that do not require a prior user/agent session:
| RPC | Purpose |
|---|---|
AuthService/InitAdmin |
First admin via bootstrap token |
AuthService/Login |
Exchange username/password for a session token |
AgentService/Register |
First-time agent join via registration token |
Everything else (apply, get, user admin, agent list/delete, Watch after register, …) needs a valid bearer.
Token cheat-sheet¶
| Token | Who creates it | Who consumes it | Lifetime |
|---|---|---|---|
| Bootstrap token | CP log when no users exist | pgctl init |
One-shot; new value if you restart before init |
| User session token | pgctl init / pgctl login |
pgctl → CP |
Default token_ttl (e.g. 720h); optional --no-expiry |
| Agent registration token | pgctl agent token create |
pgway-dp first Register |
Single-use; default TTL registration_token_ttl |
| Agent token | Issued at Register | pgway-dp (persisted) |
Sliding agent_token_ttl; extended on heartbeat |
All-in-one
pgway (CP+DP in one process) still needs the bootstrap / user session path for pgctl. It does not need agent registration tokens — there is no separate agent process.
Operators (users)¶
Bootstrap (empty install)¶
- Start
pgwayorpgway-cpwith empty Badger user store. - Read
bootstrap_tokenfrom the warn log line. - Run:
./build/pgctl init --bootstrap-token '<token-from-log>'
Creates the first admin, issues a session token, writes ~/.pgctl/credentials.
Warning
Restarting the CP before init generates a new bootstrap token. The old one is useless.
Login / logout¶
./build/pgctl login --username admin # default TTL
./build/pgctl login --username alice --no-expiry # automation
./build/pgctl logout # revoke current token
How pgctl picks a token¶
Highest wins:
--tokenflagPGWAY_TOKENenv /tokenin config file~/.pgctl/credentials(frominit/login)
CLI state (~/.pgctl/) is separate from shared config search paths (~/.pgway/, /etc/pgway/, .).
Users¶
Passwords are stored bcrypt-hashed. Changing a password revokes all of that user’s session tokens.
./build/pgctl user create bob # admin; prints one-time temporary password
./build/pgctl user create alice --role admin
./build/pgctl user list # admin
./build/pgctl user change-password # own password
./build/pgctl user change-password bob # admin reset
./build/pgctl user delete bob # admin; last admin cannot be deleted
Agents (pgway-dp)¶
Standalone Data Planes do not use user login. They authenticate with an agent token obtained via registration.
First start¶
# on a machine with pgctl logged in as admin
./build/pgctl agent token create
# → single-use registration token
PGWAY_REGISTRATION_TOKEN='<registration-token>' \
./build/pgway-dp --config ./dp.yml
dp.yml must dial the CP (grpc_listen_addr) and set at least agent_name / agent_state_path (see Configuration).
On success, Register returns credentials written to agent_state_path ({agent_id, agent_token}; directory mode 0700, file 0600).
Later starts¶
Reuse agent_state_path — no registration token:
./build/pgway-dp --config ./dp.yml
Heartbeats (interval heartbeat_interval) extend the sliding agent token TTL. Status on the CP:
| Status | Meaning (approx.) |
|---|---|
| active | Heartbeat within agent_heartbeat_threshold |
| passive | Graceful deregister (clean shutdown) |
| disconnected | Missed heartbeats / stale |
./build/pgctl agent list
./build/pgctl agent delete <name> # revoke credentials + remove registry row
After delete (or expired token without heartbeats), the DP needs a new registration token to join again.
Related config keys¶
| Key | Role |
|---|---|
token_ttl |
Default user session lifetime |
registration_token_ttl |
Default agent registration token TTL |
agent_token_ttl |
Sliding agent bearer lifetime |
agent_heartbeat_threshold |
Active vs disconnected boundary |
heartbeat_interval |
DP heartbeat period |
agent_state_path |
Persisted agent credentials |
registration_token / PGWAY_REGISTRATION_TOKEN |
First Register only |
Security notes¶
- Treat bootstrap, registration, and session tokens as secrets.
- Prefer env vars for secrets (
PGWAY_TOKEN,PGWAY_REGISTRATION_TOKEN) over committing them in YAML. - Do not expose unauthenticated REST / dashboard ports on untrusted networks.
- mTLS between CP and DP is planned (#47), not implemented yet.