跳到正文
AWS Machine Learning Blog· Suntosh Murthy·· 3 小时前AI 评分44

用 Denodo 与 Amazon Bedrock AgentCore 在 AWS 上为 Agentic AI 构建语义层

Build a semantic layer for agentic AI on AWS with Denodo and Amazon Bedrock AgentCore

AI 导读

本文演示如何在 AWS 上用 Denodo Platform 为 Agentic AI 构建语义层,通过 Denodo MCP Server 和 Model Context Protocol(MCP),让托管在 Amazon Bedrock AgentCore 上的智能体查询统一的 customer 360 视图。

正文 · AI 翻译

智能体 AI 应用需要对实时企业数据的受管访问。这些数据可能位于运营系统、分析型数据仓库、SaaS 应用、其他云或本地环境中。在 本系列上一篇文章 中,我们在 AWS 上基于 Amazon Aurora 和 Amazon Redshift,使用 Stardog 的知识图谱构建了一个语义层。Amazon Bedrock AgentCore 上的 Strands 智能体对该语义层进行了查询。Amazon Bedrock AgentCore 是一个用于大规模构建、连接和优化智能体的平台,支持任意框架或模型。本文沿用相同的客户 360 模式,但换用了不同的语义层实现,并扩展了数据源组合。

这里有两处变化。首先,语义层是 Denodo 平台:一个 AI 数据层,可提供主动上下文以及对分布式企业数据的实时零拷贝访问。智能体通过 VQL(Denodo 的 SQL 方言)与之通信。其次,数据源组合在 Amazon Aurora 和 Amazon Redshift 之外增加了一个本地 PostgreSQL 数据库,因此联邦查询问题不再局限于 Amazon Virtual Private Cloud (Amazon VPC) 之内。

该模式的其余部分保持不变。Amazon Bedrock 上的基础模型负责规划并编写查询。Denodo MCP Server 通过模型上下文协议 (MCP) 向智能体暴露受管视图。Amazon Bedrock AgentCore 承载智能体、终结入站身份验证,并管理智能体向 Denodo 出示的出站凭证。模型所推理的全部内容都位于语义层内部而非提示词中:包括联接、指标定义,以及适用于调用者的行级和列级过滤器。

读完本文后,你将了解:

  • 如何在 Denodo 中将 Amazon Aurora、Amazon Redshift 和本地 PostgreSQL 数据库联邦化,整合为智能体可查询的单一客户 360 视图。
  • 如何通过 Denodo MCP Server 将该语义视图暴露给 AgentCore 承载的智能体,以及如何将 MCP Server 注册为 AgentCore Gateway 目标。
  • 最终用户的身份如何从企业身份提供商出发,经由 AgentCore Identity 的代表 (On-Behalf-Of) 令牌交换流程传递到 Denodo。
  • 全局安全策略 如何在查询时应用行级和列级过滤器。
  • Denodo 在 AWS 上的两种部署选项:Agora(完全托管的云服务)以及在 Amazon Elastic Compute Cloud (Amazon EC2) 或 Amazon Elastic Kubernetes Service (Amazon EKS) 上的自行托管安装。

我们假设你已熟悉上一篇文章中的语义层架构:它是什么、用途是什么,以及为什么由模型规划查询而不直接掌控联接。如果其中有任何内容对你是新的,上一篇文章已做过介绍。

示例:数据源在 AWS 之外的客户 360

我们继续沿用上一篇文章中相同的客户 360 模式。上一篇文章中使用的 Stardog C360 Knowledge Kit 为一家电商零售商建模,包含两个核心用例:理解客户流失,以及识别可自动注册加入奖励计划的客户。本文中模式不变,变化的是其中一张表的位置:rewards_account 位于一个本地 PostgreSQL 集群上,而非与其余客户档案数据一起放在 Amazon Aurora 中。

这种放置方式并非特例。企业数据源可能位于 AWS 之外:本地部署、SaaS 工具(如 CRM)中,或另一个云中。语义层必须能够触及适用的任何一种。我们在本演练中使用本地部署的 PostgreSQL 来代表来自第三方应用的数据。扩展到其他数据源一节介绍了当数据源是 SaaS 工具、CRM 或大型机时会有哪些变化,还介绍了 Denodo 默认支持的其他数百种数据源。

Amazon Aurora(PostgreSQL 兼容):客户画像

表 关键列
customer cid (PK), first_name, last_name, email, ssn, phone, location
address id (PK), city, state, zip, street_name
credit_card id (PK), cid, card_num, card_type

Amazon Redshift:订单历史

表 关键列
order id (PK), cid, pid, order_date, quantity, price, card
product id (PK), name, brand, price, dept

本地部署 PostgreSQL:会员奖励计划

表 关键列
rewards_account id (PK), cid, account_id, create_date

共享标识符是 cid,一个普通整数,在 Aurora 的 customer 表中作为主键出现。它在 Amazon Redshift 的 order 表和本地部署的 rewards_account 中作为非外键列出现。在 Aurora 内部,customer.location 列是指向 address.id 的整数外键,这正是客户画像与地址记录关联的方式。没有任何跨两个引擎的外键,也没有用于构建外键的 ETL 任务。将客户与其购买记录和会员注册信息关联起来的查询必须在查询时对 cid 进行协调。

这套架构能够回答的一个典型问题是:“在我们的累计消费额前 20 名客户中,哪些还没有注册会员奖励计划?”这是 Stardood 套件中的自动注册场景,回答它需要来自 Aurora 的客户画像数据、来自 Amazon Redshift 的累计消费额,以及来自本地部署集群的注册状态。

Denodo 在执行时规划联邦查询,决定将哪些内容下推到 Aurora、哪些下推到 Amazon Redshift、从本地部署集群获取哪些内容,以及如何合并结果。数据不会在数据源之间移动,语义层只声明一次,供所有使用者复用。

本文中用到的 Denodo 术语

Denodo 将语义层实现为一个数据虚拟化平台。Denodo Virtual DataPort (VDP) 是核心的查询引擎:语义层对象存放在这里,VQL 在这里执行,访问策略也在这里评估。Design Studio 是面向 VDP 的基于浏览器的创作界面。本文中建模的每个对象都在其中定义。

有三类对象会被反复用到。

  • 基础视图(base view)是源系统中物理表、API 或文件与 VDP 中逻辑视图之间的映射。一个 Aurora 表映射到一个基础视图。
  • 派生视图(derived view)是对一个或多个基础视图或其他派生视图的 VQL 查询。本文中的 customer_360 视图就是一个派生视图。
  • 指标视图(metric view)将业务度量定义一次(例如 lifetime_customer_value),并允许其他派生视图引用它。指标视图将度量的定义与使用它的任何具体查询分离开来。

VQL 是 Denodo 的 SQL 方言。它是对齐 ANSI 标准的 SQL,外加一组 Denodo 特有的结构,特别是用于表示数据源的 DDL 结构,以及语义指标视图的语法。在智能体场景中,VQL 的特定语法由一项技能提供,当 LLM 使用 Denodo 工具时,该技能将帮助其正确使用 Denodo 的语法。

全局安全策略(GSP)是一种运行时访问控制规则,适用于带有特定标签的视图或列。GSP 是行过滤器和列掩码在查询时按调用者逐个评估并强制执行的方式。

更完整的参考请参阅 Denodo Platform 文档。

参考架构

运行时有两条流程。入站:客户端通过 Amazon Bedrock AgentCore Gateway 将用户的请求发送给智能体。Gateway 根据企业身份提供商(IdP)验证标识人类用户的 JSON Web Token(JWT),然后将请求路由到 Amazon Bedrock AgentCore runtime,后者托管 Strands 智能体进程。智能体调用 Amazon Bedrock 上的基础模型(本演练中为 Anthropic Claude Sonnet 4.6)来解释提示并规划查询。

出站:AgentCore Gateway 还充当智能体工具调用的出站代理。Denodo MCP Server 在 Gateway 上注册为一个 MCP 目标,因此智能体为访问企业数据而发起的工具调用会经由 Gateway 路由到 MCP Server。在请求到达 Denodo 之前,AgentCore Identity 会执行一次 On-Behalf-Of 令牌交换,将人类用户的入站令牌转换为一个作用域受限的访问令牌,该令牌代表同一用户并以 Denodo 为受众。Denodo MCP Server 接受交换后的令牌作为持有者凭据,并通过 JDBC 将 VQL 请求转发给 Denodo Virtual DataPort(VDP)。VDP 独立验证令牌,将调用者解析为 Denodo 角色,应用访问策略,并针对 Amazon Aurora、Amazon Redshift 和本地 PostgreSQL 集群规划联邦查询。

只有 VQL 请求向下传递到 VDP,结果集向上返回。没有任何源数据在引擎之间移动。Aurora、Amazon Redshift 和本地集群响应由 VDP 的联邦优化器改写后的原生 SQL。以下各节将详细介绍身份传播和策略执行。其他章节将介绍 MCP Server 注册和智能体部署步骤。

Figure 1. Inbound authentication path and outbound query path between the caller, Amazon Bedrock AgentCore components, the Denodo MCP Server, Denodo Virtual DataPort, and the three data sources.

图 1:调用者、Amazon Bedrock AgentCore 组件、Denodo MCP Server、Denodo Virtual DataPort 以及三个数据源之间的入站身份验证路径和出站查询路径

构建语义层

Denodo 中的语义模型并非单一产物。它由 VDP 中的基础视图、派生视图、指标视图和标签组成,共同向消费者呈现具有业务含义的数据。在这篇文章中构建语义模型意味着创建上述每一个部分。

我们分三步构建:为每个源表建立基础视图,一个在客户级别基于 cid 联接基础视图的派生视图(customer_360),以及一个定义可复用支出聚合的指标视图(lifetime_customer_value),需要时查询可以联接该视图。

实践中,这种建模是在 Denodo Design Studio 中通过可视化方式完成的。你把 Aurora、Amazon Redshift 和本地 PostgreSQL 源拖到画布上,在它们之间绘制连接,并通过表单(而不是手写 DDL)重命名或重新定义字段类型(例如,将 cust_ref 映射到 customer_id)。本文稍后介绍的安全策略的挂载也在同一个 UI 中完成。

指标视图与引用它们的派生视图放在一起,定义一次即可复用。如果两个团队基于相同的基础数据构建两个不同的客户级视图,两者都会呈现相同的指标定义。

基础视图

每个源表在 VDP 中都会成为一个基础视图。对于 Aurora 客户表,这意味着在 Design Studio 中使用特定连接器引入 Aurora,指向对应的 schema,然后让 VDP 对列进行自省。自省由 Design Studio 处理。得到的基础视图是物理列与 VDP 对应项之间的一对一映射,不会转换源数据。

创建过程中还需要两个额外的配置:

  • 用于治理的列标签。 customer 基础视图上的 ssn 被赋予标签 pii_sensitive。credit_card 基础视图上的 card_num 被赋予相同的标签。受治理访问部分定义的全局安全策略正是绑定到这些标签。
  • 主键和连接字段。cid 在 aurora_customer 上被标记为主键,并在 redshift_order 和 postgres_rewards_account 上被标记为连接字段。当源元数据可用时,Design Studio 会据此推断主键;否则,你需要在基础视图定义中设置一次。

对之前引入的源表重复上述操作。最终得到六个基础视图:Amazon Aurora 上的 aurora_customer、aurora_address 和 aurora_credit_card;Amazon Redshift 上的 redshift_order 和 redshift_product;以及本地 PostgreSQL 上的 postgres_rewards_account。

Design Studio 还支持通过 Denodo Assistant 进行自然语言创作。开发者可以用通俗的英语描述一个视图(例如,“基于 cid 将 Aurora 的客户资料与 Amazon Redshift 的订单总额连接起来”),然后获得一个候选 VQL 定义,可在保存前于同一画布中审查和完善。完善是迭代进行的:在定义最终确定之前,可以通过后续提示调整过滤器、连接或字段映射。本节描述的治理和类型规则同样适用于以这种方式创建的对象。

派生视图:客户 360

customer_360 是跨三个数据源的客户级视图,每个客户一行。订单明细和聚合单独存放在我们接下来定义的指标视图中。

CREATE OR REPLACE VIEW customer_360 AS
SELECT aurora_customer.cid,
aurora_customer.first_name,
aurora_customer.last_name,
aurora_customer.email,
aurora_customer.ssn,
aurora_address.city,
aurora_address.state,
aurora_credit_card.card_num,
aurora_credit_card.card_type,
postgres_rewards_account.account_id,
postgres_rewards_account.create_date AS rewards_since
FROM (
(
aurora_customer AS aurora_customer
LEFT OUTER JOIN aurora_address AS aurora_address
ON aurora_customer.location = aurora_address.id
)
LEFT OUTER JOIN aurora_credit_card AS aurora_credit_card
ON aurora_customer.cid = aurora_credit_card.cid
)
LEFT OUTER JOIN postgres_rewards_account AS postgres_rewards_account
ON aurora_customer.cid = postgres_rewards_account.cid;

这个定义有两个属性对架构的其余部分很重要。第一,连接发生在 Denodo Platform 中,而不是在管道中。没有维护物化 customer_360 表的 ETL 作业。VDP 在执行时解析连接:Aurora 返回资料和卡片信息,本地集群返回奖励注册记录,VDP 在 cid 上将它们合并。第二,派生视图携带所有列,包括 ssn 和 card_num。

出于治理和 AI 的考虑,我们还添加了元数据:用于个人身份信息(PII)字段的列标签,以及记录该视图及每个字段的描述。Denodo 的 Assistant 可以使用 LLM 来建议这些内容。后面的章节将说明这些元数据为什么重要。

Figure 2. The customer_360 derived view in Denodo Design Studio. Four base views appear on the canvas across the three sources, joined on cid and location. The ssn column on aurora_customer and the card_num column on aurora_credit_card carry the pii_sensitive tag referenced by the Global Security Policy in the Governed access section.

图 2:Denodo Design Studio 中的 customer_360 派生视图。三个数据源中的四个基础视图显示在画布上,按 cid 和 location 进行连接。aurora_customer 上的 ssn 列和 aurora_credit_card 上的 card_num 列带有 pii_sensitive 标签,被“受管访问”部分中的全局安全策略所引用

指标视图:客户生命周期价值

指标视图以特定的 SOURCES/DIMENSIONS/METRICS 结构定义可复用的业务度量。完整语法请参阅 VQL 指南中的 Defining a Metric View 参考。lifetime_customer_value 并不位于 customer_360 内部,而是存在于它旁边,作为一个独立的对象:

CREATE OR REPLACE METRIC VIEW lifetime_customer_value
(
first_name, last_name, state, rewards_since, lifetime_spend, order_count, product_id,product_name, product_brand,product_dept, units_sold
)
SOURCES (
customer_360 AS customer_360,
redshift_order AS redshift_order,
redshift_product AS redshift_product
)
ASSOCIATIONS (
customer_360 redshift_order assoc_customer360_orders,
redshift_product redshift_order assoc_product_orders
)
DIMENSIONS (
customer_360(
first_name AS customer_360.first_name,
last_name AS customer_360.last_name,
state AS customer_360.state,
rewards_since AS customer_360.rewards_since
),
product(
product_id AS redshift_product.id,
product_name AS redshift_product.name,
product_brand AS redshift_product.brand,
product_dept AS redshift_product.dept
)
)
METRICS (
lifetime_spend AS sum((redshift_order.price*redshift_order.quantity)),
order_count AS count(redshift_order.id),
units_sold AS sum(redshift_order.quantity)
);

其他视图和外部报表工具可以按照引用其他视图的相同方式来引用 lifetime_customer_value。当业务规则发生变化时(例如 lifetime_spend 应排除已取消的订单),只需在指标定义中更新一次。每个使用方在下一次查询时就会获取该变更,无需改动派生视图或下游应用。不同团队可以构建自己的派生视图,以表达其业务线看待世界的方式。基础数据保持共享,而语义解释保持独立,因此任何一个团队的修改都不会干扰另一个团队。

Figure 3. The lifetime_customer_value metric view in Design Studio. The SOURCES panel shows customer_360, redshift_order, redshift_product, the DIMENSIONS panel shows customer_360 and product views, and the METRICS panel shows lifetime_spend as SUM(redshift_order.price * redshift_order.quantity) , order_count as count(redshift_order.id) and units_sold as sum(redshift_order.quantity)

图 3:Design Studio 中的 lifetime_customer_value 指标视图,展示了定义 lifetime_spend、order_count 和 units_sold 的 SOURCES、DIMENSIONS 和 METRICS 面板

VDP 如何执行联邦查询

当智能体运行示例中的自动注册问题(“在我们按生命周期消费额排名前 20 的客户中,哪些还没有加入奖励计划?”)时,相应的 VQL 会使用指标视图来计算结果集并评估所需的指标:

SELECT first_name, last_name, state, EVALUATE_METRIC(lifetime_spend) AS lifetime_spend
FROM lifetime_customer_value
WHERE rewards_since IS NULL
GROUP BY first_name, last_name, state
ORDER BY EVALUATE_METRIC(lifetime_spend) DESC
LIMIT 20;

尽管此查询只引用了指标视图,VDP 的基于成本的优化器会在相应数据所在的三个引擎之间规划联邦执行。生成的执行计划大致如下:

  1. 下推到 Amazon Aurora:Denodo 将 customer、address 和 credit_card 的连接下推到 Aurora,返回包括 first_name、last_name、state 和 cid 在内的客户画像字段。
  2. 下推到本地 PostgreSQL:Denodo 将 rewards_account 的投影下推,返回 cid 和 create_date。
  3. 下推到 Amazon Redshift:Denodo 将消费额聚合下推到 Amazon Redshift,即按 cid 分组的 SUM(price * quantity)。
  4. 在 Denodo 内部合并:Denodo 将 Aurora 的画像结果与 PostgreSQL 的奖励结果按 cid 进行左连接,然后将该结果与 Amazon Redshift 聚合的消费额按 cid 进行右外连接。Denodo 过滤 rewards_since 为 IS NULL 的行,将指标计算为按 first_name、last_name 和 state 分组的外层分组聚合(sum(sum) AS lifetime_spend),按 lifetime_spend 降序排列,并最多返回 20 行。

该计划充分发挥了各数据源的优势:Amazon Redshift 负责聚合,Aurora 负责客户画像连接(因为三个画像表都存放在那里),本地集群返回一小部分奖励记录。VDP 处理最终的跨引擎连接和 top-N 过滤,处理三个紧凑的中间结果集,每个结果集每位客户只有一行而不是每笔订单一行。手写的流水线通常也只能接近这一形态,而且还必须永远保持同步。

VDP 还会在成本最低的地方处理类型对齐。如果同一标识符在一个源中以整数存储,而在另一个源中以字符串存储,VDP 会将类型转换下推到仍能基于该谓词进行过滤的源,而不是跨引擎拉取数据之后再做类型对齐。

Figure 4. The query flow from the C360 agent to Amazon Aurora, Amazon Redshift, and on-premises PostgreSQL and back. VDP rewrites one VQL request against customer_360 joined with lifetime_customer_value into source-native SQL per engine, collects the intermediate result sets, and joins them on cid inside VDP before returning the final rows to the agent.

图 4:从 C360 智能体到 Amazon Aurora、Amazon Redshift 以及本地 PostgreSQL 的查询流程。VDP 将针对 customer_360 与 lifetime_customer_value 联接的一个 VQL 请求重写为每个引擎各自的原生 SQL,收集中间结果集,并在 VDP 内部按 cid 完成联接,然后把最终行返回给智能体

除了查询下推和按需联合查询之外,VDP 还提供 缓存、感知聚合的加速以及点对点复制。在可能需要预先计算复杂转换的场景中,这些技术可以作为下推能力的补充,同时保留访问控制规则和数据血缘。

发布以供发现

一个仅以可查询端点形式存在的语义视图会留下可发现性缺口。下一个需要“客户生命周期价值”指标的团队无从得知 lifetime_customer_value 已经存在、它建立在什么之上,或者还有谁依赖它。将 customer_360 和 lifetime_customer_value 发布到 Denodo Data Marketplace,可以把它们变成可复用、受治理的企业数据产品,从而填补这一缺口:这两个对象连同其 VQL 定义、所有者、业务描述、自定义属性以及回溯到基础视图的血缘一起呈现。使用者可以按业务含义搜索,而不必了解底层模式。Denodo Data Marketplace 还提供其他面向非技术用户自助服务的功能,包括数据准备向导、管理员发布的认可与弃用说明,以及向数据产品所有者提问和发起请求的能力。

Denodo 通过 360 graph 对此进行了扩展,这是一种围绕业务概念的关系视图。该图会挂载已经在使用 customer_360 的报表、仪表板、笔记本或智能体工具,以及定义表中数据含义或使用条件等内容的术语表。使用者可以在编写查询之前先查看数据集的周边上下文。

Figure 5. customer_360 Graph View listing in the Denodo Data Marketplace. The detail panel shows a BI Tool in Tableau Consuming the view and the Glossary Definition linked to the view.

图 5:Denodo Data Marketplace 中的 customer_360 图视图列表。详情面板显示一个在 Tableau 中使用该视图的 BI 工具,以及链接到该视图的术语表定义

关于互操作性的一点说明

Denodo 的语义模型使用 VQL 定义,但 Denodo 可以通过多种开放协议原生暴露任何视图。同一个 customer_360 视图可以通过 JDBC、ODBC 或 ADBC 以 SQL 方式访问,通过 Denodo GraphQL Service 以 GraphQL 方式访问,通过 Denodo OData Service 以 OData 2.0 或 4.0 方式访问,或通过 Denodo MCP Server 以 MCP 工具方式访问。本次演练选择 MCP 是因为它与 AgentCore 相契合。同一个视图无需额外建模即可供 Power BI 仪表板、Tableau 工作簿或 Java 应用程序使用。

2026 年 3 月,Denodo 还加入了 Apache Ossie(孵化中),其前身为 Open Semantic Interchange(OSI),这是一个供应商中立的开源语义元数据规范。Apache Ossie 尚处于早期阶段,但其目标是让采用该规范的应用之间能够移植语义定义。此外,Denodo 已经通过 Denodo Connects 提供集成,可与 SageMaker Catalog、Collibra、Purview 等其他数据目录共享元数据。

治理访问:身份传播与运行时执行

覆盖广泛数据源是企业级语义层的核心特征之一,但同样的广泛覆盖在缺少运行时访问控制时会带来真实风险。如果按用户过滤的逻辑存在于智能体的代码中,离被绕过只差一次提示词注入。如果它存在于 LLM 中,那它其实哪儿都不存在。如果只在各个源系统中执行,策略可能不一致,且可能无法顾及跨源创建的业务含义。Aurora 不知道语义层中“消费最高者”是什么意思,位于堡垒主机之后的本地部署 PostgreSQL 集群也不知道。而且很多时候,尤其是在混合本地部署与云系统的场景中,为所有这些系统配置统一的身份提供商(IdP)甚至都不是一个选项。

该架构采取的方法是在语义层执行访问控制,使用发起请求的人类用户的身份,该身份从 IdP 端到端地经由 Amazon Bedrock AgentCore 传播到 Denodo Virtual DataPort。

身份传播链

图 6 放大了图 1 参考架构中的身份部分,将从应用出发到 Denodo VDP 的出站路径展开为一个八跳序列。下列编号步骤与图中带编号的箭头一一对应。

Figure 6. Identity propagation and query flow from the user’s login through Amazon Bedrock AgentCore to Denodo (MCP Server and VDP) and the underlying data sources. Black arrows show the outbound identity and query path. Green dashed arrows show the return path with the filtered result set.

图 6:从用户登录经 Amazon Bedrock AgentCore 到 Denodo(MCP Server 和 VDP)及底层数据源的身份传播与查询流程。黑色箭头显示出站的身份与查询路径。绿色虚线箭头显示返回经过滤结果集的回程

  1. 用户通过企业 IdP 对应用进行身份验证。IdP 返回一个 JWT,其中包含用户的身份和属性声明——角色、地区、部门,以及 IdP 配置发出的其他任何内容。
  2. 应用通过 AgentCore Gateway 调用智能体,并以用户的 JWT 作为持有者令牌。
  3. Gateway 将请求路由到承载 Strands 智能体进程的 AgentCore runtime。
  4. 当智能体发起出站工具调用时,AgentCore Identity 执行代表(On-Behalf-Of)令牌交换,并返回一个新的访问令牌,其 sub 声明为该人类用户,aud 声明为 Denodo。
  5. 智能体将新的访问令牌作为 Authorization: Bearer <access_token> 在 MCP 请求中提供给 Denodo MCP Server。
  6. Denodo VDP 根据配置的 JWKS URL 验证 JWT,检查签发者和受众,提取 scope 声明,并将调用者映射到 Denodo 角色。
  7. VDP 在查询时评估全局安全策略,并向智能体返回经过滤的结果集。
  8. VDP 查询数据源以满足请求,并在返回前合并结果。

步骤 2 的 Gateway JWT 验证是可选的,因为 VDP 会在步骤 6 重新验证令牌。开启 Gateway 验证后,格式错误的令牌会在请求路径中更早地失败。

步骤 4 的令牌交换基于凭据提供程序配置,使用 RFC 8693 令牌交换授权或 RFC 7523 JWT 持有者授权。凭据本身不会进入智能体代码。AgentCore Identity 在调用时注入凭据。

步骤 8 的调用者身份透传选项按数据源启用,并要求 Denodo 与数据源共享同一个 IdP。适用时,调用者的身份将端到端转发,从而在源端实现完整的审计。

在 Denodo 中应用访问策略

Customer 360 数据受到监管。例如,某些用户(HR、欺诈分析师)可能需要查看社会保险号(SSN)和完整信用卡号等 PII。但大多数用户(营销、分析)则不允许。

Denodo 的实现机制是带有基于属性和角色的访问控制的 全局安全策略(Global Security Policies)。全局安全策略是一条应用于带有特定标签的视图或列的规则,在查询时根据调用者的角色和会话属性进行评估。底层视图不会被重构。

为了说明这一点,我们在 Aurora 之上的基础视图上将两列(ssn 和 card_num)标记为 PII。我们创建一个全局安全策略 mask_pii_columns。

  • 受众:调用者的角色不是 hr_user。
  • 元素:应用于带有 pii_sensitive 标签的列。
  • 操作:用星号掩码(****)。

然后我们定义两个 Denodo 角色。

  • hr_user:对 customer_360 拥有 Execute 权限。可以看到每一列。
  • marketing_user:对 customer_360 拥有 Execute 权限。由于策略生效,将看到 ssn 和 card_num 显示为 ****。

当 marketing_user 运行 VQL 查询时:

SELECT cid, first_name, last_name, state, ssn
FROM customer_360
WHERE state = 'WI';

VDP 在规划查询之前会评估全局安全策略。它发现 ssn 带有 pii_sensitive 标签,而调用者的角色不是 hr_user,因此它会重写投影,为 ssn 返回 ***。

对于行级过滤(例如,一位美东分析师应该只能看到东海岸的客户),同样的机制也可以扩展。策略条件甚至可以依赖于从 JWT 令牌映射的会话属性,或从外部表动态获取。

关于负责任 AI 的说明

Denodo 的全局安全策略在语义层过滤 PII,因此模型永远不会看到不该看到的调用者的 ssn 或 card_num。即便如此,智能体的响应仍可能以自然语言回显客户标识符、位置或消费模式。请以对待底层受监管数据相同的处理和保留策略来对待智能体的输出:限定日志和对话记录的存储范围,应用 Amazon Bedrock Guardrails 进行内容和敏感主题控制,并限制谁可以读取响应。更广泛的指导请参见 Amazon Bedrock 中的负责任 AI。

跨层的审计与可观测性

请求路径的每一层都独立记录日志。AgentCore 运行时向 Amazon CloudWatch 发送调用记录。AgentCore Gateway 记录入站的 MCP 请求,包括调用者的 JWT sub 声明。Denodo MCP Server 将工具调用记录到自己的日志中。Denodo VDP 的审计日志会捕获完整的 VQL 请求、映射的 Denodo 角色、解析后的联邦执行计划以及策略评估结果。

这些日志还可以被 整合到 Amazon CloudWatch 中。当需要将每个数据源的审计关联到人类用户时(例如出于 HIPAA 或 SOX 合规要求),请在这些数据源的基础视图上配置直通会话凭证,以便在源系统支持的情况下,Denodo 将调用者的身份转发给源系统,而不是依赖服务账户。

通过 Denodo MCP Server 暴露该层

Denodo MCP Server 是一个附加组件,位于 MCP 客户端与 VDP 之间:下载发行包、解压、编辑 config/application.properties 并启动它。该服务器在 http://<mcp-host>:8080/<database>/mcp 监听可流式传输的 HTTP MCP 请求,并通过 JDBC 将其转发给 VDP。

本次演练中有三个配置值很重要。

  • mcp.security.oauth2.enabled=true:接受入站 MCP 请求中的 OAuth 2.0 bearer 令牌。配合 VDP 的 OAuth 身份验证器配置,令牌会转发给 VDP 进行验证和角色解析(另请参阅 受管控的访问 一节)。
  • vdp.datasource.jdbcUrl=jdbc:vdb://<vdp-host>:9999/:访问 VDP 所用的 JDBC URL。每个请求具体指向的数据库由 MCP 端点路径决定。
  • mcp.visibility.tags=mcp 控制从 MCP Server 中可见哪些视图。如果定义了该选项,则只有带有这些标签中至少一个标签的视图才会可见。

该服务器实现了 MCP OAuth 2.0 授权流程,包括 RFC 9728 受保护资源元数据(Protected Resource Metadata)和 RFC 7591 动态客户端注册(Dynamic Client Registration)。

关于 IdP 兼容性的说明

Denodo MCP Server 文档支持与 Okta、Ping Identity 和 Keycloak 的自动动态客户端注册流程。对于其他身份提供商,MCP Server 还接受手动客户端配置,即 OAuth 令牌在带外获取,并作为静态 Authorization 请求头随 MCP 请求转发,具体如 Denodo MCP Server 用户手册中所述。

在服务器前端部署应用负载均衡器

如果 Denodo MCP Server 运行在与 VDP 处于同一 VPC 中的 Amazon EC2 或 Amazon EKS 上,可以通过带有 HTTPS 监听器的应用程序负载均衡器以及来自 AWS Certificate Manager 的证书将其公开。这为 AgentCore Gateway 提供了一个稳定的 HTTPS 端点,并将 TLS 终止从 MCP Server 进程中卸载。目标组:HTTP,端口 8080。健康检查路径应同时接受 200 和 404 作为健康响应,因为根路径返回 404,而当服务器已启动并连接到 VDP 时,/health 返回 200。

注册为 AgentCore Gateway 目标

完整的分步操作流程(包括 AgentCore Gateway 创建、IAM 服务角色配置和 Gateway 目标验证)见 Denodo 的 通过 MCP Server 将 Amazon Bedrock AgentCore 与 Denodo 集成集成指南。

在 harness 中添加 Denodo VQL 技能

Denodo VQL 技能充当智能体框架(如 Strands 或 Bedrock AgentCore)内 LLM 的系统提示词扩展。注册到智能体 harness 中后,它会向模型讲解 VQL 语法规则,以及如何帮助避免 SQL 错误。

部署并运行智能体

Denodo AgentCore 文档参考中的 完整智能体代码位于 Denodo KB。该模式很简短:Amazon Bedrock 上的一个基础模型、一个指向 Denodo MCP Server 的 MCP 客户端,以及将它们连接在一起的 AgentCore 运行时入口点。

验证

为确认语义层、智能体和身份流程均按预期工作,我们通过智能体运行三类查询,外加一次治理重跑,以展示受治理的访问部分所述的“同一查询、两个用户”特性。我们可以使用 Denodo 的 Data Marketplace 助手(其幕后依赖等效的工具)对场景进行快速验证。

查询 1,仅 Aurora

“列出我们在威斯康星州的客户及其所在城市。”

智能体生成并运行:

/* The query needs to retrieve first_name, last_name, and city from the customer_360 view where state = 'WI', ordered by last_name. The output will be multiple rows with 3 columns. The table is at customer granularity (one row per customer). No obligatory columns are present, so a simple WHERE filter on state suffices. */
SELECT "first_name",
"last_name",
"city"
FROM "customer_360"."customer_360"
WHERE "state" = 'WI'
ORDER BY "last_name"

VDP 的优化器确定投影和过滤只需要 Aurora 端的数据,于是将单条查询下推到 Amazon Aurora。基于一次探测查询,智能体可以将威斯康星州过滤器转换为谓词 state = 'WI'。Amazon Redshift 和本地集群均未被触碰。

查询 2,仅 Redshift

“按销量计,我们的前 10 大产品是什么?”

智能体生成:

/* The user wants top 10 products by total units sold from a metric view. I need to use EVALUATE_METRIC for units_sold, GROUP BY product_name, ORDER BY the metric descending, LIMIT 10. The output will be multiple rows (up to 10) with two columns: product_name and total_units_sold. */
SELECT "product_name",
EVALUATE_METRIC("units_sold") AS "total_units_sold"
FROM "customer_360"."lifetime_customer_value"
GROUP BY "product_name"
ORDER BY "total_units_sold" DESC
LIMIT 10

Query plan view showing the Query 2 request pushed down in full to Amazon Redshift

图 7:由于产品和订单数据都位于 Amazon Redshift,VDP 将整个查询(连接、聚合、排序和限制)下推到 Amazon Redshift。Aurora 和本地集群均未被触碰

查询 3,三方联合查询

“按客户终身价值排名的前 20 位客户中,哪些尚未注册奖励计划?”

智能体生成:

/* This is a metric view, so I need to use EVALUATE_METRIC for lifetime_spend and order_count. The query needs to: 1. Aggregate by first_name, last_name, state, rewards_since to get total lifetime_spend and order_count 2. Rank top 20 by total lifetime_spend 3. Filter those top 20 where rewards_since IS NULL I'll use a CTE with ROW_NUMBER() to get top 20, then filter for NULL rewards_since in outer query. */
WITH "ranked_customers" AS (
SELECT "first_name",
"last_name",
"state",
"rewards_since",
EVALUATE_METRIC("lifetime_spend") AS "total_lifetime_spend",
EVALUATE_METRIC("order_count") AS "total_order_count"
FROM "customer_360"."lifetime_customer_value"
GROUP BY "first_name",
"last_name",
"state",
"rewards_since"
ORDER BY "total_lifetime_spend" DESC
LIMIT 20
)
SELECT "first_name",
"last_name",
"state",
"rewards_since",
"total_lifetime_spend",
"total_order_count"
FROM "ranked_customers"
WHERE "rewards_since" IS NULL
ORDER BY "total_lifetime_spend" DESC

Agent output listing the top 20 customers by lifetime value who are not enrolled in the rewards program

图 8:三路联邦查询的智能体结果,列出按终身价值排名的、尚未注册奖励计划的首选客户

三个引擎中的 VDP 计划,如构建语义层部分所述:来自 Aurora 的画像数据、来自 Amazon Redshift 的聚合消费额、来自本地集群的注册记录,以及在 VDP 内部完成的最终联接和前 N 名排序。在 POC 数据中,排名最高的是来自威斯康星州密尔沃基的 Marcus Chen,终身消费额为 47,832 美元,是一位高消费但未注册奖励计划的客户——这正是示例中示例问题所针对的自动注册目标。请注意,LLM 无需自己想出 lifetime_spend 的定义,因为该公式已作为指标视图中定义的语义模型的一部分。

治理重跑

我们以两个不同的调用者身份运行 Query 1,并在投影中添加了 ssn:

SELECT cid, first_name, last_name, state, ssn
FROM customer_360
WHERE state = 'WI';

作为 hr_user 时,结果包含 ssn 值。作为 marketing_user 时,结果返回相同的行,但 ssn 以星号作为掩码值显示。两次运行之间,查询文本、智能体代码、MCP Server、VDP 或 Aurora 均无任何更改。受治理访问部分中的全局安全策略 mask_pii_columns 会在查询时根据调用者的角色进行评估,VDP 会相应地重写投影。同样的行为也适用于 card_num。

Query result with the ssn column returned in full for one role and masked with asterisks for another

图 9:同一查询的治理重跑,ssn 对 hr_user 完整返回,对 marketing_user 则被掩码

扩展到其他数据源

将 AWS 之外的数据源添加到 customer_360,无论是用于 CRM 记录的 Salesforce、用于客服数据的 ServiceNow,还是用于 ERP 表的 SAP,其建模过程与 Aurora、Amazon Redshift 和本地集群相同。创建基础视图,通过 cid 将其联接到派生视图中,并标记敏感列。指标视图、全局安全策略和智能体的 VQL 均无需更改。变化的是 VDP 用于访问该数据源的封装器。例如:

  • Salesforce 通过 Denodo Salesforce 连接器连接,使用 OAuth 2.0 身份验证,并在 REST 或 Bulk API 上进行 VQL-to-SOQL 转换。
  • ServiceNow、Microsoft Dynamics 365 及其他 SaaS 工具使用 Denodo 的 SaaS 向导模板,这些模板已针对常见 API 预先配置好。
  • SAP ERP 通过使用 SAP Java Connector 的 BAPI 数据源连接。VDP 调用 SAP RFC 并将响应整形为行。

智能体并不知道底层使用的是哪一种。它以 VQL 查询 customer_360。Denodo 的封装器处理数据源原生的转换,并且无论数据行来自 JDBC 引擎、REST API 还是 RFC 调用,Denodo 的全局安全策略都会统一适用。

有一个部署时因数据源而异的决策:是将调用者的身份传递到数据源,还是以服务账户连接。当数据源支持时,直通传递可在数据源端实现端到端审计(例如对 SAP 使用 Kerberos、对 Salesforce 使用 OAuth)。服务账户连接更简单,数据源的审计会将查询显示为来自 Denodo。

部署:Denodo Agora 与自管理

Denodo on AWS 以两种形态之一运行。两者使用相同的 Virtual DataPort、相同的 VQL、相同的全局安全策略、相同的 MCP Server。区别仅在于运维方式。

Agora:全托管

Denodo Agora 是 Denodo 的完全托管云服务,可在 AWS Marketplace 上获取。Agora 运行在分离平面架构上。控制平面(Solution Manager、Design Studio、Scheduler 管理、监控/诊断)运行在 Denodo 的云账户中,而执行平面(VDP、Scheduler、Data Catalog)运行在客户的 AWS 账户内。接触数据的计算位于客户的 VPC 中,管理界面则由 Denodo 运营。

当您不想自行运营应用程序,且 Denodo 发布的更新节奏符合贵组织的需求时,可选择 Agora。

在 Amazon EC2 或 Amazon EKS 上自行管理

自行管理部署将 Denodo Platform 完全安装在客户的 AWS 账户中。Denodo 在 AWS Marketplace 上发布虚拟机镜像,并为 Amazon EKS 提供带有 Helm chart 的容器镜像。集群、升级和备份由您自行处理。

当合规性要求特定的部署形态、您希望控制版本节奏,或参考架构要求在特定 VPC 内部署 Denodo 集群时,可选择自行管理。

访问 AWS 之外的数据源

两种部署形态都将 VDP 放置在客户的 AWS 账户中。访问本地(on-premises)数据源在两种情况下是同一个问题:从承载 VDP 的 VPC 到本地集群的网络路径,通过组织已采用的任一混合连接方案进行配置。对于 Salesforce 或 ServiceNow 等 SaaS 数据源,无需额外设置,因为执行平面默认具有出站互联网访问能力,这足以支持 OAuth 2.0 身份验证和 REST API 调用。

结论与入门指南

对企业数据的可靠智能体访问需要三者协同工作:一个能够规划并生成查询的基础模型,一个在实时源系统之上呈现具有业务含义数据的语义层,以及一个托管智能体并管理身份流的运行时。Amazon Bedrock、Denodo Platform 和 Amazon Bedrock AgentCore 各自承担其中一个角色。

智能体与语义层通信,而非直接访问底层数据库。基础视图、派生视图、指标视图、标签和全局安全策略都位于 VDP 中。当源架构发生变更、新数据源上线或治理规则发生变化时,更新在语义层中完成,所有使用方在下一次查询时即可获得更新。语义层携带的额外元数据(文档、描述、指标公式和 360 图谱)为模型提供了更扎实的业务上下文用于推理,而不仅仅是原始架构。

入门指南

试用 Agora on AWS 并按照说明进行部署。Agora 是 Denodo 的完全托管云服务,用于在 AWS 上部署 AI 数据层,为分布式企业数据提供实时、受治理的访问。

大多数团队通过从狭窄范围起步再逐步扩展来达成目标。

  1. 选择一个智能体工作流,它跨越两三个不同的源系统,并且目前回答问题所需的时间过长。
  2. 写出三到五个具体问题,这是该工作流需要回答的。这些就是语义层在第一天就必须支持的查询。
  3. 连接数据源并创建基础视图,覆盖该工作流涉及的源表。在创建过程中为 PII 列打上标签。
  4. 构建问题所需的派生视图和指标视图。
  5. 实施全局安全策略,帮助保护 PII、受保护健康信息(PHI)、支付卡行业(PCI)或其他敏感信息。
  6. 将 Denodo MCP Server 注册为 AgentCore Gateway 目标,并按照前文一节中的模式将 Strands 智能体连接到它。使用 agentcore deploy 进行部署。

延伸阅读


关于作者

来源: AWS Machine Learning Blog · aws.amazon.com