使用Istio打造微服务(第2部分) - 认证和受权

做者;Rinor Maloku 前端

译者:殷龙飞 web

审校:邱世达 docker

原文:medium.com/google-clou…json

这篇文章是使用Istio打造微服务

的第二部分,若是没有看第一篇的话,请先看第一部份内容,由于这篇博客是以第一篇博客为基础进行进一步深刻的。api

在第一篇文章中,咱们创建了一个Kubernetes集群,而且在上面部署了 Istio 和示例微服务应用程序“Sentiment Analysis”,用来展现Istio的功能。缓存

使用Istio后,咱们能够把应用层中的重试、超时、断路器、跟踪、监控内容抛弃,以保持咱们的服务应用保持在一个简单专一的微型状态,(如图1所示)。此外,咱们还启用了高级测试和部署技术,如A/B测试,镜像和金丝雀部署。安全

在本文中,咱们将带领读者使用Istio来处理身份验证和受权!bash

Istio中的认证和受权

我永远不会相信认证和受权会让我感到兴奋!可是Istio可让这个话题变得有趣,这种状况下难道你不感到兴奋么?服务器

答案很简单: Istio将这些职责从咱们的服务下沉到Envoy代理,当请求到达咱们的服务时,它们已经通过身份验证和受权,咱们只需编写提供业务价值的代码。并发

听起来不错? 让咱们去瞧瞧吧!

使用Auth0进行身份验证

做为身份和访问管理服务器,咱们将使用Auth0,它有一个试用选项,直观易用,我只是喜欢它! 也就是说,相同的原则能够用于任何 OpenID Connect实现, 如KeyCloak、IdentityServer等等。

要开始使用,请使用您的账户导航到Auth0 Portal,在Applications> Default App下建立租户并选择Domain,以下图所示:

更新文件 resource-manifests/istio/security/auth-policy.yaml 以使用您的域名:

apiVersion: authentication.istio.io/v1alpha1 kind: Policy metadata:   name: auth-policy spec:   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-appsa-feedback以前对其进行身份验证。同时,这个策略不会应用到运行sa-frontend服务的envoy上,这使得咱们可以未经认证就访问前端服务。要应用这些策略,请执行如下命令:

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

返回页面并发出请求,您将看到它将以401 Unauthorized结束,如今让咱们从前端转发用户以使用Auth0进行身份验证。

使用Auth0验证请求

要验证最终用户的请求,咱们须要在Auth0中建立一个API,表示通过身份验证的服务,即:评论,详细信息和评级。要建立API,请导航到 Auth0 Portal > API > Create API ,以下图所示。

这里的重要信息是稍后在脚本中使用的标识符:

  • 观众: {YOUR_AUDIENCE}

其他所需的详细信息位于Auth0 Portal中的 Applications 下 ,而后选择自动建立的与API同名的 Test Application

请记下:

  • 域名: {YOUR_DOMAIN}

  • 客户ID: {YOUR_CLIENT_ID}

在Test Application中向下滚动到Allowed Callback URLs文本位置,在此字段中咱们指定请求在完成身份验证后应被转发到的目的URL。在咱们的示例中,它是:

[http://{EXTERNAL_IP}/callback](http://%7BEXTERNAL_IP%7D/callback)

Allowed Logout URLs添加如下URL:

[http://{EXTERNAL_IP}/logout](http://%7BEXTERNAL_IP%7D/logout)

接下来让咱们开始处理前端。

更新前端

检出 [istio-mastery] 存储库中的auth0 分支。在此分支中,前端包含代码更改以将用户转发到Auth0进行身份验证,并在对其余服务的请求中使用JWT令牌,以下所示:

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用户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所示):

  • 用户 :只能访问SA-WebApp和SA-Frontend服务。

  • 版主 :能够访问全部三项服务。

要建立用户组,咱们将使用Auth0受权扩展,而后使用Istio,咱们将为他们提供不一样级别的访问权限。

安装和配置Auth0受权

在Auth0门户中,导航到Extensions并安装“Auth0 Authorization”扩展。安装完成后,导航到受权扩展并经过单击右上角的租户并选择菜单选项“配置”进行配置。启用组,而后单击 发布规则 按钮。

建立组

在受权扩展中,导航到 Groups 并建立Moderators组。同时,咱们会将全部通过身份验证的用户视为常规用户,所以无需建立其余组。

选择Moderators组,而后单击添加成员,添加您的主账户。保留一些没有任何组的用户,以验证是否禁止访问。(您能够在Auth0 Portal>用户>建立用户中手动注册新用户)

将组声明添加到访问令牌

用户将添加到组中,但此信息不会反映在访问令牌中。为了保持OpenID Connect符合要求并同时返回组,咱们须要向令牌添加自定义命名空间声明。这可使用Auth0规则来完成。

要在Auth0 Portal中建立规则,请导航到规则,单击“建立规则”并 从模板中 选择一个 空规则

粘贴下面的代码并保存名为“添加组声明”的新规则。

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

注意: 此代码选择受权扩展中定义的第一个用户组,并将其做为自定义命名空间声明添加到访问令牌中。

返回 规则页面 ,确认您按此顺序拥有两个角色:

  • auth0受权扩展

  • 添加组声明

顺序很重要,由于 **auth0-authorization-extension** 规则会异步检索组字段 ,而后由第二个规则将其添加为命名空间声明,从而产生如下访问令牌:

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

如今,咱们必须经过从https://sa.io/group返回的访问令牌中的声明中提取组来配置Envoy代理以验证用户访问权限。这是下一节的主题,让咱们继续前进。

在Istio中配置受权

要得到受权,咱们须要为Istio启用RBAC。为此,请将如下配置应用于Mesh:

apiVersion: "rbac.istio.io/v1alpha1" kind: RbacConfig metadata:   name: default spec:   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. 仅为“包含”字段中指定的服务和/或命名空间启用RBAC。

  2. 包括指定的服务列表。

经过执行如下命令应用配置:

$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml rbacconfig.rbac.istio.io/default created复制代码

如今,全部服务都须要基于角色的访问控制,换句话说,对全部服务的访问都会被拒绝,并响应“RBAC: access denied”。启用对受权用户的访问权限将成为下一节的主题。

配置常规用户访问

全部用户都应该可以访问 SA-FrontendSA-WebApp 服务,这是经过如下Istio的资源实现的:

  • ServiceRole: 指定用户拥有的权限

  • ServiceRoleBinding: 指定ServiceRole应用于谁。

对于普通用户,咱们将容许访问指定的服务:

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

使用 常规用户绑定, 咱们将ServiceRole应用于咱们页面的全部访问者:

哦! 全部用户这意味着未经身份验证的用户可使用SA WebApp吗? 不,该策略仍将检查JWT令牌的有效性。😉

应用配置:

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

配置版主用户访问权限

对于咱们的版主,咱们但愿启用对全部服务的访问:

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

但咱们只想将其绑定到Access Token声明 https://sa.io/group 等于Moderators值的用户。

apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
  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.yaml servicerole.rbac.istio.io/mod-user created servicerolebinding.rbac.istio.io/mod-user-binding created复制代码

因为Envoy中的缓存,受权规则可能须要几分钟才能生效,但在此以后,您将可以验证用户和版主具备不一样的访问级别。

第2部分 - 摘要

您是否真的见过任何更简单,零工做的可扩展和安全的身份验证和受权概念?

仅使用三个Istio资源(RbacConfig,ServiceRole和ServiceRoleBinding),咱们能够经过细粒度控制对最终用户访问咱们服务进行身份验证和受权。

此外,咱们将这些问题从咱们的服务中转移到咱们的Envoy:

  • 减小可能出现安全问题和漏洞的样板代码,

  • 减小由于忘记标记注解而暴露服务端点的愚蠢情况。

  • 每次添加新角色或权限时,都会消除更新全部服务的连锁效应。

  • 保持简单,安全和快速地添加新服务。

结论

Istio 使您的团队可以再次将资源集中在提供商业价值上,而不须要为服务的周边任务进行处理,让微服务回归“微型”的本质。

本文为您提供了在实际项目中开始使用Istio的知识和实践。

借此机会,我很感谢你加入个人此次Istio探索之旅,这确定不容易,你坚持下去就已经很棒了。我十分但愿在下面的评论中看到您的想法,你能够随时在 Twitter 或个人主页 rinormaloku.com 上与我联系。

相关文章
相关标签/搜索