Fine-grained access control for Amazon Bedrock Managed Knowledge Base tools Amazon Web Services published a design for fine-grained access control in AI agents that search Amazon Bedrock Managed Knowledge Base, injecting identity-provider-verified user attributes into tool calls at the Amazon Bedrock AgentCore Gateway layer rather than letting the large language model set the search scope. The approach uses Managed Knowledge Base's ACL awareness feature, which returns only documents a user may view when a search request carries a userContext with the user's email in userId, and adds independent defense layers in case that mechanism is bypassed. The post argues the risk is concrete: if a search tool takes "who to search as" as an argument, the LLM decides that value, so a prompt injection or LLM error could make an agent search as a different employee or, in multi-tenant SaaS, expose one customer's data to another. Artificial Intelligence https://aws.amazon.com/blogs/machine-learning/ Fine-grained access control for Amazon Bedrock Managed Knowledge Base tools More enterprises are building AI agents into their daily work, and a common pattern is an agent that searches internal documents to compose its answers. A single organization might soon run hundreds of agents, each connected to many data sources and tools. This raises a question. When an agent searches on behalf of a user, can you make sure that it uses only the information that user is allowed to see? Consider AnyCompany, a fictional company that builds an internal assistant shared by all employees. An employee in department A asks, “Compare my department’s business plan with the notice to all departments, and list the initiatives that are behind schedule.” The agent writes its own search queries and keeps searching internal documents until it has enough information. Employees in department B ask the same assistant the same question. If the application doesn’t scope searches to each user, the department B business plan can end up in an answer to an employee in department A. If you replace the departments with customer companies, the same problem occurs in a multi-tenant software as a service SaaS architecture where multiple customers share one assistant and knowledge base. Controlling access to multi-tenant data through this agent is harder than in traditional applications. In a traditional application, the application code determines who the signed-in user is and searches with that user’s permissions. In an agent, a large language model LLM decides at runtime which tool to call and with which arguments. If a search tool takes “who to search as” as an argument, the LLM decides that value too. A prompt injection or an LLM error might then make the agent search as a different employee. In this post, we build an internal assistant for AnyCompany. All employees share the same agent and knowledge base, yet each employee can search only the documents they’re allowed to view. We use Amazon Bedrock Managed Knowledge Base https://docs.aws.amazon.com/bedrock/latest/userguide/kb-build-managed.html as the search backend and expose it to the agent as Model Context Protocol MCP tools through Amazon Bedrock AgentCore Gateway https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway.html , a capability of Amazon Bedrock AgentCore. The design principle is to not let the LLM decide who the user is. Instead, trusted code decides, based on information that your identity provider has verified. On top of that, we add independent layers of defense in case that mechanism has a bug or is bypassed. Solution overview Managed Knowledge Base has a feature called ACL awareness https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-acl.html . When a search request includes a user context userContext with the user’s email in userId , the knowledge base returns only the documents that user is allowed to view. If your application calls the search API directly, the application code sets the search scope from the authentication result. Build multi-tenant agentic chat applications on enterprise data with Amazon Bedrock Managed Knowledge Base https://aws.amazon.com/blogs/machine-learning/build-multi-tenant-agentic-chat-applications-on-enterprise-data-with-amazon-bedrock-managed-knowledge-base/ shows this pattern. When you expose the knowledge base as an MCP tool through AgentCore Gateway, however, userContext becomes a tool argument, and the LLM constructs its value. Neither the gateway nor the knowledge base verifies that this value belongs to the authenticated user. This solution injects verified user attributes into tool calls at the tool layer AgentCore Gateway . It then scopes the search by those attributes at the resource layer Managed Knowledge Base . The sample stores three documents in a single knowledge base: business plans for department A and department B, and a notice shared with all departments. Two users, user-a in department A and user-b in department B, search through the same agent. The following diagram shows the architecture. The request flow is as follows. The step numbers correspond to the numbers in Figure 1. Figure 1 omits the call from the web app to AgentCore runtime, a capability of Amazon Bedrock AgentCore, so its step numbers differ from the diagram in the repository README https://github.com/aws-samples/sample-managed-knowledge-base-patterns/blob/main/agentcore-access-control/README.md . 1. The user signs in with Amazon Cognito and receives an access token, a JSON Web Token JWT . A pre token generation AWS Lambda trigger adds an email claim to it. The agent forwards this token in the Authorization header when it sends MCP requests to the gateway. 2. The JWT authorizer of the gateway validates the signature, expiration, and client ID of the token. 3. A request interceptor an AWS Lambda function on the gateway resolves the email from the validated token and overwrites the userContext argument of tools/call . 4. Policy in Amazon Bedrock AgentCore Policy in AgentCore evaluates the modified request against a Cedar policy. It denies the request if userContext.userId doesn’t match the email claim in the JWT. 5. The connector target calls the Managed Knowledge Base search API with the execution role of the gateway. The resource-based policy of the knowledge base denies searches from principals other than this role. 6. With ACL awareness, the knowledge base returns only chunks from documents that the userContext user is allowed to view. The four mechanisms map to layers and lines of defense as follows. | | Tool layer AgentCore Gateway | Resource layer Managed Knowledge Base | | Primary defense | Request interceptor: injects userContext deterministically from the verified token, which helps prevent the LLM or the client from spoofing it | ACL awareness: returns only the documents that the userContext user is allowed to view | | Secondary defense | Policy in AgentCore: checks the injected userContext against the token and denies requests that don’t match | Resource-based policy: denies search requests from principals other than the gateway execution role | For requests that go through the gateway, the two primary defenses are enough to achieve fine-grained access control, as long as no other principal can call the knowledge base. ACL awareness filters results based on the userContext that it receives and isn’t an authorization mechanism by itself https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-s3-acl.html . The two secondary defenses cover cases where an assumption behind the primary defenses fails, such as an interceptor bug or a principal that calls the knowledge base without going through the gateway. Add them based on your requirements. If other principals in the account have bedrock:Retrieve permissions, add the resource-based policy. The rest of this post covers ACL awareness, the MCP tools for Managed Knowledge Base, the request interceptor, Policy in AgentCore, and the resource-based policy, in that order. Prerequisites - An AWS account and AWS Identity and Access Management IAM permissions to create the resources in this post. - An AWS Region where Managed Knowledge Base, AgentCore Gateway, Policy in AgentCore, and AgentCore runtime are available. - Access to the Amazon Bedrock model that the agent uses. - Node.js 22 or later and npm. - uv https://docs.astral.sh/uv/ , to package the agent and run the verification script. - If you adapt the pattern to an existing Amazon Cognito user pool, the user pool must be on the Essentials or Plus feature plan, which access token customization requires. The stack in this post creates a user pool on the Essentials plan. You can deploy the architecture in Figure 1 with a single AWS Cloud Development Kit AWS CDK stack from the agentcore-access-control directory https://github.com/aws-samples/sample-managed-knowledge-base-patterns/tree/main/agentcore-access-control of the sample-managed-knowledge-base-patterns repository. Run the commands in this post from that directory. The repository installs the AWS CDK CLI and aws-cdk-lib 2.274.0 or later as npm dependencies. The stack also deploys a web app on Amazon CloudFront and runs the agent, built with Strands Agents, on Amazon Bedrock AgentCore runtime. By default, the agent uses Claude Sonnet 5.5 through the global cross-Region inference profile global.anthropic.claude-sonnet-5-5 . The agent forwards the access token of the signed-in user to the gateway and contains no access control logic. For deployment steps, including how to fetch only this directory, see the README https://github.com/aws-samples/sample-managed-knowledge-base-patterns/blob/main/agentcore-access-control/README.md . Scope searches per user with ACL awareness Managed Knowledge Base is a new type of Amazon Bedrock Knowledge Base. You connect a data source, and it runs parsing, chunking, embedding, indexing, search, and reranking as a fully managed service. It provides two search APIs. Retrieve runs a hybrid search. AgenticRetrieveStream breaks a query into subqueries and searches multiple knowledge bases iteratively. ACL awareness keeps the access permissions of the data source at ingestion time. At search time, it returns only the documents that the user can view. For an Amazon Simple Storage Service Amazon S3 data source, you define ACLs https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-ds-s3-acl.html either in a global ACL file per S3 prefix or in a metadata file per document. The sample in this post uses metadata files. When you place the following metadata file at the same S3 path as the document, only user-a can retrieve dept-a-plan.txt . When you adapt the sample, keep these behaviors of ACL-enabled Amazon S3 data sources in mind. A document without an ACL entry isn’t ingested. A change to the global ACL file requires reindexing the affected prefix, while per-document metadata files reindex only the affected documents and take precedence over the global file. Amazon S3 has no real-time ACL verification, so an ACL change applies after the next sync. ACL mistakes don’t return errors. The affected documents are silently left out of the results. At query time, pass the user’s email in the top-level userContext.userId for both Retrieve and AgenticRetrieveStream . Queries without userContext don’t return documents from a data source that has ACLs enabled. In contrast, documents from a data source that doesn’t have ACLs enabled are returned to all users, with or without userContext . The following diagram shows the ACLs that the knowledge base keeps for the three sample documents at ingestion, and the search results for each userContext . Managed Knowledge Base doesn’t authenticate end users. It trusts the userContext that it receives and filters results based on it. Passing a verified userContext is the responsibility of the caller https://docs.aws.amazon.com/bedrock/latest/userguide/kb-managed-acl.html . Expose Managed Knowledge Base as MCP tools When you create a Managed Knowledge Base connector target https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-target-connector-managed-kb.html on AgentCore Gateway, you can expose two MCP tools: