文章中使用到的相关资源下载处:istio 实战:JWT认证
前言
请求认证策略指定验证 JSON Web Token(JWT)所需的值。这些值包括:
- token 在请求中的位置
- 请求的 issuer
- 公共 JSON Web Key Set(JWKS)
Istio 会根据请求认证策略中的规则检查提供的令牌(如果已提供), 并拒绝令牌无效的请求。当请求不带有令牌时,默认将接受这些请求。 要拒绝没有令牌的请求,请提供授权规则,该规则指定对特定操作(例如,路径或操作)的限制,即 istio 授权 AuthorizationPolicy CRD
环境准备
创建命名空间 mm-foo,开启 istio sidecar 自动注入
kubectl create ns mm-foo kubectl edit ns mm-foo # 在 label 处添加 "istio-injection: enabled"
创建 httpbin 应用,创建对应的虚拟服务和网关资源
kubectl apply -f httpbin.yaml kubectl apply -f httpbin-gw-vs.yaml
根据 vs 和 gw 配置的域名,修改主机 hosts 文件
验证 httpbin 功能是否正常工作
启用 JWT 验证
创建请求身份验证以启用 JWT 验证
kubectl apply -f requestAuth.yaml
这个请求身份验证将在 Istio 网关上启用 JWT 校验
这个请求身份验证只应用于入口网关
请求身份验证将只检查请求中是否存在 JWT
要使 JWT 成为必要条件, 如果请求中不包含 JWT 的时候就拒绝请求, 请应用任务中指定的授权策略
更新虚拟服务,将需要 JWT 验证的服务更新到路由
kubectl apply -f httpbin-vs.yaml
JWT 功能验证
不携带 jwt 的请求返回
404
[root@node2 ~]# curl -s -I mmjwt.com/headers HTTP/1.1 404 Not Found date: Fri, 05 Jan 2024 01:50:06 GMT server: istio-envoy transfer-encoding: chunked
无效 jwt 的请求返回
401
[root@node2 ~]# curl -s -I mmjwt.com/headers -H "Authorization: Bearer invalid.token" HTTP/1.1 401 Unauthorized www-authenticate: Bearer realm="http://mmjwt.com/headers", error="invalid_token" content-length: 79 content-type: text/plain date: Fri, 05 Jan 2024 01:58:11 GMT server: istio-envoy
有效 jwt 的请求返回
200
这边由于服务器无法访问外网,所以先使用其他机子获取到 tokenubuntu $ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.20/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode { "exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"} ubuntu $ echo $TOKEN_GROUP eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg
再回到环境中携带上面的 token 访问 httpbin 服务
[root@node2 ~]# token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg [root@node2 ~]# curl -s -I mmjwt.com/headers -H "Authorization: Bearer $token" HTTP/1.1 200 OK server: istio-envoy date: Fri, 05 Jan 2024 01:56:52 GMT content-type: application/json content-length: 588 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 7
配置解释
- RequestAuthentication
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.20/security/tools/jwt/samples/jwks.json"
- issuer:jwt 颁发机构
- jwksUri:获取 jwt 的服务地址
- VirtualService
http:
- match:
- uri:
prefix: /headers
headers:
"@request.auth.claims.groups":
exact: group1
- @request.auth.claims.groups:@ 表示与 jwt 数据匹配,而不是 http header 匹配;request.auth.claims 表示的是 jwt 三部分中的载荷,@request.auth.claims.groups 就是校验 jwt 中载荷中的 groups,在这个示例中也可以写成 request.auth.claims.scope。主要看 jwt 载荷中定义了哪些 claims
- exact:表示精确值匹配,在这个示例中表示请求的 jwt 的载荷 groups 必须为 group1
清除
删除部署的相关资源(假设 yaml 文件都在
/root/mm/istio/security
下kubectl delete -f /root/mm/istio/security/
删除命名空间
kubectl delete ns mm-foo