@m1a0rz/agent-identity 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README-cn.md +223 -0
  2. package/README.md +223 -0
  3. package/dist/index.d.ts +14 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +306 -0
  6. package/dist/src/actions/identity-actions.d.ts +142 -0
  7. package/dist/src/actions/identity-actions.d.ts.map +1 -0
  8. package/dist/src/actions/identity-actions.js +429 -0
  9. package/dist/src/commands/identity-commands.d.ts +33 -0
  10. package/dist/src/commands/identity-commands.d.ts.map +1 -0
  11. package/dist/src/commands/identity-commands.js +572 -0
  12. package/dist/src/hooks/after-tool-call.d.ts +22 -0
  13. package/dist/src/hooks/after-tool-call.d.ts.map +1 -0
  14. package/dist/src/hooks/after-tool-call.js +35 -0
  15. package/dist/src/hooks/before-agent-start.d.ts +30 -0
  16. package/dist/src/hooks/before-agent-start.d.ts.map +1 -0
  17. package/dist/src/hooks/before-agent-start.js +93 -0
  18. package/dist/src/hooks/before-tool-call.d.ts +38 -0
  19. package/dist/src/hooks/before-tool-call.d.ts.map +1 -0
  20. package/dist/src/hooks/before-tool-call.js +138 -0
  21. package/dist/src/risk/classify-risk.d.ts +24 -0
  22. package/dist/src/risk/classify-risk.d.ts.map +1 -0
  23. package/dist/src/risk/classify-risk.js +61 -0
  24. package/dist/src/risk/diagnose-risk.d.ts +21 -0
  25. package/dist/src/risk/diagnose-risk.d.ts.map +1 -0
  26. package/dist/src/risk/diagnose-risk.js +37 -0
  27. package/dist/src/risk/llm-risk-check.d.ts +27 -0
  28. package/dist/src/risk/llm-risk-check.d.ts.map +1 -0
  29. package/dist/src/risk/llm-risk-check.js +274 -0
  30. package/dist/src/risk/low-risk-tools.d.ts +5 -0
  31. package/dist/src/risk/low-risk-tools.d.ts.map +1 -0
  32. package/dist/src/risk/low-risk-tools.js +29 -0
  33. package/dist/src/routes/oidc-login.d.ts +51 -0
  34. package/dist/src/routes/oidc-login.d.ts.map +1 -0
  35. package/dist/src/routes/oidc-login.js +153 -0
  36. package/dist/src/services/identity-client.d.ts +366 -0
  37. package/dist/src/services/identity-client.d.ts.map +1 -0
  38. package/dist/src/services/identity-client.js +578 -0
  39. package/dist/src/services/identity-credentials.d.ts +28 -0
  40. package/dist/src/services/identity-credentials.d.ts.map +1 -0
  41. package/dist/src/services/identity-credentials.js +170 -0
  42. package/dist/src/services/identity-service.d.ts +33 -0
  43. package/dist/src/services/identity-service.d.ts.map +1 -0
  44. package/dist/src/services/identity-service.js +53 -0
  45. package/dist/src/services/oidc-client.d.ts +57 -0
  46. package/dist/src/services/oidc-client.d.ts.map +1 -0
  47. package/dist/src/services/oidc-client.js +127 -0
  48. package/dist/src/services/send-notification-feishu.d.ts +27 -0
  49. package/dist/src/services/send-notification-feishu.d.ts.map +1 -0
  50. package/dist/src/services/send-notification-feishu.js +148 -0
  51. package/dist/src/services/session-refresh.d.ts +16 -0
  52. package/dist/src/services/session-refresh.d.ts.map +1 -0
  53. package/dist/src/services/session-refresh.js +38 -0
  54. package/dist/src/store/credential-env-bindings.d.ts +16 -0
  55. package/dist/src/store/credential-env-bindings.d.ts.map +1 -0
  56. package/dist/src/store/credential-env-bindings.js +61 -0
  57. package/dist/src/store/credential-store.d.ts +31 -0
  58. package/dist/src/store/credential-store.d.ts.map +1 -0
  59. package/dist/src/store/credential-store.js +57 -0
  60. package/dist/src/store/oidc-state-store.d.ts +15 -0
  61. package/dist/src/store/oidc-state-store.d.ts.map +1 -0
  62. package/dist/src/store/oidc-state-store.js +32 -0
  63. package/dist/src/store/session-store.d.ts +21 -0
  64. package/dist/src/store/session-store.d.ts.map +1 -0
  65. package/dist/src/store/session-store.js +69 -0
  66. package/dist/src/store/tip-store.d.ts +21 -0
  67. package/dist/src/store/tip-store.d.ts.map +1 -0
  68. package/dist/src/store/tip-store.js +60 -0
  69. package/dist/src/store/tool-approval-store.d.ts +44 -0
  70. package/dist/src/store/tool-approval-store.d.ts.map +1 -0
  71. package/dist/src/store/tool-approval-store.js +147 -0
  72. package/dist/src/tools/identity-approve-tool.d.ts +24 -0
  73. package/dist/src/tools/identity-approve-tool.d.ts.map +1 -0
  74. package/dist/src/tools/identity-approve-tool.js +36 -0
  75. package/dist/src/tools/identity-config.d.ts +13 -0
  76. package/dist/src/tools/identity-config.d.ts.map +1 -0
  77. package/dist/src/tools/identity-config.js +18 -0
  78. package/dist/src/tools/identity-fetch.d.ts +21 -0
  79. package/dist/src/tools/identity-fetch.d.ts.map +1 -0
  80. package/dist/src/tools/identity-fetch.js +63 -0
  81. package/dist/src/tools/identity-list-credentials.d.ts +15 -0
  82. package/dist/src/tools/identity-list-credentials.d.ts.map +1 -0
  83. package/dist/src/tools/identity-list-credentials.js +30 -0
  84. package/dist/src/tools/identity-list-risk-patterns.d.ts +13 -0
  85. package/dist/src/tools/identity-list-risk-patterns.d.ts.map +1 -0
  86. package/dist/src/tools/identity-list-risk-patterns.js +23 -0
  87. package/dist/src/tools/identity-list-tips.d.ts +13 -0
  88. package/dist/src/tools/identity-list-tips.d.ts.map +1 -0
  89. package/dist/src/tools/identity-list-tips.js +21 -0
  90. package/dist/src/tools/identity-login.d.ts +14 -0
  91. package/dist/src/tools/identity-login.d.ts.map +1 -0
  92. package/dist/src/tools/identity-login.js +40 -0
  93. package/dist/src/tools/identity-logout.d.ts +13 -0
  94. package/dist/src/tools/identity-logout.d.ts.map +1 -0
  95. package/dist/src/tools/identity-logout.js +24 -0
  96. package/dist/src/tools/identity-risk-check.d.ts +29 -0
  97. package/dist/src/tools/identity-risk-check.d.ts.map +1 -0
  98. package/dist/src/tools/identity-risk-check.js +54 -0
  99. package/dist/src/tools/identity-set-binding.d.ts +16 -0
  100. package/dist/src/tools/identity-set-binding.d.ts.map +1 -0
  101. package/dist/src/tools/identity-set-binding.js +31 -0
  102. package/dist/src/tools/identity-status.d.ts +13 -0
  103. package/dist/src/tools/identity-status.d.ts.map +1 -0
  104. package/dist/src/tools/identity-status.js +41 -0
  105. package/dist/src/tools/identity-unset-binding.d.ts +15 -0
  106. package/dist/src/tools/identity-unset-binding.d.ts.map +1 -0
  107. package/dist/src/tools/identity-unset-binding.js +25 -0
  108. package/dist/src/tools/identity-whoami.d.ts +13 -0
  109. package/dist/src/tools/identity-whoami.d.ts.map +1 -0
  110. package/dist/src/tools/identity-whoami.js +38 -0
  111. package/dist/src/types.d.ts +93 -0
  112. package/dist/src/types.d.ts.map +1 -0
  113. package/dist/src/types.js +5 -0
  114. package/dist/src/utils/approval-channel.d.ts +11 -0
  115. package/dist/src/utils/approval-channel.d.ts.map +1 -0
  116. package/dist/src/utils/approval-channel.js +13 -0
  117. package/dist/src/utils/auth.d.ts +24 -0
  118. package/dist/src/utils/auth.d.ts.map +1 -0
  119. package/dist/src/utils/auth.js +44 -0
  120. package/dist/src/utils/derive-session-key.d.ts +78 -0
  121. package/dist/src/utils/derive-session-key.d.ts.map +1 -0
  122. package/dist/src/utils/derive-session-key.js +198 -0
  123. package/openclaw.plugin.json +162 -0
  124. package/package.json +33 -0
  125. package/skills/SKILL.md +230 -0
package/README-cn.md ADDED
@@ -0,0 +1,223 @@
1
+ # Agent Identity 插件
2
+
3
+ UserPool OIDC 登录、TIP (Trusted Identity Provider) 令牌(通过 Identity GetWorkloadAccessTokenForJWT 获取)、凭据 3LO(GetResourceOauth2Token/Oauth2Callback)以及 OpenClaw 的会话管理。
4
+
5
+ 集成 [火山引擎智能体身份和权限管理平台](https://www.volcengine.com/docs/86848)。术语映射:用户池 (UserPool)、入站授权 (OIDC login)、出站授权 (credential fetch)、工作负载令牌 (TIP)、凭据托管 (credential hosting)、权限管控 (CheckPermission)。
6
+
7
+ > For English documentation, see [README.md](README.md)
8
+
9
+ ## 功能特性
10
+
11
+ - **OIDC 登录**:`/identity login` 返回 IdP 授权 URL。用户打开 URL 后,IdP 重定向到 `/identity/oauth/callback`。
12
+ - **TIP 令牌**:当会话中有已登录用户时,`before_agent_start` 钩子会获取 TIP 令牌。
13
+ - **凭据 3LO**:`/identity fetch <provider>` 返回授权 URL。IdP 重定向到 Identity 提供的回调地址(控制台配置)。
14
+ - **凭据绑定**:`/identity set <provider> <envVar>` 将存储的凭据绑定到环境变量。工具运行时在 `before_agent_start` 中注入到 `process.env`。
15
+ - **动态 UserPool**:通过 `userPoolName` + `clientName` 解析 OIDC 配置(无需手动配置 clientId)。
16
+ - **凭证加载**:从环境变量、文件或 STS AssumeRole 加载 AK/SK(veadk 风格)。
17
+
18
+ ## HTTP 端点
19
+
20
+ 仅暴露 OIDC 登录回调。凭据 OAuth 使用 Identity 回调。其余逻辑在 slash 命令中执行。
21
+
22
+ | 路径 | 方法 | 描述 |
23
+ | -------------------------- | ---- | ------------------------- |
24
+ | `/identity/oauth/callback` | GET | OIDC 登录回调(IdP 重定向到此) |
25
+
26
+ ## Slash 命令
27
+
28
+ 单一命令 `/identity`(别名 `/id`)及其子命令。无参数时默认:`status`。
29
+
30
+ | 子命令 | 描述 |
31
+ | ------------------------------- | -------------------------------------------------------------------- |
32
+ | _(无)_ | 显示帮助。 |
33
+ | `whoami` | 显示当前会话身份(sub、TIP 状态)。 |
34
+ | `login` | 已登录:刷新 TIP。未登录:返回需打开的 OIDC IdP URL。 |
35
+ | `status` | 登录状态、TIP、凭据。会话存在时尝试刷新 TIP。 |
36
+ | `logout` | 清除当前会话的 session 和 TIP。 |
37
+ | `list-tips` | 列出所有有效 TIP 令牌及其委托链、过期时间和环境变量绑定。 |
38
+ | `config` | 显示 identity 插件配置(敏感信息脱敏)。 |
39
+ | `list-credentials` 或 `list [page]` | 分页列出控制台 provider 及已绑定的凭据。使用 `list 2` 加载更多。 |
40
+ | `fetch <provider> [--flow=...]` | 添加凭据。flow 根据 provider 类型自动推断;可用 `--flow` 覆盖。 |
41
+ | `set <provider> <envVar>` | 将凭据绑定到环境变量供工具注入。无凭据时从 `process.env[envVar]` 导入。 |
42
+ | `unset <provider>` | 移除 provider 的环境变量绑定。 |
43
+ | `approve <approval_id>` | 审批待处理的高风险工具调用。 |
44
+ | `reject <approval_id>` | 拒绝待处理的高风险工具调用。 |
45
+
46
+ ## OIDC 登录流程
47
+
48
+ 1. 用户在聊天中发送 `/identity login`(如 Telegram、Discord)
49
+ 2. 命令根据 channel/sender 推导 sessionKey,构建 IdP 授权 URL,保存 state
50
+ 3. 命令返回 IdP URL,用户在浏览器中打开
51
+ 4. 用户在 UserPool IdP 完成登录
52
+ 5. IdP 携带 `code` 和 `state` 重定向到 `/identity/oauth/callback`
53
+ 6. 插件交换 code,创建会话,显示成功页并向聊天发送消息
54
+
55
+ ## 凭据获取流程
56
+
57
+ **OAuth2(用户联邦或 M2M):**
58
+
59
+ 1. 用户发送 `/identity fetch google` 或 `/identity fetch google --flow=oauth2-m2m`(在 `/identity login` 之后)
60
+ 2. 命令使用 TIP 调用 Identity API,返回授权 URL 或直接返回 token
61
+ 3. 若有授权 URL:用户打开,IdP 重定向到 Identity 回调(控制台 provider 配置)
62
+ 4. Identity 处理回调,获取 token;用户可再次执行 fetch 拉取凭据
63
+
64
+ **API Key:**
65
+
66
+ 1. 用户发送 `/identity fetch openai`(控制台 provider 类型为 api_key)或 `/identity fetch openai --flow=apikey`
67
+ 2. 命令使用 TIP 调用 GetResourceApiKey,直接存储 API key
68
+
69
+ flow 根据 ListCredentialProviders 的 Type 和 Flow 自动推断。可通过 `--flow=oauth2-user|oauth2-m2m|apikey` 覆盖。
70
+
71
+ ## 开通火山引擎 Agent Identity 服务
72
+
73
+ 使用本插件前,需先在火山引擎开通 **智能体身份和权限管理平台** 并完成授权。详见:
74
+
75
+ - [开通智能体身份和权限管理平台并完成授权](https://www.volcengine.com/docs/86848/2123358?lang=zh)
76
+
77
+ ## 获取火山引擎 AK/SK
78
+
79
+ 插件调用 Identity API 需要火山引擎访问密钥(Access Key / Secret Key)。获取方式:
80
+
81
+ - [创建 Access Key - 火山引擎文档](https://www.volcengine.com/docs/6291/65568?lang=zh)
82
+
83
+ 在控制台创建 AK/SK 后,可通过配置传入,或使用环境变量 `VOLCENGINE_ACCESS_KEY`、`VOLCENGINE_SECRET_KEY`。
84
+
85
+ ## 安装
86
+
87
+ ```bash
88
+ openclaw plugins install @m1a0rz/agent-identity
89
+ ```
90
+
91
+ 开发模式(link):
92
+
93
+ ```bash
94
+ openclaw plugins install --link .
95
+ ```
96
+
97
+ ## 配置
98
+
99
+ 在 `openclaw.json` 的 `plugins.entries.agent-identity.config` 下添加:
100
+
101
+ ```json
102
+ {
103
+ "plugins": {
104
+ "entries": {
105
+ "agent-identity": {
106
+ "config": {
107
+ "identity": {
108
+ "endpoint": "https://id.cn-beijing.volcengineapi.com",
109
+ "accessKeyId": "<your-ak>",
110
+ "secretAccessKey": "<your-sk>",
111
+ "workloadPoolName": "default",
112
+ "workloadName": "openclaw-agent",
113
+ "audience": ["asi-gateway"],
114
+ "durationSeconds": 3600
115
+ },
116
+ "userpool": {
117
+ "discoveryUrl": "https://userpool-xxx.userpool.auth.id.cn-beijing.volces.com",
118
+ "clientId": "<client-id>",
119
+ "clientSecret": "<client-secret>",
120
+ "callbackUrl": "https://gateway.example.com/identity/oauth/callback",
121
+ "scope": "openid profile email"
122
+ },
123
+ "authz": {
124
+ "enable": false,
125
+ "namespaceName": "default",
126
+ "enableLlmRiskCheck": false,
127
+ "llmRiskCheck": {
128
+ "endpoint": "http://localhost:11434",
129
+ "api": "ollama",
130
+ "model": "qwen3:8b"
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ ### identity 配置(必填与可选)
141
+
142
+ | 参数 | 类型 | 必填 | 含义 |
143
+ |------|------|------|------|
144
+ | `endpoint` | string | 是 | Identity API 地址,如 `https://id.cn-beijing.volcengineapi.com` |
145
+ | `accessKeyId` | string | 否* | 火山引擎 Access Key。不填时从 `VOLCENGINE_ACCESS_KEY` 或 `credentialsFile` 读取 |
146
+ | `secretAccessKey` | string | 否* | 火山引擎 Secret Key。不填时从 `VOLCENGINE_SECRET_KEY` 或 `credentialsFile` 读取 |
147
+ | `workloadPoolName` | string | 否 | 工作负载池名称,默认 `default` |
148
+ | `workloadName` | string | 否 | 工作负载名称。不填时用 agentId 或 `openclaw-agent` |
149
+ | `audience` | string[] | 否 | TIP token 的 audience |
150
+ | `durationSeconds` | number | 否 | TIP token 有效期(秒),默认 3600 |
151
+ | `roleTrn` | string | 否 | STS AssumeRole 的 Role TRN。设置后不传 workload name,后端使用 roleName |
152
+ | `credentialsFile` | string | 否 | 凭证 JSON 文件路径。默认 `VOLCENGINE_CREDENTIALS_FILE` 或 `/var/run/secrets/iam/credential` |
153
+ | `sessionToken` | string | 否 | STS 临时会话令牌(或 `VOLCENGINE_SESSION_TOKEN`) |
154
+
155
+ \* AK/SK 至少通过 `accessKeyId`+`secretAccessKey`、环境变量或 `credentialsFile` 之一提供。
156
+
157
+ ### userpool 配置(OIDC 登录)
158
+
159
+ **Explicit 模式**(必填):`discoveryUrl`、`clientId`、`clientSecret`、`callbackUrl`、`scope`
160
+
161
+ **Dynamic 模式**(必填):`userPoolName`、`clientName`、`callbackUrl`;`autoCreate` 默认 true
162
+
163
+ OAuth2 credential fetch 使用控制台配置的 redirect URL 和 scopes。可通过 `/identity fetch <provider> --redirectUrl` 和 `--scopes` 覆盖。
164
+
165
+ ### authz 配置(可选,默认关闭)
166
+
167
+ | 参数 | 类型 | 含义 |
168
+ |------|------|------|
169
+ | `enable` | boolean | 是否启用 TIP + CheckPermission + 风险审批,默认 false |
170
+ | `namespaceName` | string | CheckPermission 命名空间,默认 `default` |
171
+ | `requireRiskApproval` | boolean | 高风险工具调用需用户审批,默认 true |
172
+ | `enableLlmRiskCheck` | boolean | 规则返回 medium 时用 LLM 二次评估,默认 false |
173
+ | `llmRiskCheck` | object | LLM 配置:`endpoint`、`api`、`model` 等 |
174
+
175
+ ### 工作负载与 TIP
176
+
177
+ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
178
+
179
+ - **workloadName**(可选):发送给 API 的工作负载名称。默认:会话中的 `agentId` 或 `"openclaw-agent"`。仅在不使用 `roleTrn` 时生效。
180
+ - **roleTrn**(可选):设置后(AssumeRole),插件**不**传递 workload name,后端使用 roleName。用于委托执行(如 VeFaaS、K8s IRSA)。
181
+ - **自动创建工作负载**:当 `GetWorkloadAccessTokenForJWT` 返回 404(工作负载不存在)时,插件调用 `CreateWorkloadIdentity` 创建工作负载(Category: Agent),然后重试。仅在使用 workload name 时生效(未设置 `roleTrn`)。并发创建产生的 Duplicated (409) 会被忽略。
182
+
183
+ ### 飞书通知
184
+
185
+ 当用户从飞书聊天运行 `/identity` 时,登录成功和凭据获取的跟进消息会通过飞书发送。凭据从 openclaw.json 的 `channels.feishu` 读取(与 feishu 扩展相同:`appId`、`appSecret`,可选 `accounts`)。agent-identity 无需额外配置。
186
+
187
+ **审批消息**(当高风险工具被拦截时):若要向飞书(或 Telegram、Slack 等)推送审批请求,请在 openclaw.json 中将 `session.dmScope` 设置为 `per-channel-peer` 或 `per-account-channel-peer`。默认 `session.dmScope: "main"` 时,sessionKey 不包含 channel/peer 信息,插件无法推导推送目标,审批消息不会推送。用户仍可在 agent 的错误回复中看到 block/approval_id;使用 `/identity approve <id>` 审批。
188
+
189
+ ### WebChat / TUI
190
+
191
+ 用户从 WebChat 或 TUI 运行 `/identity` 时,跟进消息不会投递;插件无 API 推送至这些渠道。请使用 `/identity status` 确认结果。
192
+
193
+ ## 工具
194
+
195
+ - **identity_whoami** - 显示当前会话身份(sub、TIP 状态)
196
+ - **identity_status** - 登录状态、凭据、绑定
197
+ - **identity_login** - 启动 OIDC 登录或刷新 TIP
198
+ - **identity_logout** - 清除 session 和 TIP
199
+ - **identity_list_credentials** - 列出 provider 和凭据(分页)
200
+ - **identity_list_tips** - 列出有效 TIP 令牌和绑定
201
+ - **identity_config** - 显示插件配置(脱敏)
202
+ - **identity_fetch** - 添加凭据(provider、flow?、redirectUrl?、scopes?)
203
+ - **identity_set_binding** - 绑定 provider → 环境变量
204
+ - **identity_unset_binding** - 移除环境变量绑定
205
+ - **identity_approve_tool** - 可选工具;按 approval_id 审批高风险工具调用。推荐用户使用 `/identity approve <id>`(仅人工;agent 不得自批)。
206
+ - **identity_risk_check** - 诊断命令或工具调用的风险(command 或 toolName+params)
207
+ - **identity_list_risk_patterns** - 列出内置危险命令和敏感路径
208
+
209
+ ## 钩子
210
+
211
+ - **before_agent_start** - 获取 TIP token;按 credential-env-bindings(按 session)将凭据注入到 `process.env`
212
+ - **after_tool_call** - 在 `sessions_spawn` 时将 TIP 传播到子会话
213
+ - **before_tool_call** - 当 authz.enable 时可选 AuthZ(TIP + CheckPermission + 风险审批)。评估用户提供的命令/路径风险(规则 + 可选 LLM)。高风险调用需审批;LLM 风险原因会出现在审批提示和拦截消息中。
214
+
215
+ ## 数据存储
216
+
217
+ 插件数据位于 `~/.openclaw/plugins/identity/`:
218
+
219
+ - `sessions.json` - sessionKey → userToken 映射(加载/保存时清理过期)
220
+ - `tip-tokens.json` - sessionKey → TIP token 缓存(加载/保存时清理过期)
221
+ - Credentials - 仅内存,按 session(api_key、oauth2);gateway 重启后丢失;logout 时清除
222
+ - `credential-env-bindings.json` - 按 session:`{ [sessionKey]: { [provider]: envVar } }`
223
+ - OIDC state - 仅内存(临时,5 分钟 TTL)
package/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # Agent Identity Plugin
2
+
3
+ UserPool OIDC login, TIP (Trusted Identity Provider) token via Identity GetWorkloadAccessTokenForJWT, credential 3LO (GetResourceOauth2Token/Oauth2Callback), and session management for OpenClaw.
4
+
5
+ > 中文文档请参阅 [README-cn.md](README-cn.md)
6
+
7
+ Integrates with [Volcengine Agent Identity and Permission Management](https://www.volcengine.com/docs/86848).
8
+
9
+ ## Features
10
+
11
+ - **OIDC Login**: `/identity login` returns IdP auth URL (no HTTP start endpoint). User opens URL, IdP redirects to `/identity/oauth/callback`.
12
+ - **TIP Token**: `before_agent_start` hook fetches TIP token when session has a logged-in user
13
+ - **Credential 3LO**: `/identity fetch <provider>` returns auth URL. IdP redirects to Identity-provided callback (control-plane config).
14
+ - **Credential Binding**: `/identity set <provider> <envVar>` binds stored credential to env var. Credentials are injected into `process.env` in `before_agent_start` when tools run.
15
+ - **Dynamic UserPool**: Resolve OIDC config by `userPoolName` + `clientName` (no manual clientId)
16
+ - **Credentials**: Load AK/SK from env, file, or STS AssumeRole (veadk-style)
17
+
18
+ ## HTTP Endpoints
19
+
20
+ Only the OIDC login callback is exposed. Credential OAuth uses Identity callback. All other logic runs in slash commands.
21
+
22
+ | Path | Method | Description |
23
+ | -------------------------- | ------ | ---------------------------------------- |
24
+ | `/identity/oauth/callback` | GET | OIDC login callback (IdP redirects here) |
25
+
26
+ ## Slash Commands
27
+
28
+ Single command `/identity` (alias `/id`) with subcommands. Default with no args: `status`.
29
+
30
+ | Subcommand | Description |
31
+ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------- |
32
+ | _(none)_ | Show help. |
33
+ | `whoami` | Show current session identity (sub, TIP status). |
34
+ | `login` | If logged in: refresh TIP. If not: return OIDC IdP URL to open. |
35
+ | `status` | Show login status, TIP, credentials. Tries to refresh TIP when session exists. |
36
+ | `logout` | Clear session and TIP for current session. |
37
+ | `list-tips` | List all valid TIP tokens with delegation chain, expiry, and env bindings. |
38
+ | `config` | Show identity plugin config (sensitive values redacted). |
39
+ | `list-credentials` or `list [page]` | List providers from control plane (paginated) and your credentials with bound env. Use `list 2` to load more. |
40
+ | `fetch <provider> [--flow=...]` | Add credential. Flow auto-inferred from provider type (api_key/oauth2/m2m); override with `--flow`. |
41
+ | `set <provider> <envVar>` | Bind credential to env var for tool injection. If no credential, import from `process.env[envVar]`. |
42
+ | `unset <provider>` | Remove env binding for provider. |
43
+ | `approve <approval_id>` | Approve a pending high-risk tool call. |
44
+ | `reject <approval_id>` | Reject a pending high-risk tool call. |
45
+
46
+ ## OIDC Login Flow
47
+
48
+ 1. User sends `/identity login` in chat (e.g. Telegram, Discord)
49
+ 2. Command derives sessionKey from channel/sender, builds IdP authorize URL, stores state
50
+ 3. Command returns the IdP URL; user opens it in browser
51
+ 4. User completes login at UserPool IdP
52
+ 5. IdP redirects to `/identity/oauth/callback` with `code` and `state`
53
+ 6. Plugin exchanges code, creates session, shows success page and sends message to chat
54
+
55
+ ## Credential Fetch Flow
56
+
57
+ **OAuth2 (user federation or M2M):**
58
+
59
+ 1. User sends `/identity fetch google` or `/identity fetch google --flow=oauth2-m2m` (after `/identity login`)
60
+ 2. Command uses TIP to call Identity API; returns auth URL or direct token
61
+ 3. If auth URL: user opens it; IdP redirects to Identity callback (control-plane provider config)
62
+ 4. Identity handles callback; token obtained via Identity; user may re-run fetch to pull credential
63
+
64
+ **API Key:**
65
+
66
+ 1. User sends `/identity fetch openai` (provider type api_key in control plane) or `/identity fetch openai --flow=apikey`
67
+ 2. Command uses TIP to call GetResourceApiKey; API key stored directly
68
+
69
+ Flow is auto-inferred from ListCredentialProviders (Type + Flow). Override with `--flow=oauth2-user|oauth2-m2m|apikey` when needed.
70
+
71
+ ## Enable Volcengine Agent Identity Service
72
+
73
+ Before using this plugin, you must enable **Agent Identity and Permission Management** in Volcengine and complete authorization. See:
74
+
75
+ - [Enable Agent Identity Service (Chinese)](https://www.volcengine.com/docs/86848/2123358?lang=zh)
76
+
77
+ ## Get Volcengine AK/SK
78
+
79
+ The plugin requires Volcengine Access Key and Secret Key to call the Identity API. To create credentials:
80
+
81
+ - [Create Access Key - Volcengine Docs](https://www.volcengine.com/docs/6291/65568?lang=zh)
82
+
83
+ After creating AK/SK in the console, pass them via config or use environment variables `VOLCENGINE_ACCESS_KEY` and `VOLCENGINE_SECRET_KEY`.
84
+
85
+ ## Installation
86
+
87
+ ```bash
88
+ openclaw plugins install @m1a0rz/agent-identity
89
+ ```
90
+
91
+ Or with link for development:
92
+
93
+ ```bash
94
+ openclaw plugins install --link .
95
+ ```
96
+
97
+ ## Configuration
98
+
99
+ Add to `openclaw.json` under `plugins.entries.agent-identity.config`:
100
+
101
+ ```json
102
+ {
103
+ "plugins": {
104
+ "entries": {
105
+ "agent-identity": {
106
+ "config": {
107
+ "identity": {
108
+ "endpoint": "https://id.cn-beijing.volcengineapi.com",
109
+ "accessKeyId": "<your-ak>",
110
+ "secretAccessKey": "<your-sk>",
111
+ "workloadPoolName": "default",
112
+ "workloadName": "openclaw-agent",
113
+ "audience": ["asi-gateway"],
114
+ "durationSeconds": 3600
115
+ },
116
+ "userpool": {
117
+ "discoveryUrl": "https://userpool-xxx.userpool.auth.id.cn-beijing.volces.com",
118
+ "clientId": "<client-id>",
119
+ "clientSecret": "<client-secret>",
120
+ "callbackUrl": "https://gateway.example.com/identity/oauth/callback",
121
+ "scope": "openid profile email"
122
+ },
123
+ "authz": {
124
+ "enable": false,
125
+ "namespaceName": "default",
126
+ "enableLlmRiskCheck": false,
127
+ "llmRiskCheck": {
128
+ "endpoint": "http://localhost:11434",
129
+ "api": "ollama",
130
+ "model": "qwen3:8b"
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ ### identity config (required vs optional)
141
+
142
+ | Param | Type | Required | Description |
143
+ |-------|------|----------|--------------|
144
+ | `endpoint` | string | Yes | Identity API URL, e.g. `https://id.cn-beijing.volcengineapi.com` |
145
+ | `accessKeyId` | string | No* | Volcengine Access Key. Omit to load from `VOLCENGINE_ACCESS_KEY` or `credentialsFile` |
146
+ | `secretAccessKey` | string | No* | Volcengine Secret Key. Omit to load from `VOLCENGINE_SECRET_KEY` or `credentialsFile` |
147
+ | `workloadPoolName` | string | No | Workload pool name, default `default` |
148
+ | `workloadName` | string | No | Workload name. Default: agentId or `openclaw-agent` |
149
+ | `audience` | string[] | No | TIP token audience |
150
+ | `durationSeconds` | number | No | TIP token TTL (seconds), default 3600 |
151
+ | `roleTrn` | string | No | Role TRN for STS AssumeRole. When set, workload name is omitted; backend uses roleName |
152
+ | `credentialsFile` | string | No | Path to credential JSON. Default: `VOLCENGINE_CREDENTIALS_FILE` or `/var/run/secrets/iam/credential` |
153
+ | `sessionToken` | string | No | STS session token (or `VOLCENGINE_SESSION_TOKEN`) |
154
+
155
+ \* AK/SK must be provided via `accessKeyId`+`secretAccessKey`, environment variables, or `credentialsFile`.
156
+
157
+ ### userpool config (OIDC login)
158
+
159
+ **Explicit mode** (required): `discoveryUrl`, `clientId`, `clientSecret`, `callbackUrl`, `scope`
160
+
161
+ **Dynamic mode** (required): `userPoolName`, `clientName`, `callbackUrl`; `autoCreate` defaults to true
162
+
163
+ OAuth2 credential fetch uses control-plane redirect URL and scopes. Override via `/identity fetch <provider> --redirectUrl` and `--scopes`.
164
+
165
+ ### authz config (optional, disabled by default)
166
+
167
+ | Param | Type | Description |
168
+ |-------|------|-------------|
169
+ | `enable` | boolean | Enable TIP + CheckPermission + risk approval, default false |
170
+ | `namespaceName` | string | CheckPermission namespace, default `default` |
171
+ | `requireRiskApproval` | boolean | Require user approval for high-risk tools, default true |
172
+ | `enableLlmRiskCheck` | boolean | Re-evaluate with LLM when rules return medium, default false |
173
+ | `llmRiskCheck` | object | LLM config: `endpoint`, `api`, `model`, etc. |
174
+
175
+ ### Workload and TIP
176
+
177
+ TIP token is obtained via `GetWorkloadAccessTokenForJWT`. Workload behavior:
178
+
179
+ - **workloadName** (optional): Workload name sent to the API. Default: `agentId` from session, or `"openclaw-agent"`. Used only when not using `roleTrn`.
180
+ - **roleTrn** (optional): When set (AssumeRole), the plugin does **not** pass workload name; the backend uses the role name. Use this for delegated execution (e.g. VeFaaS, K8s IRSA).
181
+ - **Auto-create workload**: When `GetWorkloadAccessTokenForJWT` returns 404 (workload not found), the plugin calls `CreateWorkloadIdentity` to create the workload (Category: Agent), then retries. Only applies when a workload name is used (no `roleTrn`). Duplicated (409) from concurrent create is ignored.
182
+
183
+ ### Feishu notifications
184
+
185
+ Login success and credential fetch follow-up messages (e.g. "✓ Credential for `google` added.") are sent via Feishu when the user runs `/identity` from a Feishu chat. Credentials are read from `channels.feishu` in openclaw.json (same as feishu extension: `appId`, `appSecret`, optional `accounts`). No extra config in agent-identity is required.
186
+
187
+ **Approval messages** (when a high-risk tool is blocked): For approval requests to be delivered to Feishu (or Telegram, Slack, etc.), set `session.dmScope` to `per-channel-peer` or `per-account-channel-peer` in openclaw.json. With default `session.dmScope: "main"`, the sessionKey does not include channel/peer info, so the plugin cannot derive a delivery target and approval messages are not pushed. The user will still see the block/approval_id in the agent's error reply; use `/identity approve <id>` to approve.
188
+
189
+ ### WebChat / TUI
190
+
191
+ Follow-up messages (login success, credential fetch done) are not delivered when the user runs `/identity` from WebChat or TUI; the plugin has no API to push to those channels. Use `/identity status` to confirm results.
192
+
193
+ ## Tools
194
+
195
+ - **identity_whoami** - Show current session identity (sub, TIP status)
196
+ - **identity_status** - Login status, credentials, bindings
197
+ - **identity_login** - Start OIDC login or refresh TIP
198
+ - **identity_logout** - Clear session and TIP
199
+ - **identity_list_credentials** - List providers and credentials (paginated)
200
+ - **identity_list_tips** - List valid TIP tokens and bindings
201
+ - **identity_config** - Show plugin config (redacted)
202
+ - **identity_fetch** - Add credential (provider, flow?, redirectUrl?, scopes?)
203
+ - **identity_set_binding** - Bind provider → env var
204
+ - **identity_unset_binding** - Remove env binding
205
+ - **identity_approve_tool** - Optional tool; approve high-risk tool call by approval_id. Prefer `/identity approve <id>` (human-only; agent must not self-approve).
206
+ - **identity_risk_check** - Diagnose risk for a command or tool call (command, or toolName+params)
207
+ - **identity_list_risk_patterns** - List built-in dangerous commands and sensitive paths
208
+
209
+ ## Hooks
210
+
211
+ - **before_agent_start** - Fetch TIP token; inject credentials into `process.env` per credential-env-bindings (per-session)
212
+ - **after_tool_call** - Propagate TIP to child session on `sessions_spawn`
213
+ - **before_tool_call** - Optional AuthZ (TIP + CheckPermission + risk approval) when authz.enable. Evaluates user-provided commands/paths for risk (rules + optional LLM). High-risk calls require approval; the LLM risk reason is included in approval prompts and block messages when available.
214
+
215
+ ## Data Storage
216
+
217
+ Plugin data at `~/.openclaw/plugins/identity/`:
218
+
219
+ - `sessions.json` - sessionKey → userToken mapping (expired pruned on load/save)
220
+ - `tip-tokens.json` - sessionKey → TIP token cache (expired pruned on load/save)
221
+ - Credentials - in-memory only, per-session (api_key, oauth2); lost on gateway restart; cleared on logout
222
+ - `credential-env-bindings.json` - per-session: `{ [sessionKey]: { [provider]: envVar } }`
223
+ - OIDC state - in-memory only (ephemeral, 5 min TTL)
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Agent Identity Plugin
3
+ *
4
+ * - UserPool login via /identity login (OIDC URL returned directly, no HTTP start endpoint)
5
+ * - Credential hosting: list-credentials, fetch <provider>, set <provider> <envVar>
6
+ * - TIP token via CIS GetWorkloadAccessTokenForJWT in before_agent_start
7
+ * - Sub-agent TIP propagation in after_tool_call (sessions_spawn)
8
+ * - Optional AuthZ in before_tool_call
9
+ * - HTTP callback: /identity/oauth/callback (OIDC login). Credential OAuth uses Identity-provided callback.
10
+ * - Tools: identity_whoami, identity_logout
11
+ */
12
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
13
+ export default function register(api: OpenClawPluginApi): void;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAwD7D,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QAgTtD"}