Implementing Tenant Isolation Using Agents for Amazon Bedrock in a Multi-Tenant Environment

Implementing Tenant Isolation Using Agents for Amazon Bedrock in a Multi-Tenant EnvironmentMore Info

The expansion of generative artificial intelligence (AI) features within software solutions has accelerated, particularly with the introduction of market-leading foundational models (FMs) accessible via an API through Amazon Bedrock. This fully managed service provides a selection of high-performance foundation models from esteemed AI organizations, including AI21 Labs, Anthropic, Cohere, Meta, Stability AI, and Amazon, all through a singular API. It offers comprehensive capabilities to construct generative AI applications while ensuring security, privacy, and responsible AI practices.

Agents for Amazon Bedrock empower software developers to execute tasks based on user inputs and organizational data. A prevalent challenge within multi-tenant platforms, particularly Software as a Service (SaaS) products, is ensuring tenant isolation. This isolation guarantees that each tenant can only access their specific resources, even when utilizing shared infrastructure.

You can achieve tenant isolation in applications through various multi-tenant architecture patterns. In certain scenarios, complete stacks of resources may be allocated to individual tenants (silo model) with broad policies to avert cross-tenant access. In others, pooled resources (such as a single database table containing entries from various tenants) necessitate meticulously defined policies to manage access. Often, Amazon Web Services (AWS) customers implement a combination of both models to balance their respective advantages and disadvantages.

In a pooled model, isolating tenants involves utilizing tenant context information across different application components. This tenant context can be injected by an authoritative source, like the identity provider (IdP), during user authentication. It is crucial to maintain the integrity of the tenant context throughout the system to prevent unauthorized users from impersonating a tenant, which could lead to unauthorized access to sensitive data or modifications.

FMs operate on unstructured data and respond probabilistically, rendering them unsuitable for securely handling tenant context. For instance, FMs are vulnerable to prompt injection, which can be exploited by malicious individuals to alter tenant context. Instead, tenant context should be securely transmitted between deterministic application components that can leverage FM capabilities, thereby providing the FM with information that is already limited to the specific tenant.

In this blog post, we will guide you through implementing tenant isolation using Amazon Bedrock agents within a multi-tenant environment. We will illustrate this with a sample multi-tenant e-commerce application that enables various tenants to create online stores. This application employs Amazon Bedrock agents to develop an AI assistant or chatbot capable of delivering tenant-specific information, such as return policies and individual user data like order counts and status updates. This architecture exemplifies the use of pooled Amazon Bedrock agents while enforcing tenant isolation at both the tenant level for return policy data and the user level for user-specific data, thereby ensuring a secure and tailored experience for each tenant and their users.

Architecture Overview

Let’s delve into the various components utilized in this solution.

A tenant user authenticates through an identity provider like Amazon Cognito, receiving a JSON Web Token (JWT) for API requests. The JWT contains claims such as the user ID (or subject, sub), which identifies the tenant user, and the tenantId, indicating the tenant to which the user belongs.

The tenant user submits a question through the client application. This application forwards the question to a GraphQL API endpoint provided by AWS AppSync as a GraphQL mutation. For additional information on this pattern, refer to another blog post here. The client app authenticates to AWS AppSync using the JWT from Amazon Cognito, authorizing the user through the Cognito User Pools integration.

The GraphQL mutation invokes the EventBridge resolver, triggering an AWS Lambda function via an EventBridge rule.

The Lambda function calls the Amazon Bedrock InvokeAgent API, applying a tenant isolation policy to define permissions while generating tenant-specific scoped credentials. For more insights into this process, you can check out this resource. The tenant ID, user ID, and tenant-specific scoped credentials are sent to the API using the sessionAttributes parameter from the agent’s sessionState.

The Amazon Bedrock agent assesses the required actions to fulfill the user request by employing the reasoning capabilities of the associated large language model (LLM). A variety of LLMs are available, and for this solution, we utilized Anthropic Claude 3 Sonnet. The agent transmits the sessionAttributes object to an action group designed to assist with the request, securely relaying tenant and user IDs for subsequent processing steps.

This Lambda function utilizes the provided tenant-specific scoped credentials and tenant ID to retrieve information from Amazon DynamoDB. Tenant configuration data is housed in a single, shared table, while user data is allocated in separate tables for each tenant. Once the relevant data is retrieved, it is returned to the agent, which interacts with the LLM a second time to craft a natural-language response to the user based on the data provided.

The agent’s response is transmitted back as another GraphQL mutation through AWS AppSync.

The client listens for the response using a GraphQL subscription, rendering the information to the user upon receipt from the server.

Bear in mind that each component of this sample architecture can be adapted to fit your existing framework and expertise within your organization. For instance, you might opt for a WebSocket implementation via Amazon API Gateway instead of GraphQL or implement a synchronous request-response model. Regardless of the technology stack you choose, ensure that tenant and user contexts are securely communicated throughout the various layers. Avoid depending on probabilistic components, such as LLMs, to accurately transmit security information.

How Tenant and User Data Is Isolated

This section details how user and tenant data are isolated during the processing of a request throughout the system. Each step will be elaborated upon in more detail following the accompanying diagram. For every prompt in the user interface, the frontend sends the prompt as a mutation request to the AWS AppSync API, listening for the response via a subscription, as outlined in step 8 of the diagram. The subscription is necessary to obtain the agent’s answer, given that the agent is invoked asynchronously. Both the request and response are authenticated through Amazon Cognito, with the request’s context, including user and tenant ID, accessible to subsequent components.

For each prompt created in the sample user interface, a unique ID (answerId) is generated. This answerId is essential for correlating the input prompt with the agent’s response. It employs the Cognito user ID (found in the sub field of the JWT and accessible as userId in the AWS Amplify SDK) as a prefix to enable precise permissions. This is elaborated on in step 3. The answerId is generated in the page.tsx file:

const answerId = user?.userId + "." + uuidv4(); 

In summary, the implementation of tenant isolation within a multi-tenant architecture using Amazon Bedrock agents is crucial for maintaining data integrity and security. By following best practices and leveraging robust architectural patterns, organizations can ensure a secure, personalized experience for their users.

Location: Amazon IXD – VGT2, 6401 E Howdy Wells Ave, Las Vegas, NV 89115
For further information, you can access this excellent resource on Reddit.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *