当前位置: 首页 > 科技观察

一种简化微服务认证的新方法:OpenPolicyAgent(OPA)_0

时间:2023-03-14 16:42:16 科技观察

【.com快译】从概念上讲,认证是指识别用户是谁,而授权是指识别经过身份验证的用户。您拥有什么级别的访问权限。不知道大家有没有注意到:由于分布式应用往往难以实现集中管理所需的强认证授权(AuthenticationandAuthorization,A&A)策略,所以在微服务的实际应用中,可能经常会遇到认证的实现问题和授权。接下来,我将与您讨论OpenPolicyAgent(OPA)如何帮助简化授权问题。为简单起见,我创建了一个包含多个微服务的示例应用程序。通过它的基本用户界面,我们可以在其中执行各种操作并查看产生的结果。此应用程序将向您展示OpenPolicyBroker如何处理各种授权场景。应用示例这里我们以销售团队常用的为客户报价的CPQ(Configuration,PricingandQuotation)应用(https://en.wikipedia.org/wiki/Configure,_price_and_quote)为例,定义和create角色如下:销售——作为销售人员,他们可以为客户创建和更新报价。但是不能删除引号。销售支持–作为支持人员,他们可以查看所有报价但不能编辑任何报价。销售管理员–作为管理员,他们可以查看所有报价但不能编辑或创建任何报价。但是,他们可以根据需要删除引号以进行清理。由于本文只关注授权,这里我们假设用户已经通过身份验证并持有有效的JSONWebToken(JWT)。并且每个API请求都会在请求标头中包含JWT。GitHub上示例应用程序的下载链接是--https://github.com/gchaware/opa-ms-sample/tree/master。请按照README中的说明一步步安装,通过URL访问其UI--http://:执行授权根据上述角色分配,我们授权销售团队创建新的报价单,查看报价单,更新现有的报价单。销售支持只能查看报价,不能编辑或创建报价。销售管理团队既可以查看报价也可以删除报价。上图的UI显示了多个按钮,每个按钮代表了用户的一个动作。根据用户选择使用的角色,UI会及时反馈创建、编辑或删除产品操作的成功或失败。上图显示了具有两个微服务的应用程序:报价和客户。通过对外发布API,NGINX反向代理可以拦截每一个API请求,并通过请求授权服务来验证是否允许用户执行该请求的相关操作。在这里,我们使用NGINX的auth_request指令来拦截传入的API调用。其中,每个API调用都有一个包含JWT标头的授权。所有用户的基本信息,包括他们的角色,都包含在JWT中。在这里,授权服务带有两个容器:授权——作为定制的授权服务,可用于接收请求并为下面的OpenPolicyAgent创建格式化的输入请求。开放策略代理(OPA,OpenPolicyAgent)——作为一个辅助工具,它通过将HTTP端点暴露给外界来与授权容器进行通信。首先,NGINX会向授权容器发送/authorize请求来授权API调用。接下来授权服务会询问开放策略代理是否有授权请求(true/false)。然后它向NGINX返回成功(200OK)或失败(403Forbidden)响应。因此,NGINX要么允许API调用,要么向客户端返回403Forbidden响应。什么是开放策略代理?OpenPolicyAgent(OPA)是一种开放源代码的通用策略引擎,可统一堆栈中的策略执行。OPA提供了一种高级的声明性语言,允许您将策略转化为代码和简单的API,从而减轻软件的决策负担。您可以使用OPA在微服务、Kubernetes、CI/CD管道和API网关中实施策略。由于OPA可以接受JSON等结构化数据作为输入,并可以返回真/假决策或任意结构化数据作为输出,因此它有效地将决策制定与执行分离。值得一提的是,OPA使用rego作为策略语言。您可以通过链接了解有关rego和openpolicyagent的更多信息-https://www.openpolicyagent.org/docs/latest/。描述授权服务让我们详细讨论授权服务是如何工作的。如上图所示,我们在服务器模式下运行OpenPolicyAgent,并利用其RESTAPI的更新策略来获取决策。以下命令演示了OpenPolicyAgent公开RESTAPI以创建或更新策略。PUT/v1/policies/Content-Type:text/plain在这个例子中,我们需要端点接收以下请求来更新OPA中的策略(详情请参阅GitHub中的README)。curl-XPUT--data-binary@policies/httpapi.authz.regohttp:///authorize/v1/policies/httpapi/authz同时,我们需要另一个API来根据策略进行决策:POST/v1/data/Content-Type:application/json这里是通过“packagehttpapi.authz”等策略来标识的。在此示例中,由于我们需要删除订单ID“1000”,授权服务将使用以下请求调用端点--http://localhost:8181/data/httpapi/authz。其具体Java代码如下:{"input":{"method":"DELETE","api":"/offer/1000","jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE1NzQ2NjM3MDAsImV4cCI6NDA5OTE4NTMwMCwiYXVkIjoib3BhLWV4YW1wbGUuY29tIiwic3ViIjoianjvy2tldeblegftcgxllmnvbsisikdpdmvutmftzsi6ikpvag5uesisiln1cm5hbwuioijsb2nrzxqilcjfbwfpbci6impyb2nrzxrazxhhbxbszs5jb20iLCJSb2xlIjoiU2FsZXMgQWRtaW4ifQ._UtjZtowF3NNN3IF1t0LBHuzQhdfIfsO8jC-46GvbRM"}}由代码可知,授权的应用程序将接收来自NGINX的请求,并根据上面的逻辑图生成对OPA的输入请求。对于这个例子,我们在前端代码中硬编码了JWT。并且每个API请求都将在Authorization标头中包含JWT。据此,授权应用获取到JWT后,会添加到OPA的输入请求中。其具体Java代码如下:Authorization:BearereyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJMb2NhbEpXVElzc3VlciIsImlhdCI6MTU3MzcyNzM5MSwiZXhwIjo0MDk4MjQ1Mzc4LCJhdWQiOiJvcGEtZXhhbXBsZS5jb20iLCJzdWIiOiJzYWxlc0BleGFtcGxlLmNvbSIsIkdpdmVuTmFtdyI6IkpvaG5ueSIsIlN1cm5hbWUiOiJTYWxlcyIsIkVtYWlsIjoianNhbGVzQGV4YW1wbGUuY29tIiwiUm9sZSI6IlNhbGVzIn0.UbHWQpCMwupzsFp8f0CQ4o_bJSVaBugKijhcURZ_Mko值得注意的是,授权服务只会从输入的请求中检索JWT,而不会对其进行解码。Therefore,OPAwillsupportJWTparsingthroughthebuilt-inio.jwt.decodefunction.Youcanlearnmoreabouttheprogramcodeandlogicoftheregostrategythroughthelink--https://play.openpolicyagent.org/p/4LOvGaEXEU.Bytryingdifferentinputrequests,youwillbeabletoseethedifferentoutputthatOPAgeneratesforeachrequest.SummaryInsummary,OpenPolicyProxyprovidesawaytodecoupleauthorizationdecisionsfrombusinesslogicinmicroservices.Inpracticalapplications,thesystemadministratorcandelegatetheresponsibilityofgeneratingtheauthorizationpolicy(regopolicy)totheownerofeachmicroservicebysettingtheopenpolicyagent.Neitherthemicroserviceownernorthesysadmindoesanyprocessingbeyondthebounds.OriginalTitle:OpenPolicyAgent:MicroservicesAuthorizationSimplified,Author:GauravChaware