尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

使用 Google 服务账号签发 JWT:Istio 端用户认证测试工具 sa-jwt.py 实战指南

使用 Google 服务账号签发 JWT:Istio 端用户认证测试工具 sa-jwt.py 实战指南 使用 Google 服务账号签发 JWTIstio 端用户认证测试工具 sa-jwt.py 实战指南【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istioIstio 的RequestAuthentication请求认证策略依赖签发方与验签公钥JWKS来验证终端用户携带的 JWT。本指南以仓库中 security/tools/jwt/README.md 为骨架完整讲解其中的sa-jwt.py工具——如何用 Google 服务账号私钥签发结构正确、可被 Istio 校验的 RS256 JWT并深入源码说明其 payload 构造与签名原理同时对比配套的本地私钥签发工具gen-jwt.py帮助你快速获得可用于 Istio 端用户认证测试的合法 Token。工具定位为 Istio 端用户认证造出可信 TokenIstio 的安全模型分两层服务间认证mTLS与端用户认证end-user authentication。后者通过security.istio.io/v1的RequestAuthentication资源声明issuer签发方与jwksUri验签公钥集地址由 istiod 拉取 JWKS 后对到达数据面的Authorization: Bearer JWT请求头做本地验签。要验证这一整套链路前提是手里有一枚由可信签发方私钥签出的 JWT。security/tools/jwt/ 目录正是为此准备的造 Token 工具箱包含两类工具与一套演示数据文件作用sa-jwt.py用Google 服务账号私钥签发 JWT本文主角对应顶层 READMErequirements.txt声明sa-jwt.py的唯一依赖google-authsamples/gen-jwt.py用本地任意 RSA 私钥签发 JWT并可生成配套 JWKSsamples/key.pem / samples/jwks.json演示用私钥与对应公钥集issuer 固定为testingsecure.istio.iosamples/demo.jwt / samples/groups-scope.jwt预签发的可直接使用测试 Token两者覆盖两种典型场景生产/联调中希望以真实 Google 身份体系签发sa-jwt.py本地功能自测中希望用自带私钥快速伪造任意 issuer 的 Tokengen-jwt.py。环境准备安装依赖并取得 Google 服务账号私钥1. 安装 Python 依赖sa-jwt.py基于 Google 官方认证库实现仅依赖一个包。可直接使用仓库中现成的依赖声明文件pip install google-auth或使用仓库内的 requirements.txtpip install -r security/tools/jwt/requirements.txt2. 创建或选用Google 服务账号并下载私钥在 Google Cloud Console 的 IAM 与服务账号页面点击CREATE SERVICE ACCOUNT新建一个服务账号若已存在可复用的服务账号则直接选用在该服务账号的下拉菜单中选择Create Key创建密钥密钥类型选择默认的JSON浏览器会自动下载一份 JSON 格式的服务账号密钥文件内含私钥等敏感材料后续把它作为service_account_file位置参数传给脚本。注意该 JSON 密钥等同于账号私钥请妥善保管切勿提交进代码仓库。sa-jwt.py 用法从帮助输出到参数逐项解读先查看帮助信息确认脚本的完整接口python sa-jwt.py -h输出如下README 中记录的原文注意脚本自带 shebang加执行权限后也可直接用./sa-jwt.pyusage: ./sa-jwt.py [-h] [-iss ISS] [-aud AUD] [-sub SUB] [-claims CLAIMS] service_account_file Python script generates a JWT signed by a Google service account positional arguments: service_account_file The path to your service account key file (in JSON format). optional arguments: -h, --help show this help message and exit -iss ISS, --iss ISS iss claim. This should be your service account email. -aud AUD, --aud AUD aud claim. This is comma-separated-list of audiences. -sub SUB, --sub SUB sub claim. If not provided, it is set to the same as iss claim. -claims CLAIMS, --claims CLAIMS Other claims in format name1:value1,name2:value2 etc. Only string values are supported.对照 sa-jwt.py 的参数解析代码各参数语义如下参数类型语义默认/约束service_account_file必填位置参数Google 服务账号密钥文件路径JSON 格式无缺失即报错-iss/--iss可选JWT 的iss声明应填服务账号邮箱不传则 payload 不含iss同时会导致sub为空-aud/--aud可选JWT 的aud声明逗号分隔表示多个受众含逗号时自动解析为字符串数组见下文-sub/--sub可选JWT 的sub声明不传时自动置为与iss相同-claims/--claims可选追加自定义声明格式name1:value1,name2:value2仅支持字符串值源码拆解sa-jwt.py 内部如何构造与签名阅读 sa-jwt.py 的main()函数可以完整还原其三步工作流第一步从服务账号 JSON 加载 RSA 签名器signer google.auth.crypt.RSASigner.from_service_account_file( args.service_account_file)google.auth.crypt.RSASigner.from_service_account_file会解析下载到的 JSON 密钥中的private_key字段构造 RSA 私钥签名器——这是整个脚本能以Google 服务账号名义签名的关键后续 JWT 将使用该私钥做 RS256 签名。第二步构造 payload内置 iat/exp 与多项默认规则now int(time.time()) payload { # expire in one hour. exp: now 3600, iat: now, } if args.iss: payload[iss] args.iss if args.sub: payload[sub] args.sub else: payload[sub] args.iss if args.aud: if , in args.aud: payload[aud] args.aud.split(,) else: payload[aud] args.aud if args.claims: for item in args.claims.split(,): k, v item.split(:) payload[k] v源码层面体现了几条 README 未展开的硬性规则实测时务必注意iat与exp由脚本自动填充iat为当前 Unix 时间戳exp now 3600即Token 默认有效期仅 1 小时且不可通过命令行覆盖sub的默认行为是跟随iss-sub未指定时payload[sub] args.iss保证声明一致性aud的智能处理单个值存为字符串含逗号时用split(,)转成字符串数组——RFC 7519 允许aud为字符串或字符串数组Istio 验签时按数组逐一比对即可命中-claims的自定义声明仅支持字符串值每个条目按item.split(:)切出键值对直接塞入 payload因此无法通过该参数构造嵌套对象或数字类型。第三步编码并签名输出到标准输出signed_jwt google.auth.jwt.encode(signer, payload) return signed_jwt ... print(main(parser.parse_args()))google.auth.jwt.encode完成 headeralg/typ拼接、payload Base64URL 编码与 RS256 签名最终输出标准三段式 JWT 字符串。脚本末尾通过print()将 Token直接打印到 stdout便于在 shell 中赋值给环境变量或重定向到文件例如./sa-jwt.py /path/to/service_account.json \ -iss frodgserviceaccount.com -aud foo,bar token.jwt动手示例签发一枚可用的 Bearer Token最小可用示例./sa-jwt.py /path/to/service_account.json -iss frodgserviceaccount.com -aud foo,bar执行后 stdout 即输出完整 JWT可立刻用于模拟带认证的请求TOKEN$(./sa-jwt.py /path/to/service_account.json \ -iss frodgserviceaccount.com -aud foo,bar) curl --header Authorization: Bearer $TOKEN http://${INGRESS_HOST}/headers携带自定义声明如需在iss/aud/sub之外追加业务声明例如用于与授权策略request.headers或 JWT claim 条件联动使用-claims./sa-jwt.py /path/to/service_account.json \ -iss frodgserviceaccount.com -aud foo,bar \ -claims key1:value1,key2:value2对应生成的 payload 中会包含{ iss: frodgserviceaccount.com, aud: [foo, bar], sub: frodgserviceaccount.com, key1: value1, key2: value2, iat: 1700000000, exp: 1700003600 }提示若你手头还没有 Google 服务账号只想先在本机跑通 Istio 的 JWT 校验链路可直接使用下一节的本地私钥方案无需访问 Google。姊妹工具gen-jwt.py 与演示数据本地自测首选对于不想依赖 Google 服务账号的本地开发与集成测试仓库在 security/tools/jwt/samples/ 中提供了功能更强的gen-jwt.py它直接用本地 PEM 私钥签名其依赖声明于 samples/requirements.txtpip install jwcryptogen-jwt.py 的能力差异阅读 gen-jwt.py 可见它比sa-jwt.py多出以下参数参数说明key位置参数PEM 格式私钥路径可用openssl genrsa -out key.pem 2048生成-expire过期时间秒默认 36001 小时README 演示中配合-expire3153600000生成长期有效 Token-jwks输出 JWKS 文件路径把公钥导出为 JSON 公钥集-listclaim追加数组型声明格式key val1 val2 ...可多次使用-nestedclaim追加嵌套声明自动包进名为-nestedkey默认nested的嵌套对象且内部会复制一层nested-2用于测试深层嵌套 claim 场景签发时默认 issuer 为testingsecure.istio.io并用kid关联私钥指纹gen-jwt.py与 jwks.json 中导出的公钥一一对应。开箱即用的演示 Tokensamples/README.md 说明仓库已随附一枚签名好的 demo.jwt其 payload 固定为{ exp: 4685989700, foo: bar, iat: 1532389700, iss: testingsecure.istio.io, sub: testingsecure.istio.io }其exp被刻意设到很遥远的未来拿起来即可测试、不会过期例如把内容作为 Bearer Token 直接请求 ingressTOKEN$(cat security/tools/jwt/samples/demo.jwt) curl --header Authorization: Bearer $TOKEN $INGRESS_HOST/headers -s \ -o /dev/null -w %{http_code}\n自行重新生成私钥与演示数据仅供开发者维护数据若需要刷新整套演示密钥/公钥集可参照 samples/README.md 的步骤# 1. 重新生成 2048 位 RSA 私钥 openssl genrsa -out key.pem 2048 # 2. 由私钥导出新 JWKS 并签发新的长期演示 JWT ./gen-jwt.py key.pem -jwks./jwks.json \ --expire3153600000 --claimsfoo:bar demo.jwt在 Istio 中落地RequestAuthentication 与测试链路关联请求认证策略以 samples/README.md 给出的策略为例将 issuer 指向演示数据的固定签发方、jwksUri指向公钥集文件所在地址本地演示时需将 jwks.json 部署到 istiod 可访问的地址apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: jwt-example spec: selector: matchLabels: app: httpbin jwtRules: - issuer: testingsecure.istio.io jwksUri: your-hosted-path-to/jwks.json规则约束了两点恰好对应造 Token 时的参数选择issuer必须与 Token 的iss声明完全一致——这正是sa-jwt.py要求-iss传服务账号邮箱、gen-jwt.py默认固定testingsecure.istio.io的原因验签公钥必须能匹配上签名私钥——所以签发与验签要么走 Google 服务账号体系sa-jwt.py Google JWKS要么走本地私钥体系gen-jwt.py 自导出的-jwks。仓库中的真实验证场景整条链路的正确性在仓库集成测试中被反复验证例如 tests/integration/security/jwt_test.go 与 tests/integration/security/remote_jwks/remote_jwks_test.go 均通过签发合法 Token 后携带Authorization头请求受保护服务来断言 200/403 行为tests/integration/security/ 下的requestauthn模板目录则覆盖了aud、issuer 不匹配等负向用例。若你要在本地复现推荐组合为gen-jwt.py用 samples/key.pem 签发 → 通过 samples/jwks.json 配置jwksUri→ 携带 Token 发起请求观察返回码。常见问题与使用提醒Token 为什么突然失效sa-jwt.py生成的 Tokenexp固定为签发时刻 1 小时且不可调适合短时测试需要长期有效的演示 Token 请改用gen-jwt.py的-expire参数仓库演示数据即采用 3153600000 秒 ≈ 100 年。sub与iss的关系两个脚本都遵循不传-sub则等于iss的默认逻辑若你的授权策略基于sub做用户维度区分务必显式指定。自定义声明只能是字符串-claims走k, v item.split(:)的朴素解析无法表达数字、布尔或嵌套 JSON需要复杂结构时改用gen-jwt.py的-listclaim/-nestedclaim。aud的数组行为传-aud foo,bar时会生成字符串数组[foo,bar]Istio 校验时任一命中即可若只传一个值则保留字符串形式语义等价。私钥安全无论是 Google 服务账号 JSON 密钥还是 key.pem都属于私密材料仅应存在于可信的测试环境。【免费下载链接】istioConnect, secure, control, and observe services.项目地址: https://gitcode.com/GitHub_Trending/is/istio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表