agno AgentOS 怎么签发、使用和吊销机器身份 service accountPAT【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno当 CI、编码代理或聊天应用需要以机器身份调用 agno AgentOS 时需要一种非交互式的凭据。AgentOS 的 service account 就是为这个场景提供的机器身份签发一个不透明的agno_pat_令牌PAT遵循 GitHub PAT 模型数据库只保存它的 SHA-256 哈希明文只会在创建响应中出现一次。本文走通一条完整路径用管理员 JWT 签发 PAT、用它访问受保护路由、列出账户、吊销令牌并验证吊销生效。本地验证路径不需要任何外部凭据只需要一个启用了authorizationTrue的 AgentOS以及数据库支持 service account 存储cookbook 示例使用SqliteDb。准备启用授权并拿到管理员 JWT参照 service_accounts.py 的写法AgentOS 需要开启authorizationTrue并在AuthorizationConfig中提供 JWT 校验密钥OS_ID service-account-security-demo JWT_SECRET os.getenv(JWT_VERIFICATION_KEY, development-secret-at-least-256-bits-long) db SqliteDb(db_filetmp/security_service_accounts.db) agent_os AgentOS( idOS_ID, agents[assistant_agent], dbdb, authorizationTrue, authorization_configAuthorizationConfig( verification_keys[JWT_SECRET], algorithmHS256, verify_audienceTrue, ), ) app agent_os.get_app()签发 PAT 需要一个管理员凭据。示例用jwt库签一枚 HS256 JWT关键 claim 是aud等于 AgentOS 的id因为开启了verify_audienceTrue以及scopes: [agent_os:admin]def make_admin_token() - str: now datetime.now(UTC) return jwt.encode( { sub: security-operator, aud: OS_ID, scopes: [agent_os:admin], iat: now, exp: now timedelta(hours1), }, JWT_SECRET, algorithmHS256, )管理路由的 scope 要求来自 scopes.pyPOST /service-accounts需要service_accounts:writeGET /service-accounts需要service_accounts:readDELETE /service-accounts/*需要service_accounts:deleteagent_os:admin会覆盖这些要求如果你不用 admin就需要在 JWT 里带上对应的service_accounts:*scope。签发 PATPOST /service-accounts服务启动后示例用agent_os.serve(appapp, port7777)因此 REST 基地址是http://localhost:7777用管理员 JWT 调用curl -s -X POST http://localhost:7777/service-accounts \ -H Authorization: Bearer admin JWT \ -H Content-Type: application/json \ -d {name: ci-runner}请求体字段定义见 ServiceAccountCreate字段说明name必填。小写 slug以字母或数字开头后接字母、数字、_或-最长 63 字符如claude-code、github-actionsscopes可选。{scope, effect}对象列表effect只接受allow。不传则使用默认 scopesexpires_in_days可选。默认 90 天范围 1–3650never_expires默认false显式置true可签发不过期令牌会覆盖expires_in_daysallow_privileged_scopes默认false想授予特权 scope 时必须显式置true成功返回 201响应中token字段就是明文 PAT只出现这一次之后无法再取出列表接口只返回token_prefix令牌前 16 个字符供展示永不返回哈希或明文。响应还包含id吊销时要用、principal形如sa:ci-runner即该令牌发起的 run 挂上去的user_id、scopes、expires_at等。拿到明文后立即妥善保存。不传scopes时当前默认 scopes 是agents:run teams:run workflows:run sessions:read config:read其中config:read让默认令牌能调用GET /config发现自己能运行什么。两个签发阶段的限制同名冲突返回 409已存在同名活跃账户时要先吊销再重新签发即把 revoke 当作轮换手段。特权 scope 有双重门槛任何write/delete动作、admin scope 或service_accounts资源的 scope 都算特权必须带allow_privileged_scopestrue且带 scope 的签发者只能授予自己已持有的 scope子集规则admin 调用者不受此限。签发本身还要求真实凭据——匿名调用会收到 401 “JWT authentication is required to mint a service account”。使用 PATBearer 调用受保护路由PAT 与 JWT 走同一套中间件验证通过后请求的user_id被设为账户 principalsa:namescopes设为该账户存储的 scopes。与 JWT 不同service account 的 scopes 是本地 ACL 数据在任何部署模式包括os_security_key模式下都会强制执行。用刚签发的令牌访问/config默认 scopes 里的config:read允许此路由curl -s -o /dev/null -w %{http_code}\n \ http://localhost:7777/config \ -H Authorization: Bearer agno_pat_...返回200说明令牌可用。反过来用 PAT 访问GET /service-accounts会返回403——默认 scopes 不含service_accounts:read这正是示例校验的授权边界机器凭据默认“能运行不能管理”。列出账户GET /service-accounts用管理员 JWT 列出账户并确认新签发的账户在列表中curl -s http://localhost:7777/service-accounts \ -H Authorization: Bearer admin JWT返回分页结构data数组每项含id、name、principal、token_prefix、scopes、created_at、expires_at、last_used_at、revoked_at、created_by、user_id和metapage、limit、total_pages、total_count。支持查询参数include_revoked默认true、limit1–100默认 20、page、sort_by、sort_order。检查点响应data里能找到签发时返回的id。吊销并验证DELETE /service-accounts/{id}curl -s -o /dev/null -w %{http_code}\n -X DELETE \ http://localhost:7777/service-accounts/account_id \ -H Authorization: Bearer admin JWTaccount_id替换为签发响应里的id。成功返回204该操作幂等重复吊销不会报错未知 id 返回 404。带 scope 的调用者无法吊销 workspace 级user_id为null的账户会收到 403。验证吊销生效再用已吊销的 PAT 请求/configcurl -s -o /dev/null -w %{http_code}\n \ http://localhost:7777/config \ -H Authorization: Bearer 已吊销的 agno_pat_...预期返回401。关于生效时机需要理解验证缓存成功的 PAT 验证会在 worker 进程内缓存 30 秒service_account_cache_ttl_seconds默认 30避免每个请求都查库。吊销会立即清除处理该 DELETE 请求的 worker上的缓存条目其他 worker 要等各自缓存过期后才收敛。如果需要每次请求都严格查库严格即时吊销在AgnoAPISettings中设置service_account_cache_ttl_seconds0。注意令牌的过期时间即使在缓存命中时也会被检查不会因缓存而延长有效期。一键验证运行 cookbook 冒烟脚本不需要手工敲上面每个请求时可以直接运行 service_accounts.py.venvs/demo/bin/python cookbook/05_agent_os/07_security/service_accounts.py脚本先在进程内用TestClient跑一遍“签发 → 使用 → 列表 → 吊销 → 重试”的完整冒烟并断言全部通过然后才在 7777 端口起服务。冒烟覆盖的断言签发返回 201 且令牌以agno_pat_开头、scopes 等于默认集合、列表包含新账户、/config返回 200、PAT 访问/service-accounts返回 403、吊销返回 204、吊销后/config返回 401。TEST_LOG.md 记录了该文件 LIVE 模式下的实际运行结果以下属于文档示例输出不是必须逐字复现的固定值Service-account lifecycle smoke passed: {principal: sa:cookbook-xxxxxxxxxx, scopes: [agents:run, teams:run, workflows:run, sessions:read, config:read], listed: True, config_status: 200, management_status: 403, revoke_status: 204, revoked_status: 401}起服务后还可以直接浏览/docs查看 Service Accounts 路由的 OpenAPI 文档。排查与限制401 “Invalid or expired service account token”令牌未知、已吊销或已过期。吊销在缓存 TTL 内对非处理 worker 可能尚未收敛稍后重试即可。429 “Too many failed authentication attempts”同一客户端地址在 60 秒窗口内失败查找超过 20 次时失败响应会被限流只限流失败响应有效令牌永远不会被限流挡住。该限制按客户端地址计在代理后面运行时只有启用 proxy headers如uvicorn --proxy-headers才有意义。503 “Authentication is temporarily unavailable”数据库无法连接或不支持 service account例如配置了不支持该存储的数据库接口返回 “Service accounts not supported by the configured database”。令牌泄漏时的处理方式就是吊销因为明文无法找回也无法“改密”只能DELETE原账户再以同名重新签发409 提示的 “Revoke it first to rotate” 就是这个流程。参考完整示例代码cookbook/05_agent_os/07_security/service_accounts.py安全课节说明scopes 词汇表、audience 验证、用户隔离cookbook/05_agent_os/07_security/README.md路由实现与状态码细节libs/agno/agno/os/routers/service_accounts/router.py令牌生成、哈希存储与验证缓存libs/agno/agno/os/service_accounts.py请求/响应模型libs/agno/agno/os/routers/service_accounts/schema.py【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考