共计 3258 个字符,预计需要花费 9 分钟才能阅读完成。
随着微服务的发展,经常遇到实施身份验证和授权(A&A)的问题。我们需要一个强大且集中管理的身份验证和授权策略。但是,应用程序的分布式性质使其难以实现。在本文中,我将探讨 Open Policy Agent 如何帮助简化授权问题。
让我们快速查看“身份验证和授权”的定义。认证 是指识别用户(“who”)。而 授权 是指确定经过身份验证的用户具有的访问级别(“what”)。
我这篇文章的重点是授权部分。为了简单起见,我创建了一个带有一组微服务的示例应用程序。有一个基本的用户界面,我们可以在其中执行各种操作并查看结果。该应用程序的唯一目的是显示 Open Policy Agent 如何处理各种授权方案。在后续文章中,我们将扩展该应用程序的范围,以涵盖日益复杂的用例和策略管理。
示例应用
首先,关于应用程序的一些上下文。我以销售团队通常使用的 CPQ 应用程序为客户配置报价为例。
有以下角色:
- 销售–具有“销售”角色的用户可以为其客户创建新报价并更新报价。但是,具有“销售”角色的用户不能删除商品。
- 销售支持–支持人员,他们可以查看所有报价,但不能编辑任何报价。、
- 销售管理员–行政人员可以查看所有报价,但不能编辑 / 创建任何报价。但是,如果需要确保清理,他们可以删除要约。
由于我们专注于授权部分,因此我假设用户已经过身份验证,并且具有有效的 JSON Web 令牌(JWT)。每个 API 请求都在请求标头中包含此 JWT。
在此处从 github 下载示例应用程序。按照自述文件中的安装说明进行操作,您应该可以使用 URL http://<MINIKUBE URL>/
访问 UI。
授权实战
基于我们在上面看到的角色,期望销售团队能够
- 创建新报价
- 列出报价
- 更新现有报价
而销售支持团队只能列出报价,而不能编辑 / 创建报价。Sales Admin 团队只能列出报价并将其删除。
UI 显示了多个按钮,每个按钮代表用户的操作。选择您要使用的角色,然后尝试创建,编辑或删除商品。UI 将提供有关操作是否成功的反馈。
那么,这里发生了什么?
让我们快速了解一下当前的设置。
该应用程序具有两个微服务优惠和客户。NGINX 反向代理将这些 API 公开给外界。NGINX 截获每个 API 请求并请求授权服务以验证是否允许用户执行请求的操作。我们使用 NGINX 的 auth_request
指令来拦截传入的 API 调用。每个 API 调用都有一个 Authorization
标头,其中包含 JWT。包括角色在内的整个用户信息都包含在 JWT 中。
授权服务有两个容器:
- 授权–一种定制服务(Authorization),用于接收请求并为 Open Policy Agent 创建格式化的输入请求。
- 开放策略代理(OPA)–作为辅助工具运行,并公开 http 端点以与授权容器进行通信。
基本上,NGINX 将 /authorize
请求发送到 Authorization 容器以授权 API 调用。然后,授权服务咨询开放策略代理是否授权请求(是 / 否)。然后,它向 NGINX 返回成功(200 OK)或错误(403 Forbidden)响应。因此,NGINX 允许 API 调用或向客户端返回 403 Forbidden 响应。
Open Policy Agent 是什么?
Open Policy Agent(OPA,发音为“oh-pa”)是一种开放源代码的通用策略引擎,它统一了整个堆栈中的策略执行。OPA 提供了一种高级的声明性语言,可让您将策略指定为代码和简单的 API,以减轻软件决策的负担。您可以使用 OPA 在微服务,Kubernetes,CI / CD 管道,API 网关等中实施策略。
基本上,OPA 将决策与执法脱钩。它接受结构化数据作为输入(JSON),并且可以返回决策(对 / 错)或任意结构化数据作为输出。
OPA 使用 rego
作为策略语言。您可以在 https://www.openpolicyagent.org/docs/latest/
上了解有关 rego 和开放策略代理的更多信息。
授权服务详解
让我们详细查看授权服务,以了解其工作原理。
我们在服务器模式下运行 Open Policy Agent,并利用其 REST API 更新策略并获取策略决策。
- Open Policy Agent 公开 REST API 来创建或更新策略。
PUT /v1/policies/<id>
Content-Type: text/plain
对于我们的示例,使用带有以下请求的终结点(在 GitHub README 中也提到了)来更新 OPA 中的策略。
curl -X PUT --data-binary @policies/httpapi.authz.rego http://<MINIKUBE URL>/authorize/v1/policies/httpapi/authz
- 要根据此政策做出决定,还有另一个 API
POST /v1/data/<path>
Content-Type: application/json
这里的 <path>
是由软件 package
标识的策略的路径,例如package httpapi.authz
。对于我们的示例,要删除商品 ID“1000”,授权服务将使用以下请求正文调用端点http://localhost:8181/data/httpapi/authz
:
{
"input" : {
"method": "DELETE",
"api": "/offer/1000",
"jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1NzQ2NjM3MDAsImV4cCI6NDA5OTE4NTMwMCwiYXVkIjoib3BhLWV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjoiU2FsZXMgQWRtaW4ifQ._UtjZtowF3NNN3IF1t0LBHuzQhdfIfsO8jC-46GvbRM"
}
}
- 授权应用程序将接收来自 NGINX 的请求,并如上所述生成对 OPA 的输入请求。为了这个示例,我已经在前端代码中对 JWT 进行了硬编码。每个 API 请求都在
Authorization
标头中包含 JWT。授权应用程序将提取 JWT 并将其添加到 OPA 的输入请求中。
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJMb2NhbEpXVElzc3VlciIsImlhdCI6MTU3MzcyNzM5MSwiZXhwIjo0MDk4MjQ1Mzc4LCJhdWQiOiJvcGEtZXhhbXBsZS5jb20iLCJzdWIiOiJzYWxlc0BleGFtcGxlLmNvbSIsIkdpdmVuTmFtdyI6IkpvaG5ueSIsIlN1cm5hbWUiOiJTYWxlcyIsIkVtYWlsIjoianNhbGVzQGV4YW1wbGUuY29tIiwiUm9sZSI6IlNhbGVzIn0.UbHWQpCMwupzsFp8f0CQ4o_bJSVaBugKijhcURZ_Mko
- 请注意,授权服务仅从传入请求中检索 JWT,而不会对其进行解码。OPA 通过内置函数 io.jwt.decode 支持 JWT 的解析。
- 您可以在这里在 rego 操场上尝试我们用于本示例的 rego 策略。尝试不同的输入请求,您将看到 OPA 为每个输入请求生成的输出。
结论
因此,简而言之,Open Policy Agent 提供了一种将授权决策与微服务中的业务逻辑分离的方法。系统管理员可以设置 Open Policy Agent,并将生成授权策略(重发策略)的责任委托给各个微服务所有者。微服务所有者和系统管理员都不会处理其边界之外的区域。
PS: 本文属于翻译,原文