【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

通过 Istio 重新实现微服务 (五):认证和授权

  • 2019-05-30
  • 本文字数:5038 字

    阅读完需:约 17 分钟

通过 Istio 重新实现微服务 (五):认证和授权

断路器和舱壁模式

在微服务架构中,有两个重要的模式,它们能够让服务实现自愈的效果。


断路器模式(Circuit Breake)能够阻止请求发送到不健康的服务实例上,这样的话,服务能够进行恢复,同时,客户端的请求将会转发到服务的健康实例上(增加了成功率)。


舱壁模式会隔离失败,避免整个系统宕机,举例来说,服务 B 处于有问题的状态,另外一个服务(服务 B 的客户端)往服务 B 发送请求将会导致客户端耗尽线程池,从而不能为其他请求提供服务(即便其他的请求与服务 B 毫无关系也是如此)。


这里我不再展示这些模式的实现了,因为我迫不及待想要分享认证和授权的功能,这些模式的实现你可以参考官方文档

Istio 中的认证和授权

我从来没有想到有一天我会对认证和授权感到如此兴奋。在技术领域,Istio 到底做了什么能够让我对这样恐怖的话题感到兴奋呢,更重要的是它为什么能够让你也为此感到兴奋呢?


这是因为,Istio 将这些责任从我们的服务中剥离了出去,并将其委托给了 Envoy 代理,这意味着当请求抵达我们的服务时,它们已经经过了认证和授权,我们只需要编写提供业务价值的代码就可以了。


让我们来深入了解一下!

使用 Auth0 进行认证

我们会使用 Auth0 作为身份识别和访问管理的服务器,它有一个试用方案,对我来说非常便利,我非常喜欢它!这也就是说,相同的理念可以用于任意的OpenID Connect实现,比如 KeyCloak、IdentityServer 等等。


首先,使用预设账号导航至Auth0 Portal,在 Applications > Default App 下创建一个租户,并记住 Domain,如下所示:



图 22 Auth0 管理门户中的 Default App


更新resource-manifests/istio/security/auth-policy.yaml文件,以便于使用该 Domain:


apiVersion: authentication.istio.io/v1alpha1 kind: Policymetadata:  name: auth-policyspec:  targets:  - name: sa-web-app  - name: sa-feedback  origins:  - jwt:    issuer: "https://{YOUR_DOMAIN}/"    jwksUri: "https://{YOUR_DOMAIN}/.well-known/jwks.json"   principalBinding: USE_ORIGIN

复制代码


借助该资源,Pilot 将会配置 envoy 在将请求转发至 sa-web-app 和 sa-feedback 服务之前进行认证。同时,它不会将该规则应用于服务sa-frontend的 envoy,这样的话,前端能够不用进行认证。为了应用该策略,我们需要执行如下命令:


$ kubectl apply -f resource-manifests/istio/security/auth-policy.yamlpolicy.authentication.istio.io "auth-policy" created
复制代码


回到页面并发送一个请求,我们将会看到 401 Unauthorized,现在,我们让来自前端的用户使用 Auth0 进行认证。

使用 Auth0 认证请求

要认证终端用户的请求,我们需要在 Auth0 中创建一个 API,它代表了经过认证的服务,比如评论、详情和评级。为了创建这样的 API,我们需要导航至 Auth0 Portal > APIs > Create API,如下图所示:



图 23 创建 API


这里重要的信息是 Identifier,在随后的脚本中,我们会以如下的形式进行使用:


  • Audience: {YOUR_AUDIENCE}


其余所需的细节在 Auth0 Portal 的 Applications 下进行配置,选择自动创建的 Test Application,其名称与 API 相同。


这里需要注意:


  • Domain: {YOUR_DOMAIN}

  • Client Id: {YOUR_CLIENT_ID}


在 Test Application 中向下滚动至 Allowed Callback URLs 文本域,在这里我们可以指定在认证完成后要转发到哪个 URL,在我们的场景中,应该是:


http://{EXTERNAL_IP}/callback


Allowed Logout URLs 中添加如下的 URL:


http://{EXTERNAL_IP}/logout


接下来,我们更新前端。

更新前端

切换至仓库的 auth0 分支。在这个分支中,前端包含了将用户转发至 Auth0 进行认证的代码变更,并在发送至其他服务的请求中包含了 JWT Token,如下所示:


analyzeSentence() {    fetch('/sentiment', {        method: 'POST',        headers: {        'Content-Type': 'application/json',        'Authorization': `Bearer ${auth.getAccessToken()}` // Access Token     },    body: JSON.stringify({ sentence: this.textField.getValue() })   })  .then(response => response.json())   .then(data => this.setState(data));}

复制代码


为了更新前端以便于使用租户的详细信息,我们导航至sa-frontend/src/services/Auth.js文件并替换如下的值,也就是在前文中我提醒注意的地方:


const Config = {  clientID: '{YOUR_CLIENT_ID}',  domain:'{YOUR_DOMAIN}',  audience: '{YOUR_AUDIENCE}',  ingressIP: '{EXTERNAL_IP}' // Used to redirect after authentication}

复制代码


应用已经就绪了,在如下的命令指定 docker user id,然后构建和部署变更:


$ docker build -f sa-frontend/Dockerfile \  -t {DOCKER_USER_ID}/sentiment-analysis-frontend:istio-auth0 sa-frontend
$ docker push {DOCKER_USER_ID}/sentiment-analysis-frontend:istio-auth0$ kubectl set image deployment/sa-frontend \ sa-frontend={DOCKER_USER_ID}/sentiment-analysis-frontend:istio-auth0
复制代码


我们可以尝试运行一下应用。访问的时候,你会被导航至 Auth0,在这里必要要登录(或注册),再次之后会重新转发会页面,这时候就可以发送认证后的请求了。如果你使用之前的 curl 命令的话,将会遇到 401 状态码,表明请求没有经过授权。


接下来,我们更进一步,对请求进行授权。

使用 Auth0 进行授权

认证能够让我们知道用户是谁,但是我们需要授权信息才能得知他们能够访问哪些内容。Istio 也提供了这样的工具。


作为样例,我们会创建两组用户(如图 24 所示):


  • Users:只能访问 SA-WebApp 和 SA-Frontend 服务;

  • Moderators:能够访问所有的三个服务。



图 24 授权的概念


为了创建用户组,我们需要使用 Auth0 Authorization 扩展,随后借助 Istio,我们为它们提供不同级别的访问权限。

安装和配置 Auth0 授权

在 Auth0 Portal 中,切换至 Extensions,并安装“Auth0 Authorization”扩展。安装之后,切换至 Authorization Extension 并点击右上角你的租户并选择“Configuration”选项进行配置。启用组并点击“Publish rule”按钮。



图 25 在 Token Contents 中激活组

创建 Group

在 Authorization Extension 中,导航至 Groups 并创建 Moderators 组。我们会将所有已认证过的用户视为普通的 User,这样的话,就没有必要额外再建立一个组了。


选择 Moderators 组并点击 Add Members,然后添加你的主账号。请将一些用户不放到任何的组中,以便于检验禁止他们访问(你可以通过 Auth0 Portal > Users > Create User 手动注册新用户)。

添加 Group Claim 到 Access Token

用户现在已经添加到组中了,但是这些信息还没有反映到 Access Token 中。为了确保 OpenID Connect 的一致性,同时又能返回组,我们需要在 token 中添加自定义的命名空间声明。这可以通过 Auth0 规则来实现。


要在 Auth0 Portal 中创建规则,我们需要导航至 Rules,点击“Create Rule”,并从模板中选择一个 empty rule



图 26 Rules 截屏


粘贴如下的代码并将规则命名为“Add Group Claim”。


function (user, context, callback) {   context.accessToken['https://sa.io/group'] = user.groups[0];   return callback(null, user, context);}
复制代码


注意: 这个规则会获取 Authorization Extension 中定义的第一个用户组,并将其添加到 access token 中,作为自定义命名空间的声明。


回到 Rules 页面,确保我们按照如下顺序有了两个角色:


  • auth0-authorization-extension

  • Add Group Claim


这里的顺序是非常重要的,因为组的字段会由auth0-authorization-extension异步获取,然后由第二个规则将其添加为命名空间声明,这将会形成如下的 access token:


{"https://sa.io/group": "Moderators","iss": "https://bookinfo.eu.auth0.com/", "sub": "google-oauth2|196405271625531691872"// [shortened for brevity]}
复制代码


现在,我们必须配置 Envoy 代理,从而能够在返回的 access token 中抽取https://sa.io/group声明的组。这是下一部分的主题,我们马上来看一下。

在 Istio 中配置授权

为了实现授权,我们为 Istio 启用 RBAC。为了实现这一点,要将如下的配置用到 Mesh 中:


apiVersion: "rbac.istio.io/v1alpha1" kind: RbacConfigmetadata:  name: defaultspec:  mode: 'ON_WITH_INCLUSION'  # 1  inclusion:    services:               # 2    - "sa-frontend.default.svc.cluster.local"    - "sa-web-app.default.svc.cluster.local"    - "sa-feedback.default.svc.cluster.local"

复制代码


  1. 仅为“Inclusion”字段中的服务和命名空间启用 RBAC;

  2. 包含如下服务。


执行如下命令,应用该配置:


$ kubectl apply -f resource-manifests\istio\security\enable-rbac.yamlrbacconfig.rbac.istio.io "default" created
复制代码


现在,所有的服务都需要基于角色的访问控制(Role-Based Access Control),换句话说,访问所有的服务都会遭到拒绝并且响应中会包含“RBAC: access denied”。我们下一节的主题就是启用对授权用户的访问。

配置常规的用户访问

所有的用户应该都能访问 SA-Frontend SA-WebApp 服务,这是通过如下的 Istio 资源实现的:


  • ServiceRole:指定用户具有的权限;

  • ServiceRoleBinding:指定 ServiceRole 应用到哪些用户上。


对于常规用户,我们允许访问指定的服务:


apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRolemetadata:  name: regular-user   namespace: defaultspec:   rules:  - services:    - "sa-frontend.default.svc.cluster.local"    - "sa-web-app.default.svc.cluster.local"     paths: ["*"]    methods: ["*"]
复制代码


然后,借助 regular-user-binding,我们将该 ServiceRole 应用到页面的所有访问者上:


apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBindingmetadata:  name: regular-user-binding  namespace: default spec:  subjects:  - user: "*"  roleRef:    kind: ServiceRole    name: "regular-user"
复制代码


这里所说的所有用户,是不是意味着未认证的用户也能访问 SA WebApp 呢?并非如此,该策略依然会检查 JWT token 的合法性。


通过如下命令,应用该配置:


$ kubectl apply -f resource-manifests/istio/security/user-role.yamlservicerole.rbac.istio.io/regular-user createdservicerolebinding.rbac.istio.io/regular-user-binding created
复制代码

配置 Moderator 用户访问

对于 Moderator,我们想要启用对所有服务的访问:


apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRolemetadata:  name: mod-user  namespace: default spec:  rules:  - services: ["*"]    paths: ["*"]      methods: ["*"]
复制代码


但是,我们只想要绑定 Access Token 中https://sa.io/group声明的值为 Moderators 的用户。


apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBindingmetadata:  name: mod-user-binding  namespace: default spec:  subjects:  - properties:    request.auth.claims[https://sa.io/group]: "Moderators"  roleRef:    kind: ServiceRole    name: "mod-user"
复制代码


要应用该配置,需要执行下述命令:


$ kubectl apply -f resource-manifests/istio/security/mod-role.yamlservicerole.rbac.istio.io/mod-user unchanged servicerolebinding.rbac.istio.io/mod-user-binding unchanged
复制代码


Envoy 中会有缓存,所以授权规则可能需要几分钟之后才能生效,在此之后,我们就可以校验 Users 和 Moderators 会有不同级别的访问权限。


坦白讲,你见过像这样毫不费力就能构建可扩展的认证和授权吗,还有比这更简单的过程吗?反正我是没有见过!接下来,我们总结一下得到的结论。

结论

想象不到吧?我们将其称为怪兽(Beast-io),因为它确实太强大了。借助它,我们能够:


  • 实现服务的可观察性,借助 Kiali,我们能够回答哪个服务在运行、它们的表现如何以及它们是如何关联在一起的;

  • 借助 Prometheus Grafana,能够实现指标收集和可视化,完全是开箱即用的

  • 使用 Jaeger(德语中猎人的意思)实现请求跟踪;

  • 对网络流量的完整且细粒度控制,能够实现金丝雀部署、A/B 测试和影子镜像

  • 很容易实现重试、超时和断路器

  • 极大地减少了为集群引入新服务的开销;

  • 为各种语言编写的微服务添加了认证和授权功能,服务端代码无需任何修改。



图 27 Beast-io!


有个这个 Beastio,我们就能让团队真正地提供业务价值,并将资源聚焦在领域问题上,不用再担心服务的开销,让服务真正做到“微型化”。


我是 Rinor Maloku,非常感谢 Istio 之旅。你可以在Twitter 关注我,也可以访问我的主页 rinormaloku.com


2019-05-30 08:009649

评论

发布
暂无评论
发现更多内容

便携式ECG方案介绍

华秋电子

新品研发协同平台,助力快消企业新品上市成功!

赛博威科技

数字化转型 新产品 茅台 产品研发

达芬奇DaVinci Resolve Studio 18 密钥激活资源最新

mac大玩家j

Mac软件 达芬奇18 视频调色工具

软件测试|教你轻松解决pip安装下载超时问题

霍格沃兹测试开发学社

Hutool中那些常用的工具类和实用方法 | 京东云技术团队

京东科技开发者

hutool java工具类 企业号10月PK榜

你不知道的浏览器Console玩法

Kevin_913

前端 控制台 调试工具

云起无垠典型案例入选《2023软件供应链安全洞察》报告

云起无垠

记一次 TiDB v7.1 版本生产环境的完整搭建流程

TiDB 社区干货传送门

7.x 实践

软件测试|程序猿必会的git操作(二)

霍格沃兹测试开发学社

区块链挖矿系统-云算力挖矿模式APP平台介绍

西安链酷科技

区块链 算法 dapp 挖矿

数据安全法里面的数据是指什么?具体条例内容是什么?

行云管家

数据安全 数据安全法 数据运维 数据安全运维

PCB表面镀金工艺,还有这么多讲究!

华秋电子

git 拉取分支后不想合并了

图颜有信

数字孪生智慧钢厂 Web3D 可视化管理平台

2D3D前端可视化开发

5G 物联网 可视化 数字孪生 智慧钢厂

HAProxy安装及搭建tidb数据库负载均衡服务实战

TiDB 社区干货传送门

7.x 实践

玩转视图变量,轻松实现动态可视化数据分析

观测云

数据分析 可观测性 数据可视化

CSS色域、色彩空间、CSS Color 4新标准 | 京东云技术团队

京东科技开发者

CSS 前端 浏览器 企业号10月PK榜

正式官宣|集成无界·RestCloud零代码集成自动化平台即将发布

RestCloud

TiDB实践安装及性能测试(上)

TiDB 社区干货传送门

安装 & 部署 性能测评 6.x 实践

mac电脑版多协议远程管理软件:Termius激活中文版

胖墩儿不胖y

SSH SSH工具 Mac软件 ssh客户端

Macos必备 VM虚拟机:VMware Fusion Pro 13序列号激活 附 VM 13安装激活教程 支持M1 【亲测可用】

晴雯哥

软件测试|一文带你了解Flask框架

霍格沃兹测试开发学社

基础软件是世界的事业 | 论数据库开源的力量

TiDB 社区干货传送门

抢先体验!星河社区ERNIE Bot SDK现已支持文心大模型4.0

飞桨PaddlePaddle

开发工具 文心大模型 星河社区

WinX HD Video Converter for mac (视频格式转换器) 6.8.1激活版

mac

苹果mac Windows软件 视频转换器 WinX HD Video Converter

Dapp钱包智能合约链上质押模式系统开发

l8l259l3365

WebSocket 原理详解:全方位解读

Apifox

程序员 最佳实践 websocket 协议 API

通过NGINX搭建TiDB负载均衡

TiDB 社区干货传送门

安装 & 部署

支持信创的数据安全运维平台哪个好?咨询电话多少?

行云管家

信创 数据安全 国产 数据安全运维

软件测试|一文教你flask路由配置

霍格沃兹测试开发学社

TiDB实践安装及性能测试(下)

TiDB 社区干货传送门

迁移 管理与运维 备份 & 恢复 6.x 实践

通过 Istio 重新实现微服务 (五):认证和授权_文化 & 方法_Rinor Maloku_InfoQ精选文章