为你的 SaaS 应用程序选择正确的 PostgreSQL 数据访问模式

在多租户环境中,确定最适合您的工作负载的数据库隔离策略的过程至关重要。您的隔离策略可确保一个租户无法访问另一个租户的数据,并定义租户的行为如何相互影响。隔离策略由业务、领域、安全性、成本、灵活性、合规性和技术要求的组合驱动。

亚马逊云科技 在 SaaS 租户隔离策略白皮书 使用 PostgreSQL 的 SaaS 应用程序决策矩阵 中提供了指导, 以帮助指导您为工作负载制定最佳隔离策略。选择分区模型(如何组织和存储数据)后,您需要一种安全的方式让租户能够在与其他租户隔离的情况下访问其数据。

在这篇文章中,我们将向您展示选择数据隔离策略后不同的数据访问模式会是什么样子。它重点介绍每种模式的注意事项,并使用适用于 PostgreSQL 的 亚马逊关系数据库服务 (Amazon RDS) 和亚马逊 A urora Post greSQL 兼容版提供多租户数据库访问的 代码示例。

你可以在这个 Github 存储库 中 找到与这篇文章相关的代码示例 。有关部署说明,请按照存储库中的说明进行操作。

多租户数据访问概述

有三种基本的 SaaS 分区模型 :筒仓、桥接和池。在筒仓模型中,每个租户都有自己独特的物理资源。桥接模型在逻辑上将物理资源上的租户分开,例如,共享物理数据库上的每个租户的数据库。在池模型中,所有租户在物理资源上共享一个逻辑结构,例如,所有租户共享一个架构。

数据访问模式因数据库的分区模型、可用的 亚马逊云科技 识别和访问管理 (AW S IAM ) 粒度以及访问它的计算资源而异。下图概述了本博客文章中将讨论的因素:

High level architecture diagram

适用于 PostgreSQL 的亚马逊 RDS 和 Aurora PostgreSQL 兼容版的身份验证选项

可以通过具有 IAM 认证的 亚马逊云科技 IAM 角色或使用 亚马逊云科技 S ecrets Manager 进行本地用户名/密码 认证 来限制对特定 Amazon RDS for PostgreSQL 或亚马逊 A urora 数据库 的访问。

亚马逊云科技 IAM 身份验证会生成短期证书。这改善了应用程序的安全状况,因为无需存储和更新长期证书。这降低了有效凭证被泄露的风险。亚马逊云科技 IAM 身份验证特别适合孤立或桥接架构,因为这些架构的并发用户数量通常比池化方法少。这很重要,因为在单个 亚马逊云科技 RDS 实例 上可以发出的每秒 亚马逊云科技 IAM 身份验证请求数量有 定义的上限

获得这些权限的能力因所使用的隔离策略而异。例如,如果每个租户使用 亚马逊弹性计算云 (Amazon EC2) 实例,则 可以附加一个仅允许该实例访问租户数据库的 IAM 实例配置文件 亚马逊云科技 Lambda 执行 角色 或亚马逊 ECS 任务角色也是如此。

当在多个租户之间共享单个 Amazon EC2 实例或 亚马逊云科技 Lambda 函数时,则需要其他机制。您可以 通过代币自动售货机服务实施 动态 IAM 会话策略 。或者,您可以使用基于属性的访问控制 ( ABAC ) 在运行时提供精细的租户访问权限。

亚马逊云科技 IAM 认证的替代方案是 亚马逊云科技 Secrets Manager。亚马逊云科技 Secrets Manager 允许您使用所选数据库引擎中包含的密码认证,并具有其他几个好处,包括:

  • 自动凭证管理
  • 机密以加密方式静态存储
  • 使用 亚马逊云科技 IAM 策略保护对机密的访问
  • 无需重新部署应用程序即可更新机密值
  • 按计划自动轮换密钥

有几种数据库的多租户部署模型可以从使用 亚马逊云科技 Secrets Manager 中受益。这包括具有许多并发连接的环境,例如桥接模式或池化模式,或者您无法更改应用程序以支持临时访问凭证的情况。

下一节将探讨每种方法之间的隔离模式和权衡取舍。

使用孤立计算进行思洛数据库隔离

此策略提供了最强的隔离,每个租户都有一个单独的数据库实例和单独的计算实例。通过使用每个租户的计算和数据库实例,可以获得额外的隔离控制。要设置网络隔离,可以在不同的网段中创建数据库和计算资源,例如为虚拟私有云 (VPC) 使用不同的子网。然后,可以通过路由表、安全组和网络访问控制列表来控制对这些网段中资源的访问。在最极端的情况下,可以通过 亚马逊云科技 账户隔离资源。如果有人担心 亚马逊云科技 应用程序编程接口 (API) 或服务配额级别有 噪音邻居 ,则这种隔离级别很有用。此外,专门的合规性或加密要求可能是实现这种隔离级别的驱动因素。

在此模型中,IAM 角色与特定租户的计算资源相关联。这可能是与亚马逊 EC2 实例关联的 亚马逊云科技 IAM 实例配置文件,也可以是与 亚马逊云科技 Lambda 函数关联的执行角色。然后,此 亚马逊云科技 IAM 策略的范围仅限于向包含该租户数据的数据库授予权限。

如果每个租户使用 IAM 角色,则您可以扩展到的最大租户数量取决于 IAM 服务配额 。建议改为实施范围缩小会话策略或基于属性的访问控制 (ABAC),如本文后面所述。如果您出于合规性或运营原因需要为每个租户使用单独的 IAM 角色,则可能需要在 亚马逊云科技 账户之间拆分租户,以扩展到超出单个账户的服务配额。

提高隔离程度的利弊是更高的成本和更高的操作复杂性。每个租户都需要自己的基础架构,这些基础架构应在高度可用的配置下运行。这会增加每个租户的成本,也意味着必须引入工具来管理这些独立租户堆栈的备份、维护和升级。还有一些服务配额限制了每个 亚马逊云科技 账户和区域可以创建的资源数量。

下图对概述的方法进行了可视化:

architecture pattern 1

由于筒仓示例与以下网桥隔离模式类似,因此请参阅下一节中的实现代码,该代码在同一个物理 RDS 实例上使用每个租户的数据库。

使用孤立计算桥接数据库隔离

桥梁隔离模型承认,筒仓和池模型之间存在浮动比例。这种模式的主要动机是通过在多个租户之间共享数据库实例来降低成本。

在 PostgreSQL 实例上实现网桥隔离模型有两种方法:数据库和架构。建议每个租户使用一个数据库,而不是每个租户使用一个架构。与数据库相比,架构是 PostgreSQL 中的逻辑结构,不会分离磁盘上的数据。架构还将文件存储在数据库中同一目录下的磁盘上——在极端情况下,具有许多租户的系统可能会达到特定的系统限制,例如索引节点耗尽。

这种方法在实例级别具有相同的隔离特性,在实例级别上,您可以使用本机访问控制来限制哪些用户可以访问哪些数据库对象,但会失去网络隔离控制。

你可以在这个 GitHub 存储库 中找到这个模式的 实现示例 。

architectire pattern 2

第二个示例使用 亚马逊云科技 Secrets Manager。这表示的隔离级别与前面的计算和数据库示例相同。这意味着每个租户使用一个密钥。每个租户计算资源都有一个与之关联的角色,该角色仅提供对该特定密钥的访问权限。

下图对概述的方法进行了可视化。你可以在 我们的 repo 中找到这种模式的实现示例。

architecture pattern 3

使用池化计算桥接数据库隔离

在这种模式下,多个租户共享一个计算资源,但仍然拥有单独的数据库。使用共享计算资源的动机可以是成本(尤其是对于 Amazon EC2 或容器而言),也可以是减少运营开销,因为只保留一种部署资源。但是,为每个租户强制执行安全护栏的复杂性增加了。

在此模型中,必须在运行时识别租户,而不是基于当前的计算实例。SaaS 架构中的常见模式是在每个请求上使用租户标识符。一种方法是使用 JSON Web 令牌 (JWT),该令牌提供以加密方式签名的识别信息。使用签名的 JWT 可以让您相信信息未被修改,并且可以正确识别租户。

要在使用 亚马逊云科技 Secrets Manager 时保持租户隔离,您必须确保租户只能访问自己的密钥。使用 亚马逊云科技 安全令牌服务 (STS),假定 亚马逊云科技 IAM 角色可以传入会话策略,将权限范围缩小到当前租户的密钥。此外,它使用基于属性的访问控制 ( ABAC) , 并通过会话标签动态设置租户。这意味着只需要创建一个 亚马逊云科技 IAM 角色,并且可以动态提供租户上下文。该应用程序假设租户感知型 亚马逊云科技 IAM 角色,并从令牌中传入租户声明,以缩小会话权限范围。这限制了应用程序只能访问租户特定的密钥和数据库。

下图对概述的方法进行了可视化。你可以在 我们的 repo 中找到这种模式的实现示例。

architecture pattern 4

这种访问模式也可以使用 亚马逊云科技 IAM 身份验证来实现,而不是 亚马逊云科技 Secrets Manager。在此模型中,IAM Auth 的一个重要考虑因素是,IAM 策略只能限制对数据库实例的访问,不能限制对数据库或其中的任何数据库对象的访问。 因此,为每个租户创建单独的数据库用户,并动态插值资源 ARN,如本示例所 示。

池数据库使用池化计算进行隔离

租户之间可以共享单个数据库或架构,而不是每个租户共享一个数据库。这进一步降低了操作复杂性,因为只需要为所有租户管理一个架构和机密。它还允许更有效地汇集与数据库的连接,并避免了动态检索机密权限的需要。但是,嘈杂的邻居可能会对性能产生更大的影响,并且与单一架构相关的错误会同时影响所有租户。

由于租户之间共享资源可以带来规模经济,因此与其他隔离和分区策略相比,池模型可以提高成本效益。该模型减少了服务配额的影响,并简化了维护和备份操作。有关多租户备份模式的注意事项,请参阅 多租户 SaaS 应用程序中的 托管数据库备份和恢复

从安全角度来看,可以通过 PostgreSQL 内置的 行级安全 ( RLS) 机制防止跨租户数据访问。 行级安全通过应用策略来限制可以访问的行,该策略基于已定义的条件。在多租户 SaaS 应用程序中,这种情况可能是表上的 tenant_id 属性等于表示当前租户的变量。

可以从身份验证上下文(例如从 JWT 令牌)中检索当前租户的信息,并使用以下 SQL 语句将其设置为会话变量:

SET app.current_tenant = "tenant1";

此 RLS 政策声明确保仅检索当前租户的记录。

CREATE POLICY tenant_policy ON users USING (tenant_id =(current_setting('app.current_tenant')

这里的隔离很弱,因为任何有权查询表的人都可以修改会话变量。为确保实施足够的租户隔离,请将 RLS 策略与安全编码标准相结合。这些编码标准应确保所有 SQL 语句都有额外的谓词(WH ER E 子句),这些谓词明确过滤查询以仅返回给定的租户数据。所有 SQL 代码更改都应经过同行评审流程,以确保会话变量未被操纵并且符合这些编码标准。有关 RLS 的更多信息,请阅读使用 PostgreSQL 行级安全性进行 多租户数据隔离

下图对概述的方法进行了可视化。你可以在 我们的 repo 中找到这种模式的实现示例。

architecture pattern 5

这种访问模式也可以使用 亚马逊云科技 IAM 身份验证来实现,而不是 亚马逊云科技 Secrets Manager。与前面的示例一样,这仅向数据库实例授予权限,因此您仍然需要依靠行级安全策略和应用程序逻辑来强制执行租户隔离。有关此的示例实现,请参阅 GitHub 存储库。

结合多种隔离策略

通常,SaaS 应用程序将由多个分区和隔离模型组成。这可能用于分层,其中 “高级” 级别的租户拥有自己的专用资源。也可能处于服务级别,其中某些服务可能需要单独的租户隔离方法。考虑以上方法的任意组合都可以在整个应用程序中使用。Amazon RDS 实例可以同时使用 IAM 和基于密码的身份验证。如果您的 SaaS 应用程序使用 微服务架构 ,则将一个数据库用于多个服务是一种反模式。如果您在同一个数据库实例上使用多种隔离策略和身份验证模式,则可能需要将服务分解为更专用的数据存储。

下表说明了实施本文中概述的隔离策略之一时的注意事项:

Isolation Strategy Partitioning Model

筒仓数据库和

思洛计算

Bridge Database & Silo Compute Bridge Database & Pool Compute Pool Database & Pool Compute
Authentication Method IAM / Secrets Manager IAM / Secrets Manager IAM / Secrets Manager IAM/ Secrets Manager
Security Layers Network, Compute IAM role, Session Policies, IAM ABAC, Password auth Compute IAM role, Session Policies, IAM ABAC, Password auth Application, IAM Session Policies, IAM ABAC, Password auth Application, Row-Level-Security (RLS), Password auth
Noisy Neighbor Impact None Moderate Moderate High
Operational Impact Minimal blast radius Increased blast radius Increased blast radius Large blast radius
Cost Efficiency Least efficient Moderately efficient Moderately efficient Most efficient
Tenant Onboarding Complex & time consuming Complex Less complex Simple & fast
Tenant Metering & Billing Simple Moderate effort Moderate effort Complex
Monitoring Least effort Moderate effort Moderate effort Significant effort
Implementation Options Account, VPC, Subnet or DB Instance per tenant Database or table per tenant Database or table per tenant Single shared table for all tenants

结论

在这篇文章中,我们探讨了适用于 PostgreSQL 的亚马逊 RDS 和兼容 Amazon Aurora PostgreSQL 的版本在多租户环境中的不同访问模式。它探讨了 亚马逊云科技 IAuth、计算隔离模型和数据库隔离模型等因素如何影响您的实施策略。这篇文章中的模式可帮助您对 SaaS 工作负载做出明智的决定。与每一个模式集合一样,它并不声称是完整的,而且随着未来的发展,新的访问模式也在不断演变。要查看本文中所有模式的完整代码实现示例,请访问 GitHub 存储库


作者简介

乔什·哈特 是亚马逊网络服务(亚马逊云科技)的高级解决方案架构师。他与英国的 ISV 客户合作,帮助他们在 亚马逊云科技 上构建 SaaS 应用程序并对其进行现代化改造。

马克西米利安·谢尔霍恩 在亚马逊网络服务(亚马逊云科技)担任解决方案架构师。此前,他作为软件工程师和架构师工作了10多年,负责分布式系统设计和单体到微服务的转型。