Skip to content

fix(gateway/fgac): filter semantic search results by scope + add search tests - #1987

Open
rhbelson wants to merge 2 commits into
awslabs:mainfrom
rhbelson:fix/fgac-semantic-search-filter
Open

fix(gateway/fgac): filter semantic search results by scope + add search tests#1987
rhbelson wants to merge 2 commits into
awslabs:mainfrom
rhbelson:fix/fgac-semantic-search-filter

Conversation

@rhbelson

Copy link
Copy Markdown

The Fine-Grained Access Control (FGAC) tutorial documents three access-control patterns, including pattern 2:

Semantic search with FGAC (RESPONSE interceptor) — filter search results so users only see tools they have access to

…but that pattern was neither enforced nor tested:

  • The RESPONSE interceptor only filtered the tools/list response shapes (result.tools / result.structuredContent.tools). Semantic-search results (x_amz_bedrock_agentcore_search) were not filtered, so a scoped user could discover tools they cannot access.
  • The demo (invoke.py) and the README Test Cases table covered only tools/call (Tests 1–5) and tools/list (Tests 6–7). There was no semantic-search test, despite the README promising pattern 2.

This is the gap reported during Diving Deep with AgentCore Workshop (v2) prep.

Changes

  1. RESPONSE interceptor Lambda (cloudformation/fine-grain-access-control/fgac-interceptors-stack.yaml): filter the semantic-search response in addition to tools/list. It now scope-filters every shape the gateway may emit:

    • result.tools
    • result.structuredContent.tools
    • a JSON string in result.content[*].text carrying {"tools": [...]}

    Non-JSON text content passes through untouched. Handling all three shapes makes the filter robust to the response format the gateway returns for search.

  2. Demo (scripts/fine-grain-access-control/invoke.py): add Test 8 (search with getOrder scope → only getOrder returned) and Test 9 (search with full scope → multiple tools), plus an extract_search_tools() helper tolerant of all three response shapes.

  3. README (04-advanced-concepts/fine-grain-access-control/README.md): add rows 8 and 9 to the Test Cases table so the documented tests match the demo and the promised pattern 2.

Testing / verification note

Inline Lambda code and invoke.py were validated to parse/compile. I was not able to run this against a live FGAC gateway, so the interceptor change is written defensively to cover whichever response shape the gateway emits for x_amz_bedrock_agentcore_search, and is verified by inspection rather than a live run. A maintainer with a standing FGAC gateway should confirm the exact search-response shape and that Tests 8–9 pass end-to-end before merge.

rbelson@amazon.com added 2 commits August 23, 2026 18:53
…ch tests

The FGAC tutorial documents three access-control patterns, including
pattern 2: 'Semantic search with FGAC (RESPONSE interceptor) - filter
search results so users only see tools they have access to'. But the
RESPONSE interceptor only filtered tools/list shapes (result.tools /
result.structuredContent.tools), and the demo (invoke.py) plus the
README Test Cases table exercised only tools/call and tools/list - no
semantic-search coverage, despite the README promising it.

Changes:
- RESPONSE interceptor Lambda (fgac-interceptors-stack.yaml): also filter
  the semantic-search response, whichever shape the gateway emits -
  result.tools, result.structuredContent.tools, and a JSON string in
  result.content[*].text carrying {"tools": [...]}. Non-JSON text content
  passes through untouched. So x_amz_bedrock_agentcore_search results are
  now scope-filtered like tools/list.
- invoke.py: add Test 8 (search with getOrder scope -> only getOrder) and
  Test 9 (search with full scope -> multiple tools), plus an
  extract_search_tools() helper tolerant of all three response shapes.
- README: add rows 8 and 9 to the Test Cases table so the documented tests
  match the demo and the promised pattern 2.
…ltering

Extracts the inline RESPONSE-interceptor Lambda from the CloudFormation
template and exercises lambda_handler against synthetic gateway events —
no AWS, no live gateway, no network. Asserts scope-based filtering across
all three response shapes (result.tools, structuredContent.tools, and the
semantic-search content[*].text JSON payload): a limited scope keeps only
the authorized tool, a full scope keeps all, non-JSON text is untouched,
and a missing token fails safe. 5/5 pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant