Merge pull request 'feat(enable-mother): publish colibri pubkey to Vaultwarden for hive auth' (#99) from hive-key-exchange into main
This commit is contained in:
commit
a7102d293d
1 changed files with 68 additions and 10 deletions
|
|
@ -5,9 +5,13 @@
|
|||
# mother over SSH-stdio and proxies mother's MCP tools to the Pi via its
|
||||
# external-call path. Off by default; this script turns it on.
|
||||
#
|
||||
# Key exchange is vault-mediated: this node publishes its colibri pubkey to
|
||||
# Vaultwarden (item `hive-pubkey-<hostname>`), and the mother node's
|
||||
# `mother-sync-hive-keys` rebuilds its authorized_keys from those items. The
|
||||
# pubkey is also printed as a manual fallback.
|
||||
#
|
||||
# The colibri daemon (and the Pi it spawns) run as the `colibri` user, so the
|
||||
# outbound SSH uses an identity in the colibri home (/var/db/colibri/.ssh).
|
||||
# Run this in a visible terminal so the operator can copy the public key.
|
||||
|
||||
set -eu
|
||||
|
||||
|
|
@ -27,6 +31,48 @@ have() {
|
|||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Publish the colibri pubkey to Vaultwarden as hive-pubkey-<hostname> so a
|
||||
# mother node can authorize it automatically (mother-sync-hive-keys). bw runs as
|
||||
# root so it can read the BW_* bootstrap creds from provider.env; the pubkey is
|
||||
# public, so passing it through the environment is fine. Returns non-zero on any
|
||||
# failure so the caller can fall back to the printed key.
|
||||
publish_pubkey() {
|
||||
mdo -u root env \
|
||||
HIVE_ITEM="hive-pubkey-$(hostname)" \
|
||||
HIVE_PUB="$1" \
|
||||
PROVIDER_ENV="$PROVIDER_ENV" \
|
||||
sh -s <<'PUBLISH'
|
||||
set -eu
|
||||
command -v bw >/dev/null 2>&1 || { echo "bw not found" >&2; exit 4; }
|
||||
. "$PROVIDER_ENV"
|
||||
[ -n "${BW_CLIENTID:-}" ] && [ -n "${BW_CLIENTSECRET:-}" ] && [ -n "${BW_PASSWORD:-}" ] ||
|
||||
{ echo "provider.env lacks BW_* creds" >&2; exit 1; }
|
||||
bw logout >/dev/null 2>&1 || true
|
||||
bw login --apikey >/dev/null 2>&1 || true
|
||||
SESS="$(bw unlock --passwordenv BW_PASSWORD --raw 2>/dev/null)" ||
|
||||
{ echo "bw unlock failed" >&2; exit 1; }
|
||||
[ -n "$SESS" ] || { echo "empty bw session" >&2; exit 1; }
|
||||
bw sync --session "$SESS" >/dev/null 2>&1 || true
|
||||
ITEM_ID="$(bw list items --search "$HIVE_ITEM" --session "$SESS" 2>/dev/null |
|
||||
python3 -c "import sys,json,os
|
||||
n=os.environ['HIVE_ITEM']
|
||||
try: d=json.load(sys.stdin)
|
||||
except Exception: d=[]
|
||||
print(next((i['id'] for i in d if i.get('name')==n), ''))")"
|
||||
if [ -n "$ITEM_ID" ]; then
|
||||
bw get item "$ITEM_ID" --session "$SESS" | python3 -c "import sys,json,os,base64
|
||||
d=json.load(sys.stdin); d['notes']=os.environ['HIVE_PUB']
|
||||
sys.stdout.write(base64.b64encode(json.dumps(d).encode()).decode())" |
|
||||
bw edit item "$ITEM_ID" --session "$SESS" >/dev/null
|
||||
else
|
||||
python3 -c "import json,os,base64
|
||||
print(base64.b64encode(json.dumps({'type':2,'name':os.environ['HIVE_ITEM'],'notes':os.environ['HIVE_PUB']}).encode()).decode())" |
|
||||
bw create item --session "$SESS" >/dev/null
|
||||
fi
|
||||
bw lock >/dev/null 2>&1 || true
|
||||
PUBLISH
|
||||
}
|
||||
|
||||
if ! have mdo; then
|
||||
echo "ERROR: mdo is required to update the colibri service configuration."
|
||||
finish 1
|
||||
|
|
@ -37,7 +83,7 @@ echo " Clawdie — Enable Mother Link"
|
|||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# 1. Mother's reachable address + remote MCP command.
|
||||
# 0. Mother's reachable address + remote MCP command.
|
||||
printf " Mother SSH target (user@tailscale-ip-or-name): "
|
||||
read -r MOTHER_HOST
|
||||
if [ -z "${MOTHER_HOST:-}" ]; then
|
||||
|
|
@ -48,9 +94,9 @@ printf " Mother MCP command [colibri-mcp]: "
|
|||
read -r MOTHER_CMD
|
||||
[ -n "${MOTHER_CMD:-}" ] || MOTHER_CMD="colibri-mcp"
|
||||
|
||||
# 2. Ensure the colibri service account has an SSH key for the outbound link.
|
||||
# 1. Ensure the colibri service account has an SSH key for the outbound link.
|
||||
echo ""
|
||||
echo "[1/4] Ensuring colibri SSH identity..."
|
||||
echo "[1/5] Ensuring colibri SSH identity..."
|
||||
mdo -u root sh -c '
|
||||
set -eu
|
||||
home="$1"; key="$2"
|
||||
|
|
@ -62,9 +108,20 @@ mdo -u root sh -c '
|
|||
fi
|
||||
' sh "$COLIBRI_HOME" "$SSH_KEY"
|
||||
|
||||
# 2. Publish the pubkey to Vaultwarden so mother can authorize it.
|
||||
echo "[2/5] Publishing pubkey to Vaultwarden..."
|
||||
PUBKEY="$(mdo -u root cat "${SSH_KEY}.pub" 2>/dev/null || true)"
|
||||
if [ -z "$PUBKEY" ]; then
|
||||
echo " WARNING: could not read ${SSH_KEY}.pub; skipping publish."
|
||||
elif have bw && publish_pubkey "$PUBKEY"; then
|
||||
echo " Published as hive-pubkey-$(hostname); mother will pick it up on sync."
|
||||
else
|
||||
echo " NOTE: vault publish unavailable; authorize the printed key manually."
|
||||
fi
|
||||
|
||||
# 3. Merge the mother entry into the external MCP registry. Use jq so existing
|
||||
# server entries are preserved (not overwritten), and write atomically.
|
||||
echo "[2/4] Registering mother in ${EXTERNAL_MCP}..."
|
||||
echo "[3/5] Registering mother in ${EXTERNAL_MCP}..."
|
||||
if ! have jq; then
|
||||
echo " ERROR: jq is required to merge the mother entry into ${EXTERNAL_MCP}."
|
||||
finish 1
|
||||
|
|
@ -84,7 +141,7 @@ printf '%s\n' "$existing" |
|
|||
' sh "$EXTERNAL_MCP"
|
||||
|
||||
# 4. Allow external MCP calls: upsert COLIBRI_MCP_EXTERNAL_CALL=1 into provider.env.
|
||||
echo "[3/4] Enabling external MCP calls..."
|
||||
echo "[4/5] Enabling external MCP calls..."
|
||||
mdo -u root sh -c '
|
||||
set -eu
|
||||
f="$1"
|
||||
|
|
@ -97,15 +154,16 @@ mdo -u root sh -c '
|
|||
' sh "$PROVIDER_ENV"
|
||||
|
||||
# 5. Restart the daemon so the Pi inherits the new env + registry.
|
||||
echo "[4/4] Restarting colibri daemon..."
|
||||
echo "[5/5] Restarting colibri daemon..."
|
||||
mdo -u root service colibri_daemon restart >/dev/null 2>&1 ||
|
||||
echo " WARNING: restart failed; run: mdo -u root service colibri_daemon restart"
|
||||
|
||||
echo ""
|
||||
echo "Mother link configured. Authorize this key on mother (restrict it to the"
|
||||
echo "MCP command, e.g. command=\"${MOTHER_CMD}\",restrict in authorized_keys):"
|
||||
echo "Mother link configured. If the vault publish succeeded, mother authorizes"
|
||||
echo "this key automatically on its next sync. Manual fallback — add to mother's"
|
||||
echo "authorized_keys, restricted to the MCP command:"
|
||||
echo ""
|
||||
mdo -u root cat "${SSH_KEY}.pub" 2>/dev/null || echo " (could not read ${SSH_KEY}.pub)"
|
||||
echo " command=\"${MOTHER_CMD}\",restrict,no-pty $(mdo -u root cat "${SSH_KEY}.pub" 2>/dev/null || echo '<pubkey unavailable>')"
|
||||
echo ""
|
||||
echo "Once authorized on mother, the Pi can call mother's tools via colibri-mcp."
|
||||
finish 0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue