-
Notifications
You must be signed in to change notification settings - Fork 98
fix(runner,rbac,cli,routes): credential auth reliability and SSE improvements #1231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
bf6be85
8af45d4
f998e54
029062d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,7 +17,7 @@ | |
| from urllib.parse import urlparse | ||
|
|
||
| from ambient_runner.platform.context import RunnerContext | ||
| from ambient_runner.platform.utils import get_bot_token | ||
| from ambient_runner.platform.utils import get_bot_token, refresh_bot_token | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
@@ -183,18 +183,45 @@ def _do_req(): | |
| f"and BOT_TOKEN fallback also failed" | ||
| ) from fallback_err | ||
| if e.code in (401, 403): | ||
| logger.warning( | ||
| f"{credential_type} credential fetch failed with HTTP {e.code}: {e}" | ||
| ) | ||
| raise PermissionError( | ||
| f"{credential_type} authentication failed with HTTP {e.code}" | ||
| ) from e | ||
| # BOT_TOKEN may have expired — refresh from CP endpoint and retry once. | ||
| return _retry_with_fresh_bot_token(e.code) | ||
|
Comment on lines
185
to
+187
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle 401/403 from the caller-token BOT_TOKEN fallback too. This retry only runs when the first request was sent with Patch idea try:
with _urllib_request.urlopen(fallback_req, timeout=10) as resp:
return resp.read().decode("utf-8", errors="replace")
+ except _urllib_request.HTTPError as fallback_err:
+ if fallback_err.code in (401, 403):
+ logger.warning(
+ f"{credential_type} BOT_TOKEN fallback got {fallback_err.code}; refreshing from CP endpoint and retrying"
+ )
+ return _retry_with_fresh_bot_token(fallback_err.code)
+ logger.warning(
+ f"{credential_type} BOT_TOKEN fallback also failed: {fallback_err}"
+ )
+ raise PermissionError(
+ f"{credential_type} authentication failed with HTTP {fallback_err.code}"
+ ) from fallback_err
except Exception as fallback_err:
logger.warning(
f"{credential_type} BOT_TOKEN fallback also failed: {fallback_err}"
)
raise PermissionError(🤖 Prompt for AI Agents |
||
| logger.warning(f"{credential_type} credential fetch failed: {e}") | ||
| return "" | ||
| except Exception as e: | ||
| logger.warning(f"{credential_type} credential fetch failed: {e}") | ||
| return "" | ||
|
|
||
| def _retry_with_fresh_bot_token(original_code: int): | ||
| logger.info( | ||
| f"{credential_type} got {original_code} with cached BOT_TOKEN — refreshing from CP endpoint and retrying" | ||
| ) | ||
| try: | ||
| fresh_bot = refresh_bot_token() | ||
| except Exception as refresh_err: | ||
| logger.warning(f"{credential_type} CP token refresh failed: {refresh_err}") | ||
| raise PermissionError( | ||
| f"{credential_type} authentication failed with HTTP {original_code}" | ||
| ) from refresh_err | ||
|
Comment on lines
+194
to
+204
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Coalesce CP token refreshes across concurrent failures. Line 209 can run once per failing provider fetch. 🤖 Prompt for AI Agents |
||
| retry_req = _urllib_request.Request(url, method="GET") | ||
| if fresh_bot: | ||
| retry_req.add_header("Authorization", f"Bearer {fresh_bot}") | ||
| if context.current_user_id: | ||
| retry_req.add_header("X-Runner-Current-User", context.current_user_id) | ||
| try: | ||
| with _urllib_request.urlopen(retry_req, timeout=10) as resp: | ||
|
Comment on lines
+205
to
+211
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf 'Guard and retry callsites:\n'
sed -n '121,131p;215,221p' components/runners/ambient-runner/ambient_runner/platform/auth.py
printf '\nurlparse() behavior for representative BACKEND_API_URL values:\n'
python - <<'PY'
from urllib.parse import urlparse
samples = [
"https://ambient-api-server.svc.cluster.local",
"http://localhost:8080",
"file:///tmp",
"data:text/plain,hello",
]
for value in samples:
p = urlparse(value)
allowed = bool(p.hostname) and (
p.hostname.endswith(".svc.cluster.local")
or p.hostname.endswith(".svc")
or p.hostname in {"localhost", "127.0.0.1"}
)
print(
f"{value!r} -> scheme={p.scheme!r}, hostname={p.hostname!r}, "
f"current_guard_rejects={bool(p.hostname and not allowed)}"
)
PYRepository: ambient-code/platform Length of output: 1365 Guard hostless and non-HTTP(S) schemes in addition to hostname allowlist. The current guard 🧰 Tools🪛 Ruff (0.15.9)[error] 215-215: Audit URL open for permitted schemes. Allowing use of (S310) [error] 221-221: Audit URL open for permitted schemes. Allowing use of (S310) 🤖 Prompt for AI Agents |
||
| logger.info(f"{credential_type} retry with fresh BOT_TOKEN succeeded") | ||
| return resp.read().decode("utf-8", errors="replace") | ||
| except _urllib_request.HTTPError as retry_err: | ||
| logger.warning(f"{credential_type} retry with fresh BOT_TOKEN failed: {retry_err}") | ||
| raise PermissionError( | ||
| f"{credential_type} authentication failed with HTTP {retry_err.code}" | ||
| ) from retry_err | ||
| except Exception as retry_err: | ||
| logger.warning(f"{credential_type} retry with fresh BOT_TOKEN failed: {retry_err}") | ||
| raise PermissionError( | ||
| f"{credential_type} authentication failed with HTTP {original_code}" | ||
| ) from retry_err | ||
|
|
||
| resp_text = await loop.run_in_executor(None, _do_req) | ||
| if not resp_text: | ||
| return {} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Raise the scanner limit before previewing tool results.
bufio.Scannerstill caps each SSE line at 64 KiB. Now thatTOOL_CALL_RESULTconsumes fullevt.Content, one large result can terminateacpctl session send -fwithbufio.ErrTooLong.Patch
out := cmd.OutOrStdout() scanner := bufio.NewScanner(stream) + scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024) var reasoningBuf strings.Builder var inText boolExpected: this file shows no
scanner.Buffercall today; if emitters stream full tool-result payloads, the current scanner limit is enough to abort the stream.🤖 Prompt for AI Agents