Skip to content

Commit c0cf4fb

Browse files
authored
feat(studio): manage user roles through Identity (#1100)
* feat(studio): manage user roles through Identity * test(studio): include Identity role coverage in CI discovery * fix(studio): validate role changes against the public origin * feat(studio): confirm deployments without a super administrator * test(studio): allow runtime proxy workers to start on busy hosts
1 parent 3d7b7bc commit c0cf4fb

115 files changed

Lines changed: 3916 additions & 1079 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎docs/content/docs/framework/frontend.en.mdx‎

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -371,43 +371,57 @@ authorization confirmation after login.
371371

372372
### Studio roles and Runtime access
373373

374-
`--admin` and `--developer` each accept a comma-separated list of local
375-
usernames or OAuth email addresses. Whitespace is ignored and matching is
376-
case-insensitive. If the same identity appears in both lists, `admin` takes
377-
precedence. For a local Studio:
378-
379-
```bash
380-
veadk studio \
381-
--admin "admin,admin@example.com" \
382-
--developer "alice,alice@example.com,bob"
383-
```
384-
385-
The equivalent environment variables are `VEADK_STUDIO_ADMINS` and
386-
`VEADK_STUDIO_DEVELOPERS`.
387-
388-
Use the same options for a deployed Studio:
374+
The only deployment role option is `--super-admin`, which accepts an existing
375+
Identity user's email or UID:
389376

390377
```bash
391378
veadk studio deploy \
392379
--user-pool-id <pool-id> \
393380
--allowed-client-id <client-id> \
394381
--vefaas-app-name <app-name> \
395-
--admin "admin@example.com" \
396-
--developer "alice@example.com,bob@example.com"
382+
--super-admin "owner@example.com"
397383
```
398384

399-
Omitting both options treats every signed-in user as an `admin`. Supplying
400-
either list enables role-based access control. An identity that does not match
401-
either list is a regular user.
402-
403-
| Capability | admin | developer | Regular user |
404-
| :-- | :-- | :-- | :-- |
405-
| Add, debug, and deploy agents | Allowed | Allowed | Denied; add/manage items are hidden from the sidebar |
406-
| View and connect to Runtimes | All Runtimes | Own Runtimes only | Own Runtimes only |
407-
| Manage or delete Runtimes | All Studio-managed Runtimes | Own Runtimes only | Denied |
385+
On first deployment, omitting this option makes all signed-in users admins,
386+
including future users. Supplying it makes other users regular users by default.
387+
The default and individual roles are stored in Identity. Later deployments and
388+
updates preserve existing assignments
389+
390+
Only super admins can see and use **User management** to list pool users and
391+
change roles. They inherit every admin capability. Studio protects the initial
392+
super admin from demotion. To assign the first super admin to an existing
393+
installation without changing other roles, run
394+
`veadk studio update --vefaas-app-name <app-name> --super-admin <email-or-uid>`
395+
396+
| Capability | Super admin | Admin | Developer | Regular user |
397+
| :-- | :-- | :-- | :-- | :-- |
398+
| Manage users | Allowed | Denied | Denied | Denied |
399+
| Add, debug, and deploy agents | Allowed | Allowed | Allowed | Denied |
400+
| View and connect to Runtimes | All | All | Own only | Own only |
401+
| Manage or delete Runtimes | All Studio-managed | All Studio-managed | Own only | Denied |
402+
403+
The backend reads current Identity group membership for each authenticated
404+
request. Refreshing the page reflects role changes in permissions and the
405+
account badge
406+
407+
In-app updates match the old `VEADK_STUDIO_ADMINS` and
408+
`VEADK_STUDIO_DEVELOPERS` entries to Identity users and preserve their roles.
409+
Only after migration succeeds are the old role environment values cleared.
410+
Unmatched or ambiguous entries and insufficient permissions stop migration and
411+
retain the old configuration. Empty legacy lists preserve the all-admin default;
412+
with explicit lists, unlisted users remain regular users. Existing admins are
413+
never automatically promoted to super admin
414+
415+
If the old updater predates migration, the new runtime migrates on first startup
416+
and clears the Function configuration. Published revisions may retain their old
417+
environment snapshots, but these lists never overwrite initialized Identity
418+
roles. Older deployments need Identity user/group read and membership write
419+
permissions before upgrading; alternatively, the new CLI update refreshes the
420+
managed Studio IAM policy. These rules apply to both Volcengine and BytePlus
421+
422+
Local sessions without an Identity pool still support
423+
`veadk studio --admin ... --developer ...`; `deploy` no longer accepts these options
408424

409-
The account footer shows the OAuth email below the display name. Purple,
410-
yellow, and green badges identify admins, developers, and regular users.
411425
The manage-agent view defaults to Beijing and can be switched to Shanghai.
412426
After the first message is sent, a new conversation opens immediately while the
413427
server session ID initializes in the background.
@@ -416,7 +430,7 @@ The server records Runtime ownership when it creates a Runtime; authorization
416430
does not trust an author field submitted by the browser. Existing Runtimes may
417431
still be claimed by the legacy-compatible `veadk:author` ownership tag. A
418432
historical Runtime with neither `veadk:owner` nor `veadk:author` is visible only
419-
to admins.
433+
to admins and super admins.
420434

421435
<Callout type="warning">
422436
A local username is stored in the browser and can be changed or impersonated.

‎docs/content/docs/framework/frontend.mdx‎

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -314,48 +314,56 @@ frontend/service/studio_release_server/deploy.sh
314314

315315
### Studio 角色与 Runtime 权限
316316

317-
`--admin` 和 `--developer` 分别接收逗号分隔的用户名或 OAuth 邮箱。空格会被
318-
忽略,身份匹配不区分大小写;同一身份同时出现在两个名单时,`admin` 优先。
319-
本地启动示例:
320-
321-
```bash
322-
veadk studio \
323-
--admin "admin,admin@example.com" \
324-
--developer "alice,alice@example.com,bob"
325-
```
326-
327-
也可以分别通过 `VEADK_STUDIO_ADMINS` 和 `VEADK_STUDIO_DEVELOPERS` 环境变量
328-
设置这两个名单。
329-
330-
部署 Studio 时使用相同参数:
317+
部署时唯一的角色参数是 `--super-admin`,指定用户池内已有用户的邮箱或 UID:
331318

332319
```bash
333320
veadk studio deploy \
334321
--user-pool-id <pool-id> \
335322
--allowed-client-id <client-id> \
336323
--vefaas-app-name <app-name> \
337-
--admin "admin@example.com" \
338-
--developer "alice@example.com,bob@example.com"
324+
--super-admin "owner@example.com"
339325
```
340326

341-
两项都不传时,所有登录用户都按管理员(`admin`)处理。只要传入任一名单就会启用
342-
角色权限;未命中名单的身份是普通用户。
327+
首次部署不指定超级管理员时,所有登录用户默认都是管理员,包括后续新增用户;指定后,
328+
其余用户默认是普通用户。默认角色和用户角色都存储在 Identity 中,后续部署和更新保留
329+
已保存的角色,不会重新套用初始化配置
330+
331+
只有超级管理员可见并可使用“用户管理”,可查询当前用户池的用户、修改角色。
332+
超级管理员拥有管理员的全部权限,初始超级管理员不能在 Studio 内降级。
333+
已有部署没有超级管理员时,可运行
334+
`veadk studio update --vefaas-app-name <app-name> --super-admin <email-or-uid>`
335+
设置首位超级管理员,其他人的角色保持不变
336+
337+
| 功能 | super admin | admin | developer | 普通用户 |
338+
| :-- | :-- | :-- | :-- | :-- |
339+
| 用户管理 | 允许 | 不允许 | 不允许 | 不允许 |
340+
| 添加、调试和部署 Agent | 允许 | 允许 | 允许 | 不允许 |
341+
| 查看和连接 Runtime | 全部 | 全部 | 仅自己创建的 | 仅自己创建的 |
342+
| 管理或删除 Runtime | 全部 Studio 管理的 | 全部 Studio 管理的 | 仅自己创建的 | 不允许 |
343+
344+
新版 Studio 在每次已认证的后端请求中读取 Identity 用户组,角色修改后刷新页面即可
345+
看到变化。账号区域显示对应角色徽标
346+
347+
云上页面更新会把旧环境变量 `VEADK_STUDIO_ADMINS`、`VEADK_STUDIO_DEVELOPERS`
348+
中的账号逐一匹配到 Identity,保留原角色,成功后清空旧角色变量。名单中的账号必须
349+
唯一匹配;匹配失败或权限不足时停止迁移并保留旧配置。旧名单为空时保留“全部为管理员”;
350+
有名单时,其余人仍是普通用户。不会自动将旧管理员升级成超级管理员
351+
352+
旧更新器不包含迁移逻辑时,由新版首次启动完成迁移并清理 Function 配置。
353+
已发布 Revision 的环境快照可能仍保留原值,但 Identity 初始化完成后不会再次覆盖角色。
354+
旧部署需要 Identity 用户组读写权限;可先补齐权限,或使用新版 CLI 更新,由 CLI 更新
355+
Studio 托管的 IAM 策略。火山引擎和 BytePlus 遵循同样规则
343356

344-
| 功能 | admin | developer | 普通用户 |
345-
| :-- | :-- | :-- | :-- |
346-
| 添加、调试和部署 Agent | 允许 | 允许 | 不允许;侧边栏隐藏添加/管理入口 |
347-
| 查看和连接 Runtime | 全部 Runtime | 仅自己创建的 Runtime | 仅自己创建的 Runtime |
348-
| 管理或删除 Runtime | 全部 Studio 管理的 Runtime | 仅自己创建的 Runtime | 不允许 |
357+
本地未配置 Identity 用户池时,仍兼容 `veadk studio --admin ... --developer ...`;
358+
`deploy` 已移除这两个参数
349359

350-
侧边栏底部的账号区域会在用户名下显示 OAuth 邮箱,并在用户名右侧用紫色、黄色、
351-
绿色徽标分别标识管理员、开发者和普通用户。
352360
管理 Agent 页面默认展示北京区域的 Runtime,也可以切换到上海。
353361
新会话发送首条消息后会立即进入对话页面;服务端会话创建期间,会话 ID 显示为
354362
“初始化中”。
355363

356364
Runtime 归属由服务端在创建时记录,不使用浏览器提交的作者字段做授权。升级前创建
357365
的 Runtime 会兼容 `veadk:author` 归属标签;同时缺少 `veadk:owner` 和
358-
`veadk:author` 归属标签的历史 Runtime 仅 admin 可见。
366+
`veadk:author` 归属标签的历史 Runtime 仅管理员和超级管理员可见。
359367

360368
<Callout type="warning">
361369
本地用户名保存在浏览器中,可以被用户修改或冒充,只适合本地开发和功能验证。

‎frontend/README.md‎

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ See [deployment and operation](service/studio_release_notifier/README.md).
4747
and BytePlus; existing Runtime updates and Sidecar deployments keep their
4848
existing role behavior
4949

50+
- **User management** stores Studio roles in Identity user groups
51+
scoped to the configured user pool and client. A super administrator can search
52+
all pool users, filter roles, and assign super administrator, administrator,
53+
developer, or ordinary-user access. The next page refresh reads current roles;
54+
protected backend requests also resolve live membership. Only immutable
55+
subject-to-user-ID mappings are cached
56+
5057
- **Sandbox updates** in System Information compare each Tool's current image
5158
with `ListToolTypes` for its cloud provider and actual region. Volcengine and
5259
BytePlus use their own credentials and API hosts; catalogs are cached for
@@ -555,6 +562,90 @@ Rebuild the UI from source after changing it:
555562
cd frontend && npm install && npm run build # -> veadk/webui
556563
```
557564

565+
If an existing checkout reports missing `i18next` or `react-i18next` modules,
566+
run `npm ci` from `frontend/` to synchronize dependencies with the lockfile
567+
before rebuilding. Reusing another checkout's `node_modules` can retain older
568+
dependencies even when the current `package.json` already declares them
569+
570+
### Identity-backed user management
571+
572+
Deploy with `--super-admin <existing-user-email-or-uid>` to select the first
573+
super administrator. This is the only deployment role flag; `deploy --admin`
574+
and `deploy --developer` are no longer supported
575+
576+
Without `--super-admin`, deployment first warns that user and permission
577+
management will be inconvenient without a super administrator and asks
578+
`是否继续? [y/N]`. Press Enter or enter `n` to cancel before cloud operations;
579+
enter `y` to continue. Setting `VEADK_STUDIO_SUPER_ADMIN` also satisfies this
580+
check. Read-only `--precheck-only` does not prompt
581+
582+
```bash
583+
veadk studio deploy --user-pool-id <pool-uid> \
584+
--allowed-client-id <client-uid> --vefaas-app-name <app-name> \
585+
--super-admin <existing-user-email-or-uid>
586+
```
587+
588+
On first deployment, omitting `--super-admin` stores an **admin** default in
589+
Identity, so existing and future signed-in users are administrators. Specifying
590+
it stores a **regular-user** default for other users. Existing Identity roles
591+
and the stored default are preserved on subsequent deployments and updates
592+
593+
Only super administrators can see **User management** or call its APIs. They
594+
also inherit all administrator capabilities, including visibility into all
595+
agents and resources available to the Studio. The initial super administrator
596+
is protected from demotion. If an existing Studio has none, use
597+
`veadk studio update --vefaas-app-name <app-name> --super-admin <email-or-uid>`
598+
to assign the first one without resetting other users' roles
599+
600+
Role changes validate the browser Origin against the public OAuth callback URL
601+
configured by deployment, so HTTPS gateways can forward to an internal HTTP
602+
server without blocking legitimate changes. Other origins remain blocked, and
603+
client-supplied forwarding headers cannot change the accepted origin. For a
604+
custom public domain, set `--oauth2-redirect-uri` to its OAuth callback URL
605+
606+
For local use, pass `--oauth2-user-pool-uid`, `--oauth2-user-pool-client-uid`, and
607+
optionally `--super-admin` to `veadk studio`, with the selected provider's AK/SK
608+
available. `VEIDENTITY_REGION` selects the Identity region. Volcengine and
609+
BytePlus use their respective credentials and API hosts. Local sessions without
610+
an Identity pool retain the legacy `--admin` / `--developer` options
611+
612+
Four `studio-<client-uid>-<role>` Identity groups store application roles; their
613+
metadata stores the default role and the protected user's immutable UID. These
614+
application roles do not assign cloud IAM roles. Each authenticated backend
615+
request reads current group membership. OIDC subjects map to Identity management
616+
UIDs; email cannot substitute for an authenticated subject. Refreshing the page
617+
shows a newly assigned role. Multiple role memberships fail closed to regular
618+
user access and can be repaired by assigning a role again
619+
620+
Cloud frontend updates automatically migrate `VEADK_STUDIO_ADMINS` and
621+
`VEADK_STUDIO_DEVELOPERS` into Identity. Each UID, subject, email or username
622+
must match exactly one pool user before any assignments are written. Admin
623+
membership takes precedence over developer membership. With either legacy list,
624+
unlisted users remain regular users; with neither list and no initial super
625+
administrator, everyone retains admin access. Migration never promotes a legacy
626+
admin to super administrator automatically
627+
628+
After successful migration, the update clears the old role environment values
629+
and enables Identity roles. Failures retain the old configuration. Updates and
630+
restarts preserve subsequent role edits in Identity. When the running updater
631+
predates this feature, the new runtime performs the migration before accepting
632+
requests and clears the Function configuration. Existing immutable revisions
633+
may still contain their original environment snapshot; the new runtime ignores
634+
those old lists once Identity initialization is complete
635+
636+
Deploy and CLI update provision the required Identity permissions on the
637+
managed Studio IAM policy. In-app updates check permissions and do not change
638+
IAM policies. For an older updater that lacks this check, grant Identity
639+
user/group read and group create/update/add/remove-member permissions before
640+
upgrading, or use the new `veadk studio update` CLI. Missing permissions stop
641+
migration instead of falling back to static role lists
642+
643+
Initialize a new pool/client on one instance before starting additional
644+
instances. Identity membership updates are not transactional across instances;
645+
conflicting edits are denied or reported for retry, and multiple memberships
646+
grant no additional privileges. Audit logs include the actor, target, old/new
647+
roles and operation ID
648+
558649
Dev loop with hot reload (Vite proxies the API):
559650

560651
```bash

‎frontend/server/studio_update_resources.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,35 @@ def reconcile_studio_update_resources(
137137
access_key: str,
138138
secret_key: str,
139139
session_token: str,
140+
migrate_identity_roles: bool = True,
140141
) -> dict[str, str]:
141142
"""Return environment overrides for resources missing from an older Studio."""
142143
function, environment = _function_state(function_client, function_id)
143144
overrides: dict[str, str] = {}
145+
if migrate_identity_roles and (
146+
environment.get("OAUTH2_USER_POOL_ID")
147+
or environment.get("VEADK_STUDIO_USER_POOL_ID")
148+
):
149+
import click
150+
from frontend.server.user_management.deployment import prepare_identity_roles
151+
from veadk.cli.studio_release import StudioReleaseError
152+
153+
try:
154+
overrides.update(
155+
prepare_identity_roles(
156+
pool_uid=environment.get("OAUTH2_USER_POOL_ID")
157+
or environment.get("VEADK_STUDIO_USER_POOL_ID", ""),
158+
client_uid=environment.get("OAUTH2_USER_POOL_CLIENT_ID", ""),
159+
provider=provider,
160+
region=environment.get("VEIDENTITY_REGION") or region,
161+
access_key=access_key,
162+
secret_key=secret_key,
163+
session_token=session_token,
164+
legacy_environment=environment,
165+
)
166+
)
167+
except click.ClickException as error:
168+
raise StudioReleaseError(str(error)) from error
144169

145170
from frontend.server.workspace_tool import workspace_update_environment
146171

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Studio user administration backed by Identity user groups."""

0 commit comments

Comments
 (0)