Skip to content

fix(adk): fast-follow fixes for ADK v2 CLI, MCP subprocess propagation, and credential auto-detection - #309

Open
dandye wants to merge 27 commits into
mainfrom
fix/run-with-adk-fast-follow
Open

fix(adk): fast-follow fixes for ADK v2 CLI, MCP subprocess propagation, and credential auto-detection#309
dandye wants to merge 27 commits into
mainfrom
fix/run-with-adk-fast-follow

Conversation

@dandye

@dandye dandye commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Comprehensive fast-follow hardening, security improvements, and modernized web console for run-with-google-adk following the ADK v2 migration (#303):

  • Live ADK Agent Execution & Streaming: Replaced placeholder endpoints with live Google ADK Runner session execution. Streams model text and tool execution events via Server-Sent Events (SSE) with clean HTTP content negotiation and OpenAPI schema preservation.
  • Modernized Zero-Build SecOps Console: Consolidated legacy multi-page Bootstrap templates into a reactive, zero-build Single Page Application (static/index.html, app.css, app.js):
    • Fail-closed XSS sanitization via DOMPurify.
    • In-flight request abortion when resetting sessions or switching user alias.
    • Strict viewport height constraints (height: 100vh) with custom thin scrollbars and sticky input console.
    • Professional typography and custom SVG icons (zero decorative emojis).
    • Dynamic MCP tool status indicators and non-blocking toast notifications.
  • Subprocess Isolation with Dynamic Launcher Fallback: Propagates credentials (GOOGLE_APPLICATION_CREDENTIALS, CLOUDSDK_CONFIG, SECOPS_SA_PATH) to child MCP servers while decoupling Chronicle SIEM from Google Cloud Project. Dynamically executes via uv run if available, gracefully falling back to sys.executable with PYTHONPATH on standard pip installations.
  • Memory Boundedness & Concurrency Hardening:
    • Implemented BoundedSessionService with reentrant locking (threading.RLock) and FIFO eviction capped at 1,000 sessions, pruning empty user and application dictionaries.
    • Added double-checked locking on agent singletons (get_runner, get_session_service, agent._root_agent) to prevent race conditions on cold starts.
    • Handled asyncio.CancelledError on client disconnection and aligned /favicon.ico with RFC 7230 (HTTP 204 No Content).
  • Identity Auto-Discovery & Dynamic CLI: Cached discover_user_identity() auto-detects active operator identity from ADC, google.auth, or gcloud. Lazy agent exports in agent.py allow CLI runtime flags (--secops, --scc, --gti, --soar, --model, --project) to dynamically configure the agent before instantiation.
  • Clean Configuration Template: Standardized .env.example with empty placeholders, ignoring .env* and IDE artifacts in .gitignore.

Verification

  • Hermetic Unit Test Suite: All 44 tests passing in 2.81s:
    uv run --extra test pytest run-with-google-adk/tests/ -v
  • Coverage: Verified thread-safe session eviction/pruning, dynamic uv launcher fallback, fail-closed XSS sanitization, stream abortion, identity discovery, and layout scroll constraints.
  • Manual & Browser Testing: Verified live Chronicle SIEM and Cloud SCC investigations end-to-end via web UI and CLI.

…lags

- Implement lazy export via __getattr__ in mcp_security_agent.__init__ to prevent premature agent instantiation when importing __version__
- Dynamically instantiate and register root_agent with active AgentSettings in chat() and serve() CLI commands
- Clean up test isolation in test_agent and test_toolsets to prevent sys.modules pollution across test files
- Add assertions verifying root_agent.tools updates when tool flags (--secops/--no-secops) are supplied

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Add _discover_local_adc() in AgentSettings to locate .gcloud/application_default_credentials.json across workspace candidates
- Add bootstrap_environment() to automatically export GOOGLE_APPLICATION_CREDENTIALS, CLOUDSDK_CONFIG, Vertex AI activation, and Cloudtop mTLS bypass variables
- Enhance info command to display resolved GCP Project and ADC path
- Update CLI tests to assert on Project and ADC status

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
… subprocesses

- Pass stdio_env with GOOGLE_APPLICATION_CREDENTIALS, CLOUDSDK_CONFIG, CHRONICLE_PROJECT_ID, CHRONICLE_CUSTOMER_ID, and Cloudtop mTLS bypass to StdioServerParameters
- Prevents MCP stdio subprocesses from stripping credentials and falling back to expired global ADC or hardcoded project IDs
- Update test_cli_chat_tool_flags assertions

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
…cruft

- Remove obsolete directory references (./google-mcp-security-agent)
- Replace legacy sample.env.properties block with actual sample.env template and complete environment variable table
- Remove obsolete references to deleted v1 scripts (Agent Engine, Discovery Engine AgentSpace, session/artifact services, MAX_PREV_USER_INTERACTIONS)
- Document all CLI subcommands and options (--secops, --scc, --gti, --soar, --vertex, --model, --project, --customer-id)
- Fix Table of Contents and duplicate heading numbers
- Add Testing & Verification instructions

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
…errors without VT API key

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
…icit override support

- Auto-enable GTI tools if VT_APIKEY is populated (and not placeholder NOT_SET)
- Auto-enable SOAR tools if SOAR_URL and SOAR_APP_KEY are populated
- Auto-enable SecOps SIEM tools if CHRONICLE_PROJECT_ID and CHRONICLE_CUSTOMER_ID are populated
- Respect explicit LOAD_*_MCP environment variables or CLI flags (--no-gti, --no-soar, etc.) when provided
- Update sample.env and README.md to document credential auto-detection
- Add comprehensive test coverage in test_config.py

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
…lean empty checks

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
@dandye
dandye requested a review from a team September 8, 2026 22:12
…options, and env precedence

- Decouple CHRONICLE_PROJECT_ID from GOOGLE_CLOUD_PROJECT in MCP stdio subprocess environment, preventing cross-tenant project clobbering for SCC.
- Propagate SECOPS_SA_PATH and SECOPS_IMPERSONATE_SERVICE_ACCOUNT to child MCP processes.
- Use env.setdefault for mTLS bypass environment variables.
- Fix .env precedence order in config.py so local working directory configuration overrides repo-root settings.
- Fix bootstrap_environment to properly export GOOGLE_API_KEY to os.environ and avoid forcing Vertex AI when an API key is provided.
- Expose --vertex/--no-vertex, --model, --project, and --customer-id flags on CLI chat and serve commands, plus --reload and $PORT fallback on serve.
- Make root_agent in agent.py lazily instantiated via module __getattr__ to avoid premature default creation at import time.
- Remove non-empty placeholders from sample.env to prevent false auto-detection upon copying to .env.
- Correct SSE streaming endpoint syntax and testing instructions in README.md.
- Expand unit test suite to 30 tests covering credential propagation, CLI overrides, and environment bootstrapping.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
Rename the environment template to standard .env.example and update setup instructions across README and docs.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
Ignore all .env* variations (e.g. .env.argolis, .env.local) to prevent credentials from being tracked, keeping .env.example force-tracked.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
Align anchor link with the Google ADK Autonomous SOC Agent section heading.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
…ling

- Default username to localStorage or secops_user in landing_script.js instead of popping an alert and redirecting to / in an infinite loop.
- Add routes for /login, /index.html, and /landing.html in FastAPI server.
- Support both JSON REST queries and SSE streaming on POST /chat.
- Persist username to localStorage on login and clear it on logout.
- Expand server unit test suite to 32 tests.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Append cache-busting query parameter (?v=2.0.2) to landing_script.js and index_script.js in HTML templates.
- Add HTTP middleware in app.py to send Cache-Control: no-cache, no-store, must-revalidate on static assets and page routes to prevent browser memory/disk cache entrapment.
- Add /favicon.ico route returning 204 No Content to avoid browser 404 errors.
- Expand test_server.py to 34 unit tests verifying cache-control headers and favicon response.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Replace legacy multi-page Bootstrap UI and blocking alert() popups with a modern, zero-build Single Page Application.
- Unify interface into static/index.html with Google SecOps / Material 3 dark-first styling in static/app.css.
- Implement non-blocking toast notifications for errors, theme changes, and operator profile updates in static/app.js.
- Add live MCP server status pills (SIEM, SCC, GTI, SOAR) fetched dynamically from /info.
- Add quick SOC prompt cards (Triage Alert, Threat Hunt, GTI Reputation, SCC Audit) and session management.
- Provide one-click copy buttons for code snippets, UDM queries, and tool payloads.
- Delete obsolete legacy assets: static/landing.html, static/landing_script.js, and static/index_script.js.
- Unify FastAPI routes in server/routes.py to serve the modern console.
- Expand hermetic test suite to 35 passing unit tests.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Replace decorative unicode emojis with clean SVG icons and standard typography in static/index.html.
- Add SVG shield favicon data URI and SVG empty-state graphic.
- Replace theme toggle emoji with SVG theme icon.
- Bump cache buster query parameter to v2.1.1 for instant client refresh.
- Add unit test test_index_html_no_emojis to verify zero emojis in web console.

TAG=agy
CONV=ad3258db-3ab7-4cda-89a7-62fdf635bcf8
…ironment

- Add discover_user_identity() in config.py to resolve operator identity from ADC account/client_email, google.auth credentials, active gcloud account, or OS user before falling back to secops_user.
- Return detected user in /get_session and /info endpoints.
- Update web console (app.js and index.html) to dynamically display detected user identity on load while preserving manual operator override.
- Expand hermetic test suite to 37 passing unit tests with mocked subprocess/auth checks in test_config.py and test_server.py.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Replace the placeholder echo mock in sse_event_generator with real ADK Runner execution.
- Initialize ADK Runner with InMemorySessionService and configured SecurityOperationsAgent.
- Stream model text, function call events (with tool name and JSON args), and function response events over Server-Sent Events (SSE).
- Support non-streaming REST queries by accumulating runner response parts on POST /chat.
- Update test_server.py with hermetic MockRunner test coverage.

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Replaced status and tool streaming emojis with text tags ([Warning], [Tool], [Error])
- Added test coverage in test_server.py verifying zero emojis in static assets and server stream responses

TAG=agy
CONV=1fede0e5-2332-4f6a-b461-ab44b08b4ff5
- Enforce strict 100vh viewport height on html and body to prevent document expansion.
- Add min-height: 0 and flex-basis on .app-layout, .chat-workspace, and .messages-container so chat results scroll internally within the viewport.
- Pin chat-input-area cleanly at the bottom of the viewport.
- Add custom thin scrollbar styles for WebKit and Firefox browsers.
- Bump cache buster query parameters to v2.1.2.
- Add unit test test_scroll_and_layout_constraints in tests/test_server.py.

TAG=agy
CONV=ad3258db-3ab7-4cda-89a7-62fdf635bcf8
…and concurrency

- Mitigate XSS vulnerability by loading DOMPurify and sanitizing all rendered markdown in app.js.
- Prevent unbounded memory leaks in long-running services by implementing BoundedSessionService with FIFO/LRU eviction (capped at 1000 sessions).
- Eliminate concurrency race condition in get_runner() and get_session_service() using double-checked locking with threading.Lock.
- Cache get_settings() to avoid repeated environment and file parsing on every /info request.
- Fix stream accumulation to concatenate streaming text tokens cleanly while formatting tool/error cards.
- Gracefully handle asyncio.CancelledError on client disconnection in SSE generator.
- Fix test isolation in test_agent.py by directly patching google.adk.agents.llm_agent.LlmAgent.
- Add unit tests test_bounded_session_service_eviction and test_dompurify_xss_protection.

TAG=agy
CONV=ad3258db-3ab7-4cda-89a7-62fdf635bcf8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants