笔记。 翻译。:
我们设置了一个 Kubernetes 集群,在其中部署了 Istio 和一个示例微服务应用程序“情感分析”,以演示 Istio 的功能。
借助 Istio,我们能够保持服务规模较小,因为它们不需要实现重试、超时、断路器、跟踪、监控等层。 此外,我们还使用了先进的测试和部署技术:A/B 测试、镜像和金丝雀部署。
在新材料中,我们将处理商业价值之路上的最后几层:身份验证和授权 - 在 Istio 中这真是一种乐趣!
Istio 中的身份验证和授权
我永远不会相信我会受到身份验证和授权的启发。 从技术角度来看,Istio 可以提供什么来使这些主题变得有趣,甚至更能启发您?
答案很简单:Istio 将这些功能的责任从您的服务转移到 Envoy 代理。 当请求到达服务时,它们已经经过身份验证和授权,因此您所要做的就是编写业务有用的代码。
听起来不错? 让我们看看里面吧!
使用 Auth0 进行身份验证
作为身份和访问管理的服务器,我们将使用 Auth0,它有试用版,使用起来很直观,我就是喜欢它。 然而,相同的原则可以应用于任何其他
要开始使用,请访问
在文件中指定该域 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 中的三个基本控制平面组件之一 - 大约翻译) 配置 Envoy 在将请求转发到服务之前对请求进行身份验证: sa-web-app
и sa-feedback
。 同时,该配置不适用于服务Envoys 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 并填写表格:
这里的重要信息是 识别码,我们稍后将在脚本中使用它。 让我们这样写:
- 目的:{YOUR_AUDIENCE}
我们需要的其余详细信息位于 Auth0 门户的 部分 应用领域 - 选择 测试申请 (与 API 一起自动创建)。
这里我们会写:
- 域名: {YOUR_DOMAIN}
- 客户编号:{YOUR_CLIENT_ID}
滚动到 测试申请 到文本字段 允许的回调 URL (回调的已解析 URL),其中我们指定身份验证完成后应将调用发送到的 URL。 在我们的例子中是:
http://{EXTERNAL_IP}/callback
和 允许的注销 URL (允许注销的 URL)添加:
http://{EXTERNAL_IP}/logout
让我们继续讨论前端。
前端更新
切换到分支 auth0
存储库 [istio-mastery]
。 在此分支中,前端代码已更改为将用户重定向到 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));
}
要更改前端以使用 Auth0 中的租户数据,请打开 sa-frontend/src/services/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 授权。 安装完成后,进入 授权扩展,然后 - 通过单击右上角并选择适当的菜单选项来查看租户的配置 (配置)。 激活群组 (团体) 然后点击发布规则按钮 (发布规则).
创建群组
在授权扩展中转到 组别 并创建一个组 版主。 由于我们将所有经过身份验证的用户视为普通用户,因此无需为他们创建额外的组。
选择一个组 版主, 按 新增成员,添加您的主帐户。 让某些用户不属于任何组,以确保他们被拒绝访问。 (可以通过手动创建新用户 Auth0 门户 > 用户 > 创建用户.)
将组声明添加到访问令牌
用户已添加到组中,但此信息也必须反映在访问令牌中。 为了遵守 OpenID Connect 并同时返回我们需要的组,令牌需要添加自己的
要创建规则,请转至 Auth0 Portal 规则, 按 创建规则 并从模板中选择一个空规则。
复制下面的代码并将其另存为新规则 添加团体声明 (
function (user, context, callback) {
context.accessToken['https://sa.io/group'] = user.groups[0];
return callback(null, user, context);
}
注意:此代码采用授权扩展中定义的第一个用户组,并将其作为自定义声明添加到访问令牌(在其命名空间下,根据 Auth0 的要求)。
返回页面 规则 并检查您是否有按以下顺序编写的两条规则:
- auth0-授权-扩展
- 添加团体声明
顺序很重要,因为组字段异步接收规则 auth0-授权-扩展 然后根据第二条规则将其添加为声明。 结果是一个像这样的访问令牌:
{
"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 — 仅对字段中列出的服务和命名空间启用 RBAC
Inclusion
; - 2 — 我们列出了我们的服务列表。
让我们使用以下命令应用配置:
$ kubectl apply -f resource-manifests/istio/security/enable-rbac.yaml
rbacconfig.rbac.istio.io/default created
所有服务现在都需要基于角色的访问控制。 换句话说,所有服务的访问都被禁止,并且会导致响应 RBAC: access denied
。 现在让我们允许授权用户访问。
普通用户的访问配置
所有用户都必须有权访问 SA-Frontend 和 SA-WebApp 服务。 使用以下 Istio 资源实现:
- 服务角色 ——确定用户拥有的权利;
- 服务角色绑定 — 确定此 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: ["*"]
通过 regular-user-binding
将 ServiceRole 应用于所有页面访问者(
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
主持人的访问配置
对于版主,我们希望允许访问所有服务(
apiVersion: "rbac.istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: mod-user
namespace: default
spec:
rules:
- services: ["*"]
paths: ["*"]
methods: ["*"]
但我们只希望那些访问令牌包含声明的用户拥有这样的权利 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 中存在缓存,授权规则可能需要几分钟才能生效。 然后,您可以确保用户和主持人具有不同的访问级别。
这部分的结论
但说真的,您见过更简单、轻松、可扩展且安全的身份验证和授权方法吗?
只需三个 Istio 资源(RbacConfig、ServiceRole 和 ServiceRoleBinding)即可实现对最终用户访问服务的身份验证和授权的细粒度控制。
此外,我们还通过特使服务解决了这些问题,实现了:
- 减少可能包含安全问题和错误的通用代码的数量;
- 减少愚蠢情况的数量,在这种情况下,一个端点可从外部访问但忘记报告;
- 无需在每次添加新角色或权限时更新所有服务;
- 新服务仍然简单、安全和快速。
结论
Istio 允许团队将资源集中在关键业务任务上,而不增加服务开销,将其恢复到微观状态。
本文(分三部分)提供了在实际项目中开始使用 Istio 的基础知识和现成的实用说明。
译者PS
另请阅读我们的博客:
- “回到 Istio 的微服务”:
第 1 部分(主要功能介绍) ,第 2 部分(路由、流量控制) ; - «
Conduit - Kubernetes 的轻量级服务网格 “; - «
什么是服务网格,为什么我需要它 [用于具有微服务的云应用程序]? “。
来源: habr.com