注意事项 佩雷夫 :本系列的第一部分致力于介绍Istio的功能并在实际中进行演示, 第二部分则是对路由和网络流量管理的精细调整。 现在,我们将讨论安全性:为了演示与安全性相关的基本功能,作者使用Auth0身份服务,但是可以通过类比来配置其他提供程序。我们建立了一个Kubernetes集群,其中部署了Istio和Sentiment Analysis微服务应用程序,这就是Istio的演示方式。
使用Istio,我们能够将服务保持在较小的规模,因为它们不需要实现诸如重试,退出,超时,断路器,跟踪,监视之类的“层” 。 此外,我们使用了先进的测试和部署技术:A / B测试,镜像和Canary推出。

在新材料中,我们将探讨实现商业价值的最后几层:身份验证和授权-在Istio中,这是一种真正的乐趣!
Istio中的身份验证和授权
我永远都不会相信身份验证和授权会启发我。 Istio能提供什么技术来使这些话题变得有趣,甚至可以激发您的灵感?
答案很简单:Istio将这些功能的责任从您的服务转移到Envoy代理。 在请求到达服务时,它们已经通过身份验证和授权,因此您只需要编写对业务有用的代码。
听起来不错吗? 让我们看看里面!
使用Auth0进行身份验证
我们将使用Auth0作为身份和访问管理服务器,该服务器具有一个试用版,使用直观,我很喜欢。 但是,可以将相同的原理应用于任何其他
OpenID Connect实现 :KeyCloak,IdentityServer等。
首先,使用您的帐户转到
Auth0门户 ,创建一个租户
(租户-“租户”,逻辑隔离单元,有关更多详细信息,请参见文档 -Transl。)然后转到
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
(Istio中Control Plane的三个基本组件之一-大约翻译)将Envoy配置为在将请求重定向到服务之前对请求进行身份验证:
sa-web-app
和
sa-feedback
。 同时,该配置不适用于
sa-frontend
,使我们可以使前端未经身份验证。 要应用策略,请执行以下命令:
$ kubectl apply -f resource-manifests/istio/security/auth-policy.yaml policy.authentication.istio.io “auth-policy” created
返回页面并进行请求-您将看到它以
401未经授权状态结束。 现在,我们将前端用户重定向到使用Auth0进行身份验证。
使用Auth0进行身份验证
要验证最终用户的请求,您需要在Auth0中创建一个API,该API代表已验证的服务(评论,详细信息和等级)。 要创建API,请转到
Auth0门户> API>创建API并填写以下表格:

这里的重要信息是
标识符 ,我们将在脚本的后面部分使用它。 让我们这样写出来:
我们需要的其余详细信息位于“
应用程序”部分的Auth0门户上-选择“
测试应用程序” (使用API自动创建)。
在这里我们写:
- 域 :{YOUR_DOMAIN}
- 客户编号 :{YOUR_CLIENT_ID}
在“
测试应用程序”中 ,滚动到“
允许的回调URL”文本框(回调的允许的URL),在其中我们指示身份验证完成后应将呼叫发送到的URL。 在我们的例子中是:
http://{EXTERNAL_IP}/callback
对于
允许的注销URL (允许
注销的URL ),添加:
http://{EXTERNAL_IP}/logout
让我们继续前进到前端。
前端更新
切换到
[istio-mastery]
存储库的
auth0
分支。 在此线程中,更改了前端代码,以将用户重定向到Auth0进行身份验证,并在对其他服务的请求中使用JWT令牌。 后者的实现如下(
App.js ):
analyzeSentence() { fetch('/sentiment', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${auth.getAccessToken()}`
要将前端转换为使用Auth0中的租户数据,请打开
sa-frontend/src/services/Auth.js
并替换上面我们在其中写入的值(
Auth.js ):
const Config = { clientID: '{YOUR_CLIENT_ID}', domain:'{YOUR_DOMAIN}', audience: '{YOUR_AUDIENCE}', ingressIP: '{EXTERNAL_IP}'
该应用程序已准备就绪。 在构建和部署所做更改时,在以下命令中指示您的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也为此提供工具。
作为示例,我们将创建两个用户组(请参见下图):
- 用户 (用户) -只能访问SA-WebApp和SA-Frontend服务;
- 主持人 -可以访问所有三项服务。
授权概念要创建这些组,我们将使用Auth0授权扩展,并使用Istio为它们提供不同的访问级别。
Auth0授权的安装和配置
在Auth0门户上,转到“
扩展”并安装
Auth0 Authorization 。 安装完成后,请转到“
授权扩展” ,然后通过单击右上角并选择适当的菜单选项
(“配置”)进入租户的配置。 激活
组 ,然后单击
发布规则按钮。

组创建
在授权扩展中,转到“
组”并创建一个“
主持人”组。 由于我们将所有经过身份验证的用户视为普通用户,因此无需为他们创建其他组。
选择
主持人组,单击
添加成员 ,添加您的主帐户。 使某些用户没有任何组,以确保拒绝他们的访问。 (可以通过
Auth0 Portal>用户>创建用户手动创建新用户。)
将组声明添加到访问令牌
将用户添加到组中,但是此信息应反映在访问令牌中。 为了遵守OpenID Connect并同时返回我们需要的组,令牌将需要添加其
自定义Claim 。 它通过Auth0的规则实现。
要创建规则,请转到Auth0门户网站
规则 ,单击
创建 规则 ,然后从模板中选择一个空规则。

复制下面的代码,并将其保存为新的“
添加组声明”规则(
namespacedGroup.js ):
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" // [ ] }
现在,您需要配置Envoy代理来检查用户访问权限,为此用户将从请求的访问令牌(
https://sa.io/group
)中拉出该组。 这是本文下一部分的主题。
Istio授权配置
为使授权生效,您必须为Istio启用RBAC。 为此,请使用以下配置:
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-仅对“
Inclusion
字段中列出的服务和名称空间启用RBAC; - 2-列出我们的服务列表。
我们通过以下命令应用配置:
$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml rbacconfig.rbac.istio.io/default created
现在,所有服务都需要基于角色的访问控制。 换句话说,对所有服务的访问都被拒绝,这将导致
RBAC: access denied
响应
RBAC: access denied
。 现在允许访问授权用户。
普通用户的访问配置
所有用户都必须有权访问SA-Frontend和SA-WebApp服务。 使用以下Istio资源实现:
- ServiceRole-定义用户拥有的权限;
- ServiceRoleBinding-确定此ServiceRole属于谁。
对于普通用户,允许访问某些服务(
servicerole.yaml ):
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: ["*"]
通过
regular-user-binding
将ServiceRole应用于页面的所有访问者(
regular-user-service-role-binding.yaml ):
apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: regular-user-binding namespace: default spec: subjects: - user: "*" roleRef: kind: ServiceRole name: "regular-user"
“所有用户”是否意味着未经身份验证的用户将有权访问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
主持人的访问权限配置
对于主持人,我们希望启用对所有服务的访问(
mod-service-role.yaml ):
apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: mod-user namespace: default spec: rules: - services: ["*"] paths: ["*"] methods: ["*"]
但是,我们只希望对访问令牌的声明为
https://sa.io/group
且其值为
Moderators
(
mod-service-role-binding.yaml )的那些用户使用这些权限:
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
由于特使缓存,授权规则可能要花几分钟的时间才能生效。 此后,您可以确保用户和主持人具有不同的访问级别。
结论部分
好吧,认真:您是否见过一种更简单,轻松,可扩展且安全的身份验证和授权方法?
为了实现对最终用户访问服务的身份验证和授权的精细控制,仅需要三个Istio资源(RbacConfig,ServiceRole和ServiceRoleBinding)。
此外,我们在特使的服务范围内照顾了这些问题,从而实现了:
- 减少可能包含安全性问题和错误的示例代码数量;
- 减少愚蠢的情况,其中一个端点原来可以从外部访问并且忘记了报告;
- 无需在每次添加新角色或权利时都更新所有服务;
- 新服务保持简单,安全和快速。
结论
Istio允许团队将资源集中在业务关键型任务上,而不会增加服务的开销,而使服务返回微状态。
本文(分为三部分)提供了在实际项目中开始使用Istio的基础知识和现成的实践指导。
译者的PS
另请参阅我们的博客: