docs: plan mother MCP link — Vaultwarden pubkey exchange #141
2 changed files with 163 additions and 0 deletions
162
docs/PLAN-MOTHER-MCP-VAULT-KEYS.md
Normal file
162
docs/PLAN-MOTHER-MCP-VAULT-KEYS.md
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
# Plan: Mother MCP Link — Vaultwarden Pubkey Exchange
|
||||
|
||||
**Direction:** B — we (ISO agent) call mother via SSH. Pubkeys exchanged
|
||||
through Vaultwarden, no operator copy-paste.
|
||||
|
||||
**Scope:** OSA acts as mother until dedicated machine exists. Shell scripts
|
||||
first, colibri-vault crate later when the contract is solid.
|
||||
|
||||
---
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
ISO (agent) VAULTWARDEN MOTHER (OSA)
|
||||
─────────────────────────────────────── ─────────────── ─────────────────────────────
|
||||
|
||||
[Enable Mother clicked]
|
||||
|
||||
1. ssh-keygen -t ed25519
|
||||
(if no key yet)
|
||||
|
||||
2. bw publish pubkey ──────────────► hive-pubkeys item
|
||||
name: <hostname>
|
||||
notes: ssh-ed25519 AAAA...
|
||||
|
||||
[cron: @every 5m]
|
||||
|
||||
3. bw list hive-pubkeys
|
||||
|
||||
4. rebuild authorized_keys.hive
|
||||
command="colibri-mcp",restrict
|
||||
one line per agent
|
||||
|
||||
5. update external-mcp.json ──────────────────────────────────────► ready for connections
|
||||
ssh -i key colibri@<ts-ip> colibri-mcp
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
### Our side (clawdie-iso)
|
||||
|
||||
| File | Change | What |
|
||||
|------|--------|------|
|
||||
| `clawdie-enable-mother.sh` | Extend | Add keygen + vault publish BEFORE the external-mcp.json update |
|
||||
| `clawdie-vault-fetch` (colibri) | Extend | Add `--publish-pubkey` mode: create/update item in hive-pubkeys |
|
||||
|
||||
### Mother side (OSA, new)
|
||||
|
||||
| File | What |
|
||||
|------|------|
|
||||
| `mother-sync-hive-keys.sh` | Pull all pubkeys from vault → rebuild authorized_keys.hive |
|
||||
| `/etc/cron.d/mother-hive-keys` | `@every 5m` cron entry |
|
||||
| sshd_config change | Add `AuthorizedKeysFile ... /var/db/colibri/.ssh/authorized_keys.hive` |
|
||||
|
||||
---
|
||||
|
||||
## Step-by-step
|
||||
|
||||
### A. Key generation (our side)
|
||||
|
||||
```
|
||||
clawdie-enable-mother.sh, new step [1/3]:
|
||||
|
||||
if [ ! -f ~/.ssh/id_ed25519 ]; then
|
||||
ssh-keygen -t ed25519 -N "" -C "colibri@$(hostname)" -f ~/.ssh/id_ed25519
|
||||
fi
|
||||
PUBKEY=$(cat ~/.ssh/id_ed25519.pub)
|
||||
```
|
||||
|
||||
### B. Publish to Vaultwarden (our side)
|
||||
|
||||
```
|
||||
clawdie-enable-mother.sh, new step [2/3]:
|
||||
|
||||
clawdie-vault-fetch --publish-pubkey "$PUBKEY" --collection hive-pubkeys
|
||||
|
||||
What this does:
|
||||
- bw login (using BW_* from provider.env)
|
||||
- bw get collection hive-pubkeys (create if absent)
|
||||
- bw get item "$(hostname)" --collectionid <id>
|
||||
→ if exists: bw edit item <id> notes="$PUBKEY"
|
||||
→ if not: bw create item --name "$(hostname)" --notes "$PUBKEY" --collectionid <id>
|
||||
```
|
||||
|
||||
### C. Update external-mcp.json (our side)
|
||||
|
||||
```
|
||||
clawdie-enable-mother.sh, step [3/3] (existing, with new identity file):
|
||||
|
||||
jq --arg key "$HOME/.ssh/id_ed25519" \
|
||||
'.servers.mother = {
|
||||
"command": "ssh",
|
||||
"args": ["-i", $key, "-o", "StrictHostKeyChecking=accept-new",
|
||||
"colibri@${MOTHER_TS_IP}", "colibri-mcp"],
|
||||
"env": {}
|
||||
}' "$EXTERNAL_MCP" > "$tmp" && mv "$tmp" "$EXTERNAL_MCP"
|
||||
```
|
||||
|
||||
### D. Mother sync (cron)
|
||||
|
||||
```
|
||||
mother-sync-hive-keys.sh:
|
||||
|
||||
1. bw login (BW_* from provider.env)
|
||||
2. COLLECTION_ID=$(bw get collection hive-pubkeys --id)
|
||||
3. bw list items --collectionid $COLLECTION_ID
|
||||
4. For each item:
|
||||
- HOSTNAME=$(bw get item $id | jq -r '.name')
|
||||
- PUBKEY=$(bw get item $id | jq -r '.notes')
|
||||
- echo "command=\"colibri-mcp\",restrict,no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding $PUBKEY colibri@$HOSTNAME"
|
||||
5. Write all to /var/db/colibri/.ssh/authorized_keys.hive (atomic: mktemp + mv)
|
||||
6. chmod 600
|
||||
|
||||
Cron: @every 5m root /usr/local/sbin/mother-sync-hive-keys.sh
|
||||
```
|
||||
|
||||
### E. sshd configuration (mother, one-time)
|
||||
|
||||
```
|
||||
# /etc/ssh/sshd_config addition:
|
||||
AuthorizedKeysFile .ssh/authorized_keys /var/db/colibri/.ssh/authorized_keys.hive
|
||||
|
||||
# Reload:
|
||||
service sshd reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security properties
|
||||
|
||||
| Property | How |
|
||||
|----------|-----|
|
||||
| Rebuild, not append | Each sync regenerates the file — deleting a vault item = revocation |
|
||||
| Restriction applied by mother | `command="colibri-mcp",restrict` — not baked by publisher |
|
||||
| Dedicated key file | `authorized_keys.hive` separate from operator keys |
|
||||
| No shell access | `restrict` blocks everything except the forced command |
|
||||
| Atomic write | `mktemp` + `mv` — no partial reads |
|
||||
| TOFU on first connect | `StrictHostKeyChecking=accept-new` — auto-trust on first connection |
|
||||
|
||||
---
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] Click "Enable Mother" → keypair created if absent
|
||||
- [ ] Pubkey published to Vaultwarden (verify: `bw get item <hostname>`)
|
||||
- [ ] external-mcp.json updated with SSH + identity file
|
||||
- [ ] Mother cron syncs within 5 minutes
|
||||
- [ ] `authorized_keys.hive` contains the restricted entry
|
||||
- [ ] Pi can call mother's tools via `ssh -i key colibri@<ts-ip> colibri-mcp`
|
||||
- [ ] Delete vault item → next sync removes access (revocation tested)
|
||||
|
||||
---
|
||||
|
||||
## Sequencing
|
||||
|
||||
| Step | Repo | Content |
|
||||
|------|------|---------|
|
||||
| 1 | colibri | Extend `clawdie-vault-fetch` with `--publish-pubkey` |
|
||||
| 2 | clawdie-iso | Extend `clawdie-enable-mother.sh` — keygen + publish |
|
||||
| 3 | — | Create `mother-sync-hive-keys.sh` on OSA |
|
||||
| 4 | — | Wire cron + sshd_config on OSA |
|
||||
| 5 | — | End-to-end test: ISO → vault → OSA → SSH → colibri-mcp |
|
||||
|
|
@ -15,6 +15,7 @@ A quick-reference guide to every document in this folder.
|
|||
| [`ISO-ACCEPTANCE-RUNBOOK.md`](ISO-ACCEPTANCE-RUNBOOK.md) | Post-boot acceptance commands after staging Colibri into an ISO | Codex (FreeBSD) |
|
||||
| [`ISO-SERVICE-LAYOUT.md`](ISO-SERVICE-LAYOUT.md) | `rc.conf` service layout for the ISO image | All |
|
||||
| [`MULTI-AGENT-HOST-PLAN.md`](MULTI-AGENT-HOST-PLAN.md) | **Current sprint**: multi-agent task-board tests + CLI surface gaps | All agents |
|
||||
| [`PLAN-MOTHER-MCP-VAULT-KEYS.md`](PLAN-MOTHER-MCP-VAULT-KEYS.md) | Vaultwarden pubkey exchange for mother MCP link (direction B) | Sam & Hermes |
|
||||
| [`PRIORITY-HANDOFF-ISO-SPAWN-COST.md`](PRIORITY-HANDOFF-ISO-SPAWN-COST.md) | ISO boot validation, Pi spawn path, cost mode enforcement (P2/P3 done) | All agents |
|
||||
| [`TRUSS-SPAWN-ANALYSIS.md`](TRUSS-SPAWN-ANALYSIS.md) | truss trace of jail-spawn Permission Denied — root cause + fix | Debugging |
|
||||
| [`VAULT-PROVISION-FIRST-PROOF.md`](VAULT-PROVISION-FIRST-PROOF.md) | First-proof runbook: vault → jail → `.env` chain (clean CLI) | Agents, Sam |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue