本教程已加入 Istio 系列:https://istio.whuanle.cn

7,认证

本章的内容主要是讲解服务间通讯的安全和集群外部访问内部服务的 jwt token 验证。

Istio 提供两种类型的认证,一种是服务间认证 Peer Authentication,一种是客户端请求认证 Request Authentication。

Peer Authentication

Peer authentication 用于服务到服务的认证,在零信任网络中,Envoy 给服务之间的通讯加密,只有服务双方才能看到请求内容和响应结果。

在 Istio 中,默认情况下,服务之间的通信不会被加密或进行身份验证。比如说, A 服务通过 http 请求 B 服务,流量经过 Envoy A 时,Envoy A 直接将流量发送到 Envoy B 中,流量不会进行加密处理,也就是明文请求。

Istio 的 Peer Authentication 主要解决以下问题:

  • 保护服务到服务的通信。
  • 提供密钥管理系统,通讯加密需要使用证书,而证书会过期,所以需要一个管理系统自动颁发证书、替换证书等。
  • 为每个服务提供强大的身份标识,以实现跨群集和云的互操作性。

Request Authentication

Request authentication 用于外部请求的用户认证, Istio 使用 JWT(JSON Web Token) 来验证客户端的请求,并使用自定义认证实现或任何 OpenID Connect 的Request authentication 认证实现来简化的开发人员体验。

支持以下认证类型:

  • ORY Hydra
  • Keycloak
  • Auth0
  • Firebase Auth
  • Google Auth

Peer Authentication

Istio 的 PeerAuthentication 是一种安全策略,用于对服务网格内的工作负载之间的通信进行双向 TLS(mTLS)验证。

通过 PeerAuthentication 在 Envoy 间启用 mTLS,以确保工作负载之间的通信在传输过程中是加密和安全的。

PeerAuthentication 可以配置为整个集群或只在命名空间中起作用,但是只能有一个网格范围的 Peer 认证策略,每个命名空间也只能有一个命名空间范围的 Peer 认证策略。

PeerAuthentication 的定义

下面是一个简单的 PeerAuthentication 示例:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: my-peer-authentication
namespace: my-namespace
spec:
selector:
matchLabels:
app: my-app
mtls:
mode: STRICT
  • selector: 标签选择器,用于选择应用 PeerAuthentication 策略的工作负载。例如:
selector:
matchLabels:
app: my-app

如果省略选择器,PeerAuthentication 策略将应用于命名空间中的所有工作负载。

  • mtls: 定义双向 TLS 的模式,有三种模式。

    • STRICT: 强制执行 mTLS,要求客户端和服务器使用 TLS 进行通信。这需要客户端和服务器具有有效的证书。

    • PERMISSIVE: 允许客户端使用TLS或纯文本进行通信。这对于逐步迁移到 mTLS 的场景非常有用。

    • DISABLE: 禁用 mTLS,不要求客户端和服务器使用 TLS 进行通信。

只能有一个网格范围的 Peer 认证策略,每个命名空间也只能有一个命名空间范围的 Peer 认证策略。当同一网格或命名空间配置多个网格范围或命名空间范围的 Peer 认证策略时,Istio 会忽略较新的策略。当多个特定于工作负载的 Peer 认证策略匹配时,Istio 将选择最旧的策略。

实验

我们继续服用前面使用的 bookinfo 微服务,给 bookinfo 命名空间启用 mTLS。

kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
name: "bookinfo-policy"
namespace: "bookinfo"
spec:
mtls:
mode: STRICT
EOF

然后再次请求 productpage 服务,可以使用以下命令制作大量的模拟请求。

for i in `seq 1 1000`; do curl -s -o /dev/null http://192.168.3.150:30666/productpage; done

然后在 kiali 面板中的 Display 选项中下拉选择 Security。

RequestAuthencation

Istio 的 RequestAuthentication 是一种安全策略,用于验证和授权客户端访问Istio服务网格中的服务。

RequestAuthencation 需要搭配一个 AuthorizationPolicy来 使用。RequestAuthentication 和 AuthorizationPolicy 这两个策略用于验证和授权客户端访问服务网格中的服务。

RequestAuthentication 负责验证客户端提供的 JWT,而 AuthorizationPolicy 负责基于角色的访问控制(RBAC),允许定义细粒度的权限以限制对特定服务、方法和路径的访问。

RequestAuthencation 的定义

下面是一个完整的 RequestAuthentication 示例:

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: my-request-authentication
namespace: my-namespace
spec:
jwtRules:
- issuer: "https://accounts.google.com"
audiences:
- "my-audience-1"
- "my-audience-2"
jwksUri: "https://www.googleapis.com/oauth2/v3/certs"
jwtHeaders:
- "x-jwt-assertion"
- "x-jwt-assertion-original"
jwtParams:
- "access_token"
forward: true

如果只针对命名空间中的部分应用,可以使用:

  selector:
matchLabels:
app: my-app

在 RequestAuthentication 中,jwtRules 是一个配置项,用于定义如何验证和处理 JWT。

一个典型的 jwtRules 配置可能包括以下几个部分:

  • issuer: 发行者,表示JWT的发行方,例如:https://accounts.google.com。这个字段用于验证JWT的iss(发行者)声明。
  • audiences: 受众列表,表示接受JWT的一组实体。这个字段用于验证JWT的aud(受众)声明。例如:["my-audience-1", "my-audience-2"]
  • jwksUri: JSON Web Key Set(JWKS)的URL,用于获取JWT签名公钥。Istio会从这个URL下载公钥,用于验证JWT的签名。例如:https://www.googleapis.com/oauth2/v3/certs
  • jwtHeaders: 一个字符串数组,表示可以从HTTP请求头中获取JWT的头名称。默认情况下,Istio会从"Authorization"头中获取令牌。例如:["x-jwt-assertion", "x-jwt-assertion-original"]
  • jwtParams: 一个字符串数组,表示可以从HTTP请求参数中获取JWT的参数名称。例如:["access_token"]
  • forward: 一个布尔值,表示是否将JWT转发给上游服务。默认值为false,表示JWT令牌不会转发给上游服务。如果设置为true,则Istio会将令牌添加到请求头中,并转发给上游服务。

通过正确配置 jwtRules,Istio 可以对请求中的 JWT 进行验证,确保客户端访问服务网格中的服务时具有适当的授权。

AuthorizationPolicy 的定义

Istio 的 AuthorizationPolicy 是一种安全策略,用于控制在Istio服务网格中谁可以访问哪些服务。它提供了基于角色的访问控制(RBAC),允许定义细粒度的权限,以限制对特定服务、方法和路径的访问。AuthorizationPolicy 使用 Istio 的 Envoy 代理拦截并检查传入的请求,以确保它们满足定义的访问策略。

AuthorizationPolicy 的示例如下:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin-policy
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- to:
- operation:
paths: ["/delay/*"]

AuthorizationPolicy 的主要属性包括:

  • action: 定义在规则匹配时要执行的操作。它可以是ALLOW(允许访问),DENY(拒绝访问)或CUSTOM(自定义操作,与自定义扩展插件一起使用)。
  • rules: 定义一组访问策略规则。每个规则可以包括以下属性:
    • from: 包含一个或多个源规范,用于定义允许访问的来源。可以包括principals(发起请求的主体,例如用户或服务帐户)和namespaces(发起请求的命名空间)。
    • to: 包含一个或多个目标规范,用于定义允许访问的操作。可以包括methods(允许的HTTP方法,例如GET或POST)和paths(允许访问的路径,可以是精确路径或通配符路径)。
    • when: 包含一组条件,用于定义规则生效的附加约束。例如,您可以使用keyvalues定义请求头匹配。

实验

RequestAuthentication 的作用对象是 Kubernetes Service,主要有两种形式,一种是绑定 ingressgateway。

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: ingress-jwt
namespace: bookinnfo
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.17/security/tools/jwt/samples/jwks.json"

一种是绑定 Pod。

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: frontend
namespace: default
spec:
selector:
matchLabels:
app: frontend
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.5/security/tools/jwt/samples/jwks.json"

考虑到一般不会在 istio-ingressgateway 这个入口网关上操作,所以下面我们使用第二种形式做实验。

提供 jwksjson

首先是这个 YAML 文件中的 jwksUri,里面包含了一个 jwksjson 地址,里面包含了用于验证 token 是否有效的公钥。

在 C# 中,可以这样生成一个 jwksjson。

using System;
using System.IO;
using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json; namespace JWKSGenerator
{
class Program
{
static void Main(string[] args)
{
using var rsa = RSA.Create(2048);
var jwk = new RsaSecurityKey(rsa);
jwk.KeyId = Guid.NewGuid().ToString();
var jsonWebKey = JsonWebKeyConverter.ConvertFromRSASecurityKey(jwk);
var jwkJson = JsonConvert.SerializeObject(jsonWebKey); var jwksJson = "{\"keys\": [" + jwkJson + "]}";
Console.WriteLine(jwksJson);
}
}
}

创建 RequestAuthentication

考虑到官网示例中给出的 jwks.json 需要FQ才能访问,我们可以直接将 jwks.json 放在 YAML 文件中。

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: httpbin-jwt
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
jwtRules:
- issuer: "testing@secure.istio.io"
forwardOriginalToken: true
jwks: |
{
"keys": [
{
"e": "AQAB",
"kid": "DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ",
"kty": "RSA",
"n": "xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"
}
]
}

或者继续使用官方的 jwksUri。

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: httpbin-jwt
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
jwtRules:
- issuer: "testing@secure.istio.io"
forwardOriginalToken: true
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.5/security/tools/jwt/samples/jwks.json"

然后部署一个 AuthorizationPolicy,对 /delay/* 地址进行全放通,那么其它地址都需要进行验证才能放行。

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin-policy
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- to:
- operation:
paths: ["/delay/*"]

执行命令之后,你可以使用以下命令查看是否正常:

kubectl logs -n istio-system -l app=istiod

然后查看策略规则对象:

kubectl get requestauthentication -n bookinfo
kubectl get authorizationpolicy -n bookinfo

最后通过 istio-ingressgateway 的节点端口来访问 /status/delay ,会发现 /status 在没有 token 的情况下返回 403,而 /delay 可以正常访问。

如果我们需要验证,当 token 中的 issuer 为 example-issuer 才能访问时,可以使用:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: httpbin-policy
namespace: bookinfo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- to:
- operation:
paths: ["/delay/*"]
when:
- key: request.auth.claims[iss]
values: ["example-issuer"]

AuthorizationPolicy 的规则有很多,可以通过这些规则限制不同服务的访问策略。

请参考官方文档:https://istio.io/latest/zh/docs/concepts/security/#authorization-policies

所以 istio 这里一般做验证 jwt 是否有效,或者做路由地址的策略访问,但是如果有数十个上百个路由,使用 istio 配置就会好麻烦。但是依然不是我们想要的,因为在 istio 中配置不同应用访问权限和检验 token 比较繁琐,而且业务系统大多数情况下需要给用户单独配置各种 API 的访问权限。

Isito 入门(九):安全认证的更多相关文章

  1. 网络编程懒人入门(九):通俗讲解,有了IP地址,为何还要用MAC地址?

    1.前言 标题虽然是为了解释有了 IP 地址,为什么还要用 MAC 地址,但是本文的重点在于理解为什么要有 IP 这样的东西.本文对读者的定位是知道 MAC 地址是什么,IP 地址是什么. (本文同步 ...

  2. C#基础入门 九

    C#基础入门 九 集合 对于很多应用程序,需要创建和管理相关对象组,有两种方式可以将对象分组,一是创建对象数组,如 object[] obj=new object[3]{1,2.33,"st ...

  3. cesium编程入门(九)实体 Entity

    cesium编程入门(九)实体 Entity 在cesium编程入门(五)绘制形状提到过添加实体的方法,这一节聊一聊实体相关的一些内容: 先来看 Entity 的各个属性 id 唯一标志,如果没设置, ...

  4. LOJ数列分块入门九题(上)

    一转眼,已经有整整一年没有在博客园写博客了.去洛谷写了几篇(How time flys. 最近突然想起其实我不太擅长分块算法,又想起去年暑假有位同学同我提起过LOJ的数列分块九题,说来惭愧,打了这么久 ...

  5. Django学习之九: auth 认证组件

    目录 Django auth 认证组件 配置使用auth组件及其中间件 request.user 可以直接在template模版中使用 auth组件常用api 获取认证model类 认证检测装饰器@l ...

  6. requests库入门04-http基本认证

    因为后续样例中GitHub都需要提供认证,所以先写关于基本认证的 http的请求中,有一些请求是需要通过授权认证之后才会响应,授权认证就是检查用户名和密码的过程.http有一个基本认证方式,在认证的过 ...

  7. 数列分块入门九题(三):LOJ6283~6285

    Preface 最后一题我一直觉得用莫队是最好的. 数列分块入门 7--区间乘法,区间加法,单点询问 还是很简单的吧,比起数列分块入门 7就多了个区间乘. 类似于线段树,由于乘法的优先级高于加法,因此 ...

  8. 数列分块入门九题(二):LOJ6280~6282

    Preface 个人感觉这中间的三题是最水的没有之一 数列分块入门 4--区间加法,区间求和 这个也是很多数据结构完爆的题目线段树入门题,但是练分块我们就要写吗 修改还是与之前类似,只不过我们要维护每 ...

  9. 数列分块入门九题(一):LOJ6277~6279

    Preface 分块,一个神奇的暴力算法.可以把很多\(O(n^2)\)的数据结构题的暴力优化到常数极小的\(O(n\sqrt n)\).当一些毒瘤题无法用线段树,主席树,平衡树,树状数组...... ...

  10. 微服务Kong(九)——认证参考

    客户端访问上游API服务,通常由Kong的认证插件及其配置参数来控制. 通用认证 一般情况下,上游API服务都需要客户端有身份认证,且不允许错误的认证或无认证的请求通过.认证插件可以实现这一需求.这些 ...

随机推荐

  1. Java IO流 - 字节流的使用详细介绍

    IO流的基本介绍: IO流的概述: i 表示intput,是数据从硬盘文件读入到内存的过程,称之输入,负责读. o 表示output,是内存程序的数据从内存到写出到硬盘文件的过程,称之输出,负责写. ...

  2. 【原创】Ftrace使用及实现机制

    Ftrace使用及实现机制 版权声明:本文为本文为博主原创文章,转载请注明出处 https://www.cnblogs.com/wsg1100 如有错误,欢迎指正. 目录 Ftrace使用及实现机制 ...

  3. 2021-7-7 Vue实现切换图片功能代码

    <!DOCTYPE html> <html> <head> <title> </title> </head> <body& ...

  4. Robot Framework 自动化测试随笔(二)

    二.Web自动化(1) 1.安装selenium2library库 pip install robotframework-selenium2library   2.指定报告的生成路径 在[Run]标签 ...

  5. pycharm:插件translation 更新TTK失败

    解决方案 1.修改C:\Windows\System32\drivers\etc 下hosts文件, 添加 203.208.40.66 translate.google.com 203.208.40. ...

  6. pandas 根据内容匹配并获取索引

    bool = ExcelDataStr.str.contains("Item No./Customer/Saler") # 初始位置:initial position, 终位置:e ...

  7. Bootstrap使用方法

    中文文档:https://www.bootcss.com/ 使用方式: 1.选择对应的文档:  2.网站会自动跳转,一般选择Bootstrap3中文文档:  3.点击入门,下拉找到基础模板,复制代码到 ...

  8. Rollup 编译资源离不开 plugin

    rollup 也是一个 JavaScript 的模块化编译工具,可以帮助我们处理资源. 与webpack比较 rollup相比 webpack 理念更为简单,能处理的场景也更有限. 资源类型 处理方式 ...

  9. 一篇博客带你上手Git

    概述 安装Git 下载官方网站,下载后安装包样式:双击安装,安装成功后右键文件会有如下选项证明安装成功. 基本配置 设置用户信息,桌面右键,选择Git bash here hecheng@LAPTOP ...

  10. 聊一聊 Go 的内存对齐

    前言 在一次工作中,需要使用 Go 调用 DLL 文件,其中就涉及到内存对齐的相关知识,如果自定义的结构体内存布局和所调用的 DLL 结构体内存布局不一致,就会无法正确调用.所以,一旦涉及到较为底层的 ...