Files
agent-runtime-framework/harnesses/contexts/z-ai/v1/init.sh
Paul O'Reilly 12c2172835 fix(minimax,z-ai): stage api_key as root, restore mount mode 0400
Mirrors agent-runtimes commit 6f20b51. CRS serves these harness files to
dispatchers, so this repo must match.

Switches from "mount mode 0444 so the agent user can `cat` the ESO file"
to the gitea-ssh staging pattern: keep the ESO mount root-only (0400),
init.sh as root `install`s a per-secret 0600 agent-owned copy, and
apiKeyHelper points at the staged copy. Stronger blast-radius guarantee
— if the ESO Secret later grows additional keys, they remain root-only
unless the harness explicitly stages them.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-07 20:43:13 +12:00

70 lines
2.5 KiB
Bash
Executable File

#!/bin/bash
# z-ai init — stage the auth_token for the agent user and wire apiKeyHelper.
#
# Threat model: keep the ESO mount root-only (mode 0400) so the agent user
# cannot directly read /run/agent/secrets/z-ai/*. init.sh runs as root and
# stages a single per-secret copy of auth_token into the agent's home with
# mode 0600. Only that staged file is reachable by the runtime; any other
# files in the ESO Secret (e.g. legacy base_url) stay root-only.
#
# Rotation handling: this is a one-shot copy at container start. Ephemeral
# container agents always run init.sh per task — no rotation gap there.
# Long-running sessions need a future scripts.control_loop hook to refresh
# the copy between agent CLI invocations.
#
# Auth wire-up: apiKeyHelper output routes to `Authorization: Bearer <value>`
# when ANTHROPIC_BASE_URL is non-anthropic.com (set in harness.yaml to
# https://api.z.ai/api/anthropic). The secret value never enters env or any
# process' /proc/<pid>/environ.
set -euo pipefail
ESO_AUTH_TOKEN="/run/agent/secrets/z-ai/auth_token"
if [ ! -r "$ESO_AUTH_TOKEN" ]; then
echo "ERROR: $ESO_AUTH_TOKEN not readable. Check ESO ExternalSecret acct-<z-ai-id>." >&2
exit 1
fi
AGENT_USER="${AGENT_USER:-agent}"
AGENT_HOME=$(getent passwd "$AGENT_USER" | cut -d: -f6)
if [ -z "$AGENT_HOME" ] || [ ! -d "$AGENT_HOME" ]; then
AGENT_HOME="/home/$AGENT_USER"
fi
# Stage the auth_token into a per-secret path owned by agent, mode 0600.
STAGED_KEY_DIR="$AGENT_HOME/.claude/secrets"
STAGED_KEY="$STAGED_KEY_DIR/z-ai-auth-token"
mkdir -p "$STAGED_KEY_DIR"
chown "$AGENT_USER:" "$STAGED_KEY_DIR" 2>/dev/null || true
chmod 0700 "$STAGED_KEY_DIR"
install -m 0600 -o "$AGENT_USER" -g "$AGENT_USER" "$ESO_AUTH_TOKEN" "$STAGED_KEY"
# Wire apiKeyHelper at the staged copy.
CONFIG_DIR="${CLAUDE_CONFIG_DIR:-$AGENT_HOME/.claude}"
mkdir -p "$CONFIG_DIR"
chown "$AGENT_USER:" "$CONFIG_DIR" 2>/dev/null || true
chmod 0755 "$CONFIG_DIR"
SETTINGS_FILE="$CONFIG_DIR/settings.json"
if [ -f "$SETTINGS_FILE" ] && command -v jq >/dev/null 2>&1; then
TMP=$(mktemp)
jq --arg helper "cat $STAGED_KEY" \
'. + {apiKeyHelper: $helper}' \
"$SETTINGS_FILE" > "$TMP"
mv "$TMP" "$SETTINGS_FILE"
else
cat > "$SETTINGS_FILE" <<EOF
{
"apiKeyHelper": "cat $STAGED_KEY"
}
EOF
fi
chown "$AGENT_USER:" "$SETTINGS_FILE" 2>/dev/null || true
chmod 0644 "$SETTINGS_FILE"
echo "z-ai auth_token staged at $STAGED_KEY (0600 $AGENT_USER:$AGENT_USER)"
echo "z-ai apiKeyHelper wired in $SETTINGS_FILE"