【SaaS架构】多租户SaaS授权和API访问控制
视频号
微信公众号
知识星球
- 27 次浏览
【SaaS架构】多租户SaaS授权和API访问控制 - 介绍
视频号
微信公众号
知识星球
多租户软件即服务(SaaS)应用程序的授权和API访问控制是一个复杂的主题。当您考虑到必须确保安全的微服务API的激增以及不同租户、用户特征和应用程序状态产生的大量访问条件时,这种复杂性就显而易见了。为了有效地解决这些问题,解决方案必须在微服务、前端后端(BFF)层和多租户SaaS应用程序的其他组件提供的许多API中实施访问控制。这种普遍的方法必须与灵活的实施范式相结合,该范式可以根据许多因素和属性做出复杂的访问决策。
传统上,API访问控制和授权由应用程序代码中的自定义逻辑处理。这种方法容易出错,而且不安全,因为可以访问此代码的开发人员可能会意外或故意更改授权逻辑,从而导致未经授权的访问。此外,API访问控制通常是不必要的,因为没有那么多API需要保护。应用程序设计中偏向微服务和面向服务的架构的范式转变增加了必须使用某种形式的授权和访问控制的API的数量。此外,在多租户SaaS应用程序中维护基于租户的访问的需要可能会变得非常复杂,通常使用孤立的或效率极低的模型来保持这种租赁。
本指南中概述的最佳实践提供了几个好处:
- 授权逻辑可以集中化,并用高级声明性语言编写,而不是特定于任何编程语言。
- 授权逻辑是从应用程序代码中抽象出来的,可以等幂地应用于应用程序中的所有API。
- 该抽象防止了对授权逻辑的意外更改,并使其与SaaS应用程序的集成一致且简单。
- 抽象防止了为每个API端点编写自定义授权逻辑的需要。
- 本指南中概述的方法支持根据组织的要求使用多种访问控制范式。
- 这种授权和访问控制方法提供了一种在SaaS应用程序的API层维护租户数据隔离的简单而直接的方法。
目标业务成果
本规范性指南描述了可用于多租户SaaS应用程序的授权和API访问控制的幂等设计模式。本指南适用于开发具有复杂授权要求或严格API访问控制需求的应用程序的任何团队。该体系结构详细介绍了使用开放策略代理(OPA)创建策略决策点(PDP)或策略引擎,以及在API中集成策略执行点(PEP)。本指南还讨论了基于属性的访问控制(ABAC)模型或基于角色的访问控制模型,或这两种模型的组合来做出访问决策。
我们建议您使用本指南中提供的设计模式和概念来通知和标准化多租户SaaS应用程序中的授权和API访问控制的实现。本指南有助于实现以下业务成果:
- 多租户SaaS应用程序的标准化API授权架构–此架构通过PDP、PEP、策略引擎和OPA实现。这些概念和技术有助于维护多租户SaaS应用程序中的租户隔离,并为应用程序提供API授权的整体方法。
- 授权逻辑与应用程序的解耦–当授权逻辑嵌入应用程序代码中或通过临时强制机制实现时,可能会发生意外或恶意更改,从而导致意外的跨租户数据访问或其他安全漏洞。为了帮助减少这些可能性,您可以使用OPA等策略引擎将授权决策与应用程序代码分开,并在应用程序中实施一致的策略。策略可以在高级声明性语言中集中维护,这使得维护授权逻辑比在应用程序代码的多个部分中嵌入策略要简单得多。这种方法还可确保一致地应用更新。
- 访问控制模型的灵活方法–基于角色的访问控制(RBAC)、基于属性的访问控制或这两种模型的组合都是访问控制的有效方法。这些模型试图通过使用不同的方法来满足业务的授权要求。本指南对这些模型进行比较和对比,以帮助您选择适合您的组织的模型。该指南还详细讨论了这些模型如何应用于策略引擎,尤其是OPA。本指南中讨论的体系结构使其中一个或两个模型都能成功采用。
- 严格的API访问控制–本指南提供了一种以最小的努力在应用程序中一致和普遍地保护API的方法。这对于通常使用大量API来促进应用程序内部通信的面向服务或微服务应用程序架构尤其重要。严格的API访问控制有助于提高应用程序的安全性,使其不易受到攻击或利用。
- 52 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--FAQ
视频号
微信公众号
知识星球
本节提供了关于在多租户SaaS应用程序中实现API访问控制和授权的常见问题的答案。
授权和身份验证之间的区别是什么?
身份验证是验证用户身份的过程。授权授予用户访问特定资源的权限。
为什么我需要考虑授权我的SaaS应用程序?
SaaS应用程序有多个租户。租户可以是客户组织或使用该SaaS应用程序的任何外部实体。根据应用程序的设计方式,这意味着租户可能正在访问共享的API、数据库或其他资源。维护租户隔离非常重要,即按租户分离权限和数据,以防止用户从一个租户访问另一个租户的私人信息。SaaS应用程序中的授权通常旨在确保在整个应用程序中保持租户隔离,并且租户只能访问自己的资源。
为什么我需要访问控制模型?
访问控制模型用于创建确定如何授予对应用程序中资源的访问的一致方法。这可以通过将角色分配给与业务逻辑密切相关的用户来实现,也可以基于其他上下文属性,例如一天中的时间或用户是否满足预定义的条件。访问控制模型构成了应用程序在进行授权决策以确定用户权限时使用的基本逻辑。
我的应用程序是否需要API访问控制?
对API应始终验证调用者是否具有适当的访问权限。普适的API访问控制还确保仅基于租户授予访问权限,以便保持适当的隔离。
为什么建议使用策略引擎或PDP进行授权?
策略决策点(PDP)允许将应用程序代码中的授权逻辑卸载到单独的系统。这可以简化应用程序代码。它还提供了一个易于使用的幂等接口,用于为API、微服务、前端后端(BFF)层或任何其他应用程序组件进行授权决策。
什么是PEP?
策略执行点(PEP)负责接收发送给PDP进行评估的授权请求。PEP可以位于应用程序中必须保护数据和资源或应用授权逻辑的任何位置。与PDP相比,PEP相对简单。PEP仅负责请求和评估授权决策,不要求将任何授权逻辑纳入其中。
OPA有开源替代品吗?
有一些开源系统类似于开放策略代理(OPA),例如通用表达式语言(CEL)。本指南侧重于OPA,因为它被广泛采用、记录在案,并可适应许多不同类型的应用程序和授权要求。
我是否需要编写授权服务来使用OPA,或者我可以直接与OPA交互?
您可以直接与OPA交互。本指南中的授权服务是指将授权决策请求转换为OPA查询的服务,反之亦然。如果您的应用程序可以直接查询和接受OPA响应,则无需引入这种额外的复杂性。
如何监控OPA代理的正常运行时间和审计目的?
OPA确实提供了日志记录和基本的正常运行时间监控,尽管默认配置可能不足以用于企业部署。有关更多信息,请参阅DevOps、监控和日志部分。
我可以使用哪些操作系统和AWS服务来运行OPA?
您可以在macOS、Windows和Linux上运行OPA。OPA代理可以在Amazon Elastic Compute Cloud(Amazon EC2)代理以及容器化服务(如Amazon ElasticContainer Service(Amazon ECS)和Amazon Elastics Kubernetes Service(Amazon EKS))上配置。
我可以在AWS Lambda上运行OPA吗?
您可以将OPA作为Go库在Lambda上运行。AWS博客文章“使用开放策略代理创建自定义Lambda授权者”讨论了如何为API网关Lambda授权器实现这一点。
我应该如何决定分布式PDP和集中式PDP方法?
这取决于您的应用程序。它很可能是基于分布式和集中式PDP模型之间的延迟差异来确定的。我们建议您构建概念验证并测试应用程序的性能,以验证您的解决方案。
除了API之外,我可以将OPA用于用例吗?
对OPA文档提供了Kubernetes、Envoy、Docker、Kafka、SSH和sudo以及Terraform的示例。此外,OPA能够使用Rego部分规则响应查询返回任意JSON。根据查询的不同,OPA可以用来回答JSON响应中的许多问题。
- 106 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--下一步
视频号
微信公众号
知识星球
多租户SaaS应用程序的授权和API访问控制的复杂性可以通过采用标准化、语言无关的方法来进行授权决策来克服。这些方法结合了策略决策点(PDP)和策略实施点(PDU),以灵活和普遍的方式实施访问。可以将多种访问控制方法(如基于角色的访问控制(RBAC)、基于属性的访问控制,ABAC)或两者的组合)结合到一个内聚的访问控制策略中。从应用程序中删除授权逻辑消除了在应用程序代码中包含临时解决方案以解决访问控制的开销。本指南中讨论的实现和最佳实践旨在为多租户SaaS应用程序中的授权和API访问控制的实现提供信息并使其标准化。您可以将本指南作为为应用程序收集信息和设计强大的访问控制和授权系统的第一步。
下一步:
- 检查您的授权和租户隔离需求,并为应用程序选择访问控制模型。
- 实施开放策略代理(OPA)并构建测试概念证明。(或者,编写自己的自定义策略引擎。)
- 确定应用程序中应实施PEP的API和位置。
- 24 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--多租户SaaS架构的设计模型
视频号
微信公众号
知识星球
有许多方法可以实现API访问控制和授权。本指南重点介绍三种对多租户SaaS架构有效的设计模型。这些设计为策略决策点(PDP)和策略执行点(PEP)的实现提供了一个高级参考,从而为应用程序形成了一个连贯且普遍的授权模型。
设计模型:
- 具有API上PEP的集中式PDP
- API上带有PEP的分布式PDP
- 作为库的分布式PDP
具有API上PEP的集中式PDP
在API模型上具有策略执行点(PEP)的集中式策略决策点(PDP)遵循行业最佳实践,为API访问控制和授权创建一个有效且易于维护的系统。该方法支持几个关键原则:
- 授权和API访问控制在应用程序的多个点应用。
- 授权逻辑独立于应用程序。
- 访问控制决策是集中的。
该模型使用集中式PDP来做出授权决策。PEP在所有API中实现,以向PDP发出授权请求。下图显示了如何在假设的多租户SaaS应用程序中实现此模型。
一个示例多租户SaaS应用程序,该应用程序使用带有PEP的集中式PDP
应用程序流程:
具有JWT令牌的认证用户向AmazonCloudFront生成HTTP请求。 |
|
CloudFront将请求转发到配置为CloudFront源的Amazon API网关。 |
|
调用API网关Lambda授权器来验证JWT令牌。 |
|
微服务响应请求。 |
授权和API访问控制流程:
PEP调用授权服务并传递请求数据,包括任何JWT令牌。 |
|
授权服务(PDP)接收请求数据并查询作为sidecar运行的OPA代理REST API,请求数据作为查询的输入。 |
|
OPA根据查询指定的相关策略评估输入。必要时导入数据以做出授权决定。 |
|
OPA向授权服务返回决定。 |
|
授权决定返回给PEP并进行评估。 |
在此架构中,PEP在CloudFront和API网关以及每个微服务的服务端点请求授权决策。授权决策由具有OPA侧车的授权服务(PDP)做出。您可以将此授权服务作为容器或传统服务器实例来操作。OPA sidecar在本地公开其RESTful API,因此该API只能由授权服务访问。授权服务公开了一个单独的API,可供PEP使用。授权服务充当PEP和OPA之间的中介,允许在PEP与OPA之间插入任何必要的转换逻辑,例如,当PEP的授权请求不符合OPA期望的查询输入时。
您还可以将此架构与自定义策略引擎一起使用。然而,从OPA获得的任何优势都必须用定制策略引擎提供的逻辑来代替。
在API上使用PEP的集中式PDP为为API创建一个健壮的授权系统提供了一个简单的选择。它易于实现,还提供了一个易于使用的幂等接口,用于为API、微服务、前端后端(BFF)层或其他应用程序组件做出授权决策。然而,这种方法可能会在应用程序中造成太多延迟,因为授权决策需要调用单独的API。如果网络延迟是一个问题,您可以考虑使用分布式PDP。
API上带有PEP的分布式PDP
基于API模型的分布式策略决策点(PDP)和策略执行点(PEP)遵循行业最佳实践,以创建有效的API访问控制和授权系统。与API模型上带有PEP的集中式PDP一样,该方法支持以下关键原则:
- 授权和API访问控制在应用程序的多个点应用。
- 授权逻辑独立于应用程序。
- 访问控制决策是集中的。
您可能会想知道,当分发PDP时,为什么访问控制决策是集中的。尽管PDP可能存在于应用程序中的多个位置,但它必须使用相同的授权逻辑来做出访问控制决策。给定相同的输入,所有PDP提供相同的访问控制决策。PEP在所有API中实现,以向PDP发出授权请求。下图显示了如何在假设的多租户SaaS应用程序中实现此分布式模型。
一个示例多租户SaaS应用程序,该应用程序使用带有PEP的分布式PDP
Application flow:
具有JWT令牌的认证用户向AmazonCloudFront生成HTTP请求。 |
|
CloudFront将请求转发到配置为CloudFront源的Amazon API网关。 |
|
调用API网关Lambda授权器来验证JWT令牌。 |
|
微服务响应请求。 |
Authorization and API access control flow:
PEP调用授权服务并传递请求数据,包括任何JWT令牌。 |
|
授权服务(PDP)接收请求数据并查询作为sidecar运行的OPA代理REST API,请求数据作为查询的输入。 |
|
OPA根据查询指定的相关策略评估输入。必要时导入数据以做出授权决定。 |
|
OPA向授权服务返回决定。 |
|
授权决定返回给PEP并进行评估。 |
在此架构中,PEP在CloudFront和API网关以及每个微服务的服务端点请求授权决策。微服务的授权决策是由授权服务(PDP)做出的,它作为应用程序组件的侧车运行。该模型适用于在容器或Amazon Elastic Compute Cloud(Amazon EC2)实例上运行的微服务(或服务)。API网关和CloudFront等服务的授权决策仍需要联系外部授权服务。无论如何,授权服务公开了PEP可用的API。授权服务充当PEP与OPA之间的中介,允许在PEP和OPA之间插入任何必要的转换逻辑,例如,当PEP的授权请求不符合OPA期望的查询输入时。
您还可以将此架构与自定义策略引擎一起使用。然而,从OPA获得的任何优势都必须用定制策略引擎提供的逻辑来代替。
在API上具有PEP的分布式PDP提供了为API创建健壮授权系统的选项。它易于实现,并提供了一个易于使用的幂等接口,用于为API、微服务、前端后端(BFF)层或其他应用程序组件做出授权决策。这种方法还具有减少集中式PDP模型中可能遇到的延迟的优点。
作为库的分布式PDP
您还可以向PDP请求授权决策,该PDP可以作为库或包在应用程序中使用。OPA可以用作Go第三方库。对于其他编程语言,采用此模型通常意味着您必须创建自定义策略引擎。
- 252 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--实施PDP
视频号
微信公众号
知识星球
策略决策点(PDP)可以被表征为策略或规则引擎。此组件负责应用策略或规则,并返回是否允许特定访问的决定。PDP可以使用基于角色的访问控制(RBAC)和基于属性的访问控制模型(ABAC);然而,PDP是ABAC的要求。PDP允许将应用程序代码中的授权逻辑卸载到单独的系统。这可以简化应用程序代码。它还提供了一个易于使用的幂等接口,用于为API、微服务、前端后端(BFF)层或任何其他应用程序组件进行授权决策。
以下部分讨论了实现PDP的两种方法:开放策略代理(OPA)和自定义解决方案。然而,这并不是一个详尽的列表。
PDP实施方法:
- 使用OPA
- 使用自定义策略引擎
使用OPA
实现PDP的首选方法是使用开放策略代理(OPA)。OPA是一个开源的通用策略引擎。OPA有很多用例,但与PDP实现相关的用例是它将授权逻辑与应用程序分离的能力。这被称为政策脱钩。
由于几个原因,OPA在实现PDP时很有用。它使用名为Rego的高级声明性语言来起草策略和规则。这些策略和规则与应用程序分开存在,可以在没有任何特定于应用程序的逻辑的情况下呈现授权决策。OPA还公开了一个RESTful API,使检索授权决策简单明了。为了做出授权决策,应用程序使用JSON输入查询OPA,OPA根据指定的策略评估输入,以返回JSON形式的访问决策。OPA还能够导入可能与授权决策相关的外部数据。
OPA功能
OPA与定制策略引擎相比有以下几个优势:
- OPA及其与Rego的策略评估提供了一个灵活的预先构建的策略引擎,只需要插入策略和做出授权决策所需的任何数据。必须在自定义策略引擎解决方案中重新创建此策略评估逻辑。
- OPA通过使用声明性语言编写策略来简化授权逻辑。您可以独立于任何应用程序代码修改和管理这些策略和规则,而无需应用程序开发技能。
- OPA公开了一个RESTful API,它简化了与策略执行点(PEP)的集成。
- OPA为验证和解码JSON Web令牌(JWT)提供内置支持。
- OPA是公认的授权标准,这意味着如果您需要帮助或研究来解决特定问题,那么文档和示例将非常丰富。
- 采用OPA等授权标准,无论团队应用程序使用何种编程语言,都可以在团队之间共享用Rego编写的策略。
OPA不会自动提供两件事:
- OPA没有用于更新和管理策略的强大控制平面。OPA通过公开一个管理API,为实现策略更新、监控和日志聚合提供了一些基本模式,但必须由OPA用户处理与此API的集成。作为最佳实践,您应该使用连续集成和连续部署(CI/CD)管道来管理、修改和跟踪OPA中的策略版本和管理策略。
- 默认情况下,OPA无法从外部源检索数据。授权决策的外部数据源可以是保存用户属性的数据库。在如何向OPA提供外部数据方面有一定的灵活性,当请求授权决策时,可以预先在本地缓存外部数据或从API动态检索外部数据,但OPA无法代表您获取这些信息。
在本节中:
- Rego概述
- 示例1:带OPA和Rego的基本ABAC
- 示例2:具有OPA和Rego的多租户访问控制和用户定义RBAC
- 示例3:使用OPA和Rego对RBAC和ABAC进行多租户访问控制
- 示例4:使用OPA和Rego进行UI过滤
Rego概述
Rego是一种通用策略语言,这意味着它适用于堆栈的任何层和任何域。Rego的主要目的是接受JSON/YAML输入和数据,这些输入和数据经过评估,以做出有关基础设施资源、身份和操作的策略性决策。Rego使您能够编写关于堆栈或域的任何层的策略,而无需更改或扩展语言。以下是Rego可以做出的一些决策示例:
- 是否允许或拒绝此API请求?
- 此应用程序的备份服务器的主机名是什么?
- 此拟议基础设施变更的风险评分是多少?
- 为了实现高可用性,应将此容器部署到哪些集群?
- 该微服务应使用哪些路由信息?
为了回答这些问题,Rego采用了关于如何做出这些决定的基本哲学。在雷戈起草政策时的两个关键原则是:
- 每个资源、标识或操作都可以表示为JSON或YAML数据。
- 策略是应用于数据的逻辑。
Rego通过定义如何评估JSON/YAML数据输入的逻辑,帮助软件系统做出授权决策。C、Java、Go和Python等编程语言是解决这个问题的常用方法,但Rego的设计重点是表示系统的数据和输入,以及使用这些信息进行策略决策的逻辑。
示例1:带OPA和Rego的基本ABAC
本节描述了一个场景,其中OPA用于决定哪些用户可以访问虚构的Payroll微服务中的信息。提供了Rego代码片段,以演示如何使用Rego来呈现访问控制决策。这些示例既不是详尽的,也不是对Rego和OPA功能的全面探索。为了更全面地了解Rego,我们建议您查阅OPA网站上的Rego文档。
基本OPA规则示例
在上图中,OPA为Payroll微服务实施的访问控制规则之一是:
员工可以读取自己的工资。
如果Bob试图访问Payroll微服务以查看自己的工资,那么Payroll微型服务可以将API调用重定向到OPA RESTful API以做出访问决定。Payroll服务使用以下JSON输入向OPA查询决策:
{
"user": "bob",
"method": "GET",
"path": ["getSalary", "bob"]
}
OPA根据查询选择一个或多个策略。在本例中,以下策略(用Rego编写)评估JSON输入。
default allow = false
allow = true {
input.method == "GET"
input.path = ["getSalary", user]
input.user == user
}
默认情况下,此策略拒绝访问。然后,它通过将查询中的输入绑定到全局变量输入来计算该输入。点运算符与此变量一起使用以访问变量的值。如果规则中的表达式也是true,则Rego规则allow返回true。Rego规则验证输入中的方法是否等于GET。然后,在将列表中的第二个元素分配给变量user之前,它验证列表路径中的第一个元素是getSalary。最后,它通过检查发出请求的用户input.user是否与用户变量匹配来检查访问的路径是否为/getSalary/bob。如果逻辑返回布尔值,则应用规则allow,如输出所示:
{ "allow": true }
使用外部数据的部分规则
要演示其他OPA功能,您可以向正在实施的访问规则添加要求。让我们假设您希望在前面的示例中强制执行此访问控制要求:
员工可以阅读任何向他们汇报的人的工资。
在此示例中,OPA可以访问外部数据,这些数据可以被导入以帮助做出访问决策:
"managers": {
"bob": ["dave", "john"],
"carol": ["alice"]
}
您可以通过在OPA中创建部分规则来生成任意的JSON响应,该规则返回一组值而不是固定的响应。这是部分规则的示例:
direct_report[user_ids] {
user_ids = data.managers[input.user][_]
}
该规则返回一组报告input.user值的所有用户,在本例中,该值为bob。规则中的[_]构造用于迭代集合的值。这是规则的输出:
{ "direct_report": [ "dave", "john" ] }
检索此信息可以帮助确定用户是否是经理的直接下属。对于某些应用程序,返回动态JSON比返回简单的布尔响应更好。
把这一切放在一起
最后一个访问要求比前两个更复杂,因为它结合了两个要求中指定的条件:
员工可以阅读自己的工资和任何向他们汇报的人的工资。
要满足此要求,您可以使用此Rego策略:
default allow = false
allow = true {
input.method == "GET"
input.path = ["getSalary", user]
input.user == user
}
allow = true {
input.method == "GET"
input.path = ["getSalary", user]
managers := data.managers[input.user][_]
contains(managers, user)
}
策略中的第一条规则允许任何试图查看自己工资信息的用户访问,如前所述。在Rego中有两个同名的规则allow作为逻辑或运算符。第二条规则检索与input.user关联的所有直接报告的列表(从上一个图表中的数据),并将此列表分配给manager变量。最后,该规则通过验证经理变量中是否包含用户的姓名来检查试图查看其工资的用户是否是input.user的直接报告。
本节中的示例是非常基本的,并没有对Rego和OPA的功能进行完整或彻底的探索。有关更多信息,请查看OPA文档,查看OPA GitHub README文件,并在Rego游乐场进行实验。
示例2:具有OPA和Rego的多租户访问控制和用户定义RBAC
本示例使用OPA和Rego演示如何在具有租户用户定义的自定义角色的多租户应用程序的API上实现访问控制。它还演示了如何根据租户限制访问。该模型显示了OPA如何根据高级角色提供的信息做出精细的权限决策。
具有自定义角色的多租户访问的OPA用例
租户的角色存储在外部数据(RBAC数据)中,用于为OPA做出访问决策:
{
"roles": {
"tenant_a": {
"all_access_role": ["viewData", "updateData"]
},
"tenant_b": {
"update_data_role": ["updateData"],
"view_data_role": ["viewData"]
}
}
}
当由租户用户定义这些角色时,这些角色应存储在外部数据源或身份提供程序(IdP)中,当将租户定义的角色映射到权限和租户自身时,该身份提供程序可以充当真实的来源。
本示例使用OPA中的两个策略来做出授权决策,并检查这些策略如何强制租户隔离。这些策略使用前面定义的RBAC数据。
default allowViewData = false
allowViewData = true {
input.method == "GET"
input.path = ["viewData", tenant_id]
input.tenant_id == tenant_id
role_permissions := data.roles[input.tenant_id][input.role][_]
contains(role_permissions, "viewData")
}
要显示此规则的功能,请考虑具有以下输入的OPA查询:
{
"tenant_id": "tenant_a",
"role": "all_access_role",
"path": ["viewData", "tenant_a"],
"method": "GET"
}
通过组合RBAC数据、OPA策略和OPA查询输入,该API调用的授权决策如下:
- 租户A的用户对/viewData/Tenant_A进行API调用。
- Data微服务接收调用并查询allowViewData规则,传递OPA查询输入示例中显示的输入。
- OPA使用OPA策略中的查询规则来评估提供的输入。OPA还使用RBAC数据中的数据来评估输入。OPA执行以下操作:
- 验证用于进行API调用的方法是否为GET。
- 验证请求的路径是否为viewData。
- 检查路径中的tenant_id是否等于与用户关联的input.tenant_id。这确保了租户隔离。另一个租户,即使具有相同的角色,也无法被授权进行此API调用。
- 从角色的外部数据中提取角色权限列表,并将其分配给变量role_permissions。通过使用与input.role中的用户关联的租户定义的角色来检索此列表。
- 检查role_permissions以查看它是否包含权限viewData。
- OPA向Data微服务返回以下决定:
{ "allowViewData": true }
该过程显示了RBAC和租户意识如何帮助OPA做出授权决策。为了进一步说明这一点,请考虑使用以下查询输入对/viewData/tenant_b的API调用:
{
"tenant_id": "tenant_b",
"role": "view_data_role",
"path": ["viewData", "tenant_b"],
"method": "GET"
}
该规则将返回与OPA查询输入相同的输出,尽管它是针对具有不同角色的不同租户的。这是因为此调用针对/tenant_b,并且RBAC数据中的view_data_role仍然具有与其关联的viewData权限。要对/updateData实施相同类型的访问控制,可以使用类似的OPA规则:
default allowUpdateData = false
allowUpdateData = true {
input.method == "POST"
input.path = ["updateData", tenant_id]
input.tenant_id == tenant_id
role_permissions := data.roles[input.tenant_id][input.role][_]
contains(role_permissions, "updateData")
}
此规则在功能上与allowViewData规则相同,但它验证不同的路径和输入方法。该规则仍然确保租户隔离,并检查租户定义的角色是否授予API调用方权限。要查看如何执行此操作,请检查/updateData/tenant_b的API调用的以下查询输入:
{
"tenant_id": "tenant_b",
"role": "view_data_role",
"path": ["updateData", "tenant_b"],
"method": "POST"
}
当使用allowUpdateData规则求值时,此查询输入将返回以下授权决策:
{ "allowUpdateData": false }
此呼叫将不被授权。尽管API调用方与正确的tenant_id关联,并使用经批准的方法调用API,但input.role是租户定义的view_data_role。view_data_role没有updateData权限;因此,对/updateData的调用是未授权的。对于具有update_data_role的tenant_b用户,此调用将成功。
示例3:使用OPA和Rego对RBAC和ABAC进行多租户访问控制
为了增强上一节中的RBAC示例,可以向用户添加属性。
具有用户属性的多租户访问的OPA用例
此示例包含与上一示例相同的角色,但添加了用户属性account_lockout_flag。这是一个特定于用户的属性,不与任何特定角色关联。您可以使用先前用于此示例的相同RBAC外部数据:
{
"roles": {
"tenant_a": {
"all_access_role": ["viewData", "updateData"]
},
"tenant_b": {
"update_data_role": ["updateData"],
"view_data_role": ["viewData"]
}
}
}
account_lockout_flag用户属性可以作为用户Bob的/viewData/tenant_a的OPA查询输入的一部分传递给数据服务:
{
"tenant_id": "tenant_a",
"role": "all_access_role",
"path": ["viewData", "tenant_a"],
"method": "GET",
"account_lockout_flag": "true"
}
为访问决策查询的规则与前面的示例类似,但包含一行用于检查account_lockout_flag属性:
default allowViewData = false
allowViewData = true {
input.method == "GET"
input.path = ["viewData", tenant_id]
input.tenant_id == tenant_id
role_permissions := data.roles[input.tenant_id][input.role][_]
contains(role_permissions, "viewData")
input.account_lockout_flag == "false"
}
此查询返回false的授权决定。这是因为account_lockout_flag属性对于Bob为true,并且Rego规则allowViewData拒绝访问,尽管Bob具有正确的角色和租户。
示例4:使用OPA和Rego进行UI过滤
OPA和Rego的灵活性支持过滤UI元素的能力。下面的示例演示了OPA部分规则如何做出授权决策,决定哪些元素应该显示在带有RBAC的UI中。此方法是使用OPA过滤UI元素的多种不同方法之一。
基于RBAC的OPA UI过滤
在本例中,单页web应用程序有四个按钮。假设您希望过滤Bob、Shirley和Alice的UI,以便他们只能看到与其角色对应的按钮。当UI收到来自用户的请求时,它查询OPA部分规则以确定哪些按钮应该显示在UI中。当Bob(使用角色查看器)向UI发出请求时,查询将以下内容作为输入传递给OPA:
{
"role": "viewer"
}
OPA使用为RBAC构建的外部数据来做出访问决策:
{
"roles": {
"viewer": ["viewUsersButton", "viewDataButton"],
"dataViewOnly": ["viewDataButton"],
"admin": ["viewUsersButton", "viewDataButton", "updateUsersButton", "updateDataButton"]
}
}
OPA部分规则使用外部数据和输入生成一组用户可以在UI上查看的按钮:
ui_buttons[buttons] {
buttons := data.roles[input.role][_]
}
在部分规则中,OPA使用作为查询一部分指定的input.role来确定应该显示哪些按钮。Bob具有角色查看器,外部数据指定查看器可以看到两个按钮:viewUsersButton和viewDataButton。因此,Bob(以及具有查看器角色的任何其他用户)的此规则输出如下:
{ "ui_buttons": [ "viewDataButton", "viewUsersButton" ] }
雪莉具有dataViewOnly角色,她的输出将包含一个按钮:viewDataButton。具有管理员角色的Alice的输出将包含所有按钮。当查询OPA的UI_buttons时,这些响应将返回到UI。UI可以使用此响应来相应地隐藏或显示按钮。
使用自定义策略引擎
实现PDP的另一种方法是创建自定义策略引擎。此策略引擎的目标是将授权逻辑与应用程序分离。自定义策略引擎负责做出授权决策,类似于OPA,以实现策略解耦。此解决方案与OPA的主要区别在于,编写和评估策略的逻辑是定制的。与引擎的任何交互都必须通过API或其他方法公开,以使授权决策能够到达应用程序。您可以用任何编程语言编写自定义策略引擎,也可以使用其他机制进行策略评估,例如公共表达式语言(CEL)。
- 52 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--实施PDP
视频号
微信公众号
知识星球
实施政PEP
策略执行点(PEP)负责接收发送到策略决策点(PDP)进行评估的授权请求。PEP可以位于应用程序中必须保护数据和资源或应用授权逻辑的任何位置。与PDP相比,PEP相对简单。PEP只负责请求和评估授权决策,不需要任何授权逻辑。与PDP不同,PEP不能集中在SaaS应用程序中。这是因为授权和访问控制需要在整个应用程序及其访问点中实现。PEP可以应用于API、微服务、前端后端(BFF)层或应用程序中需要或需要访问控制的任何点。在应用程序中普及PEP可以确保在多个点上经常和独立地验证授权。
要实现PEP,第一步是确定应用程序中应在何处执行访问控制。在决定PEP应集成到您的应用程序中的位置时,请考虑以下原则:
- 如果应用程序公开了API,那么应该对该API进行授权和访问控制。
- 这是因为在面向微服务或面向服务的架构中,API充当不同应用程序功能之间的分隔符。将访问控制作为应用程序功能之间的逻辑检查点是有意义的。我们强烈建议您将PEP作为访问SaaS应用程序中每个API的先决条件。还可以在应用程序的其他点集成授权。在单片应用程序中,可能需要将PEP集成到应用程序本身的逻辑中。对于PEP应包含在何处,没有一刀切的解决方案,但应考虑使用API原则作为起点。
请求授权决策
PEP必须向PDP请求授权决定。请求可以采取多种形式。请求授权决策的最简单和最易访问的方法是向PDP公开的RESTful API发送授权请求或查询(使用OPA术语)。这是将PEP与PDP集成的建议方法,因为这是一种常见的向应用程序中的多个服务公开功能的模式。在此模式中,PEP的唯一功能是转发授权请求或查询所需的信息。这可以像将API接收的请求作为输入转发到PDP一样简单。创建PEP还有其他方法。例如,您可以在本地将OPA PDP与以Go编程语言编写的应用程序集成为库,而不是使用API。
评估授权决策
PEP需要包含评估授权决策结果的逻辑。当PDP作为API公开时,授权决策可能采用JSON格式,并由API调用返回。PEP必须评估此JSON代码,以确定所采取的操作是否得到授权。例如,如果PDP被设计为提供布尔允许或拒绝授权决策,则PEP可以简单地检查该值,然后返回HTTP状态代码200以允许,返回HTTP状态码403以拒绝。这种将PEP作为访问API的先决条件的模式是在SaaS应用程序中实现访问控制的一种容易实现且高效的模式。在更复杂的场景中,PEP可能负责评估PDP返回的任意JSON代码。PEP必须包含解释PDP返回的授权决定所需的任何逻辑。由于PEP可能在应用程序中的许多不同位置实现,我们建议您将PEP代码打包为可重用的库或工件,使用您选择的编程语言。这样,您的PEP可以在应用程序的任何位置轻松集成,只需最少的返工。
- 11 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--实施注意事项
视频号
微信公众号
知识星球
DevOps、监控和日志记录
在这个建议的授权范式中,策略集中在授权服务中。这种集中是故意的,因为本指南中讨论的设计模型的目标之一是实现策略解耦,或从应用程序中的其他组件中删除授权逻辑。开放策略代理(OPA)提供了一种在需要更改授权逻辑时更新策略的机制。此功能由一个简单的REST API提供,您可以将其配置为从已建立的位置拉取新版本的策略(或捆绑包)或按需推送策略。我们建议您创建一个健壮的CI/CD管道,以增强OPA用于进行授权决策的版本控制、验证和更新策略的控制平面。此外,OPA提供了一种基本的发现服务,在该服务中,可以动态配置新的代理,并由分发发现捆绑包的控制平面集中管理。此功能可以减轻管理分布式策略决策点(PDP)的管理负担。
控制平面也为监控和审计提供了额外的好处。您可以通过控制平面监视OPA状态。也许更重要的是,包含OPA授权决策的日志可以导出到远程HTTP服务器以进行日志聚合。这些决策日志对于审计目的非常有用。如果您正在考虑采用访问控制决策与应用程序分离的授权模型,请确保您的授权服务具有有效的监控、日志记录和CI/CD管理功能,以启用新的PDP或更新策略。
检索PDP的外部数据
PDP可能需要额外的数据来做出超出作为输入提供的授权决策。例如,您可能将特定于用户或租户的属性存储在数据库中,PDP必须引用这些属性才能做出授权决策。对于OPA,如果授权决策所需的所有数据都可以作为输入或作为作为查询组件传递的JSON Web令牌(JWT)的一部分提供,则不需要额外配置。(将JWT和SaaS上下文数据作为查询输入的一部分传递给OPA相对简单。)OPA可以通过所谓的重载输入方法接受任意JSON输入。如果PDP需要的数据超出了可以作为输入或JWT令牌的范围,OPA提供了几种检索这些数据的选项。其中包括绑定、推送数据(复制)和动态数据检索。
捆绑
OPA绑定功能支持以下外部数据检索过程:
- 策略执行点(PEP)请求授权决策。
- OPA下载新的政策包,包括外部数据。
- 绑定服务从数据源复制数据。
当您使用捆绑功能时,OPA会定期从集中捆绑服务下载策略和数据捆绑包。(捆绑服务的实现和设置不是OPA提供的。)从捆绑服务中提取的所有策略和外部数据都存储在内存中。如果外部数据大小太大,无法存储在内存中,或者数据更改太频繁,则此选项将不起作用。
有关捆绑功能的更多信息,请参阅OPA文档。
复制(推送数据)
OPA复制方法支持以下外部数据检索过程:
- 策略执行点(PEP)请求授权决策。
- 数据复制器将数据推送到OPA。
- 数据复制器从数据源复制数据。
在捆绑方法的另一种选择中,数据被推送到OPA,而不是被OPA周期性地拉取。(OPA不提供复制器的实现和设置。)推送方法与捆绑方法具有相同的数据大小限制,因为OPA将所有数据存储在内存中。推送选项的主要优点是,您可以使用增量更新OPA中的数据,而不是每次替换所有外部数据。这使得推送选项更适合频繁变化的数据集。
有关复制选项的更多信息,请参阅OPA文档。
动态数据检索
如果要检索的外部数据太大,无法缓存在OPA的内存中,则可以在评估授权决策期间从外部源动态提取数据。使用此方法时,数据始终是最新的。这种方法有两个缺点:网络延迟和可访问性。目前,OPA只能通过HTTP请求在运行时检索数据。如果到外部数据源的调用不能以HTTP响应的形式返回数据,则需要自定义API或其他机制来将这些数据提供给OPA。由于OPA只能通过HTTP请求检索数据,检索数据的速度至关重要,因此我们建议您尽可能使用Amazon ElastiCache或Amazon DynamoDB等AWS服务保存外部数据。
有关拉动方法的更多信息,请参阅OPA文档。
使用授权服务实现
当您使用绑定、复制或动态拉取方法获取外部数据时,我们建议授权服务促进这种交互。这是因为授权服务可以检索外部数据并将其转换为JSON,以便OPA做出授权决策。下图显示了授权服务如何使用这三种外部数据检索方法。
Retrieving external data for OPA flow – bundle or dynamic data retrieval at decision time:
OPA调用授权服务本地API端点 此端点被配置为在授权决策期间充当捆绑包端点或动态数据检索的端点。 |
|
授权服务查询或调用外部数据源以检索数据。 (对于捆绑包端点,此数据还应包含OPA策略和规则。捆绑包更新将替换OPA缓存中的所有数据和策略。) |
|
授权服务对返回的数据执行任何必要的转换,以将其转换为预期的JSON输入。 |
|
数据返回OPA。它被缓存在内存中用于捆绑包配置,并立即用于动态授权决策。 |
Retrieving external data for OPA flow – replicator:
复制器(授权服务的一部分)调用外部数据源并检索OPA中要更新的任何数据。 这可以包括策略、规则和外部数据。此调用可以以设置的节奏进行,也可以响应外部源中的数据更新而进行。 |
|
授权服务对返回的数据执行任何必要的转换,以将其转换为预期的JSON输入。 |
|
授权服务调用OPA并将数据缓存在内存中。授权服务可以选择性地更新数据、策略和规则。 |
RBAC租户隔离和外部数据隐私建议
上一节提供了将外部数据导入OPA以帮助做出授权决策的几种方法。在可能的情况下,我们建议您使用重载输入方法将SaaS上下文数据传递给OPA,以做出授权决策。然而,在基于角色的访问控制(RBAC)或RBAC和基于属性访问控制(ABAC)混合模型中,这些数据通常不够,因为必须引用角色和权限才能做出授权决策。为了维护租户隔离和角色映射的隐私,这些数据不应驻留在OPA中。RBAC数据应驻留在外部数据源中,例如数据库。此外,OPA不应用于将预定义角色映射到特定权限,因为这使得租户难以定义自己的角色和权限。它还使您的授权逻辑僵化,需要不断更新。
维护RBAC数据隐私和租户隔离的一些安全方法是使用动态数据检索或复制器方法获取OPA的外部数据。这是因为前一图中所示的授权服务可用于仅提供租户特定或用户特定的外部数据,以进行授权决策。例如,当用户登录时,可以使用复制器向OPA缓存提供RBAC数据或权限矩阵,并根据输入数据中提供的用户引用数据。您可以对动态提取的数据使用类似的方法,以便仅检索相关数据以进行授权决策。此外,在动态数据检索方法中,这些数据不必缓存在OPA中。绑定方法在维护租户隔离方面不如动态检索方法有效,因为它更新OPA缓存中的所有内容,无法处理精确的更新。捆绑模型仍然是更新OPA策略和非RBAC数据的好方法。
- 36 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--最佳实践
视频号
微信公众号
知识星球
本节列出了本指南的一些重要内容。有关每一点的详细讨论,请单击相应章节的链接。
选择适用于应用程序的访问控制模型
本指南讨论了几种访问控制模型。根据您的应用程序和业务需求,您应该选择适合您的模型。考虑如何使用这些模型来满足您的访问控制需求,以及访问控制需求可能会如何演变,需要对所选方法进行更改。
实施PDP
策略决策点(PDP)可以被表征为策略或规则引擎。此组件负责应用策略或规则,并返回是否允许特定访问的决定。PDP允许将应用程序代码中的授权逻辑卸载到单独的系统。这可以简化应用程序代码。它还提供了一个易于使用的幂等接口,用于为API、微服务、前端后端(BFF)层或任何其他应用程序组件进行授权决策。PDP可用于在应用程序中一致地强制执行租赁要求。
为组织中的每个API实施PEP
策略实施点(PEP)的实现需要确定应用程序中的访问控制实施位置。作为第一步,找到应用程序中可以合并PEP的点。在决定在何处添加PEP时,请考虑以下原则:
如果应用程序公开了API,那么应该对该API进行授权和访问控制。
考虑使用OPA作为PDP的策略引擎
开放策略代理(OPA)比定制策略引擎具有优势。OPA及其与Rego的策略评估提供了一个灵活的预构建策略引擎,支持使用高级声明性语言编写策略。这使得实现策略引擎所需的工作量大大低于构建自己的解决方案。此外,OPA正在迅速成为一个受支持的授权标准。
为OPA实现DevOps、监控和日志记录的控制平面
因为OPA不提供通过源代码控制更新和跟踪授权逻辑更改的方法,所以我们建议您实现一个控制平面来执行这些功能。这将使更新更容易分发给OPA代理,特别是如果OPA在分布式系统中运行,这将减少使用OPA的管理负担。此外,控制平面可用于收集聚合日志并监视OPA代理的状态。
确定授权决策是否需要外部数据,并选择适合它的模型
如果PDP可以仅基于JSON Web令牌(JWT)中包含的数据做出授权决策,则通常不需要导入外部数据来帮助做出授权决策。如果OPA用作PDP,它也可以接受任意JSON数据作为重载输入,作为请求的一部分传递,即使该数据不作为JWT的一部分。使用JWT或重载输入方法通常比在另一个源中维护外部数据容易得多。如果需要更复杂的外部数据来进行授权决策,OPA提供了几种检索外部数据的模型。
- 34 次浏览
【SaaS架构】多租户SaaS授权和API访问控制--访问控制类型
视频号
微信公众号
知识星球
您可以使用两种广泛定义的模型来实现访问控制:基于角色的访问控制(RBAC)和基于属性的访问控制。每种模型都有优缺点,本节将对此进行简要讨论。您应该使用的模型取决于您的具体用例。本指南中讨论的体系结构支持这两种模型。
RBAC
基于角色的访问控制(RBAC)基于通常与业务逻辑一致的角色来确定对资源的访问。权限将根据需要与角色关联。例如,营销角色将授权用户在受限系统内执行营销活动。这是一个相对简单的访问控制模型,因为它很好地与易于识别的业务逻辑相一致。
RBAC模型在以下情况下不太有效:
- 您有独特的用户,其职责包括多个角色。
- 您有复杂的业务逻辑,难以定义角色。
- 要扩展到较大的规模,需要不断进行管理,并将权限映射到新角色和现有角色。
- 授权基于动态参数。
ABAC
基于属性的访问控制(ABAC)基于属性确定对资源的访问。属性可以与用户、资源、环境甚至应用程序状态相关联。策略或规则引用属性,并可以使用基本布尔逻辑来确定是否允许用户执行操作。以下是权限的基本示例:
在支付系统中,财务部门的所有用户都可以在工作时间内在API端点/付款处处理付款。
财务部门的成员资格是决定访问/付款的用户属性。还有一个与/支付API端点关联的资源属性,它只允许在工作时间内进行访问。在ABAC中,用户是否可以处理付款由策略决定,该策略将财务部门成员资格作为用户属性,将时间作为/付款的资源属性。
ABAC模型在允许动态、上下文和细粒度授权决策方面非常灵活。然而,ABAC模型最初很难实现。定义规则和策略以及枚举所有相关访问向量的属性需要大量的前期投资来实现。
RBAC-ABAC混合方法
结合RBAC和ABAC可以提供这两种模型的一些优点。RBAC与业务逻辑紧密结合,实现起来比ABAC简单。为了在做出授权决策时提供额外的粒度层,可以将ABAC与RBAC结合起来。这种混合方法通过将用户的角色(及其分配的权限)与其他属性相结合以做出访问决策来确定访问。使用这两种模型可以实现简单的权限管理和分配,同时还可以提高授权决策的灵活性和粒度。
访问控制模型比较
下表比较了前面讨论的三种访问控制模型。这一比较旨在提供信息和高水平。在特定情况下使用访问模型可能不一定与本表中的比较相关。
Factor | RBAC | ABAC | Hybrid |
---|---|---|---|
Flexibility | Medium | High | High |
Simplicity | High | Low | Medium |
Granularity | Low | High | Medium |
Dynamic decisions and rules | No | Yes | Yes |
Context-aware | No | Yes | Somewhat |
Implementation effort | Low | High | Medium |
- 15 次浏览