使用RAG实现数据访问授权 | AWS安全博客
组织越来越多地使用大型语言模型(LLMs)通过生成式AI驱动的聊天机器人、虚拟助手和智能搜索功能来提供新型客户互动。为了增强这些互动,组织正在使用检索增强生成(RAG)来整合专有数据、行业特定知识和内部文档,以提供更准确、更具上下文相关性的响应。
RAG使用概述
RAG架构与搜索引擎有相似之处,但在数据访问方法上存在关键差异。搜索引擎提供信息源链接,要求用户基于其权限直接访问原始数据源。而RAG实现直接从LLM返回向量数据库结果,绕过了原始数据源的权限检查。
虽然元数据过滤可以帮助控制访问,但它面临两个关键挑战:首先,向量数据库仅定期同步,意味着源数据中的权限更改不会立即反映;其次,复杂的身份权限(主体可能属于数百个组)使得准确过滤结果变得困难。
解决方案概述:S3访问授权与Bedrock知识库
本示例展示了使用Amazon S3 Access Grants与Amazon Bedrock知识库的授权架构模式。组织内有多个团队(市场营销、销售、人力资源和IT),每个主体将有权访问其相应的项目或部门文件夹。
应用流程
- 用户使用其身份提供商(IdP)登录生成式AI应用
- 生成式AI应用与IAM Identity Center交换令牌并代表用户担任角色
- 生成式AI应用调用S3 Access Grants获取用户有权访问的授权列表
- 用户向生成式AI应用发送查询
- 生成式AI应用向知识库发送查询
- 生成式AI应用根据用户授权范围审查知识库返回的数据块
- 仅用户有权访问的范围才会传递给LLM生成响应
代码实现
步骤1:担任S3访问角色
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
def assume_role(client_id, grant_type, client_assertion, role_arn, role_session_name, provider_arn):
client_oidc = boto3.client('sso-oidc')
client_sts = boto3.client('sts')
token_response = client_oidc.create_token_with_iam(
clientId=client_id,
grantType=grant_type,
assertion=client_assertion
)
id_token = jwt.decode(token_response['idToken'], options={'verify_signature': False})
identity_context = id_token['sts:identity_context']
temp_credentials = client_sts.assume_role(
RoleArn=role_arn,
RoleSessionName=role_session_name,
ProvidedContexts=[{
'ProviderArn': provider_arn,
'ContextAssertion': identity_context
}]
)
creds = temp_credentials['Credentials']
return boto3.client(
's3control',
region_name='us-west-2',
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken']
)
|
步骤2:获取调用者授权范围
1
2
3
4
5
6
7
8
|
def get_caller_grant_scopes(client, account):
try:
response = client.list_caller_access_grants(AccountId=account)
scopes = [grant['GrantScope'].replace('*','') for grant in response['CallerAccessGrantsList']]
return scopes
except ClientError as e:
print(f'Error: {e}')
sys.exit(1)
|
步骤3:检查调用者授权范围
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def check_grant_scopes(chunks, scopes):
authorized = []
not_authorized = []
if not scopes:
return [], chunks
for chunk in chunks:
location = chunk['location']
authorized_scope = next((scope for scope in scopes if location.startswith(scope)), None)
if authorized_scope:
chunk['scope'] = authorized_scope
authorized.append(chunk)
else:
not_authorized.append(chunk)
return authorized, not_authorized
|
解决方案考虑因素
实施此RAG实现授权架构时,需要理解几个影响安全性、性能和可扩展性的关键考虑因素:
- 此架构可用于您选择的数据源,前提是知识库返回数据源的URI,并且有API可以调用以验证主体有权访问的内容
- S3 Access Grants提供主体访问数据源的授权,可以通过添加键/值标签或数据源对每个存储桶应用额外的访问控制策略
- 授权范围列表可能会变得过时,需要决定刷新授权范围列表的频率
- 根据主体有权访问的数据块和知识库返回的内容,在发送到LLM之前可能会丢弃某些数据块
结论
本文展示了为知识库返回结果提供强授权的架构模式,讲解了强授权的重要性以及如何使用Amazon S3 Access Grants实现授权,并通过代码示例演示了Amazon Bedrock知识库与S3 Access Grants的实际工作方式。