全部產品
Search
文件中心

:多租戶管理

更新時間:Sep 24, 2026

多個租戶共用同一 Agent Sandbox容器版 叢集時,每個租戶通過 Team 映射到獨立的 Kubernetes Namespace,並持有各自的 API Key 作為訪問憑證。管理員和租戶可通過 HTTP 介面建立、查詢和吊銷 API Key。

概述

ack-sandbox-manager 提供一組相容 E2B 協議的 HTTP 介面,用於管理 API Key 與 Team。叢集管理員與租戶可通過這些介面以編程方式建立 API Key、查詢所屬 Team,並吊銷不再使用的 Key。

這些介面沒有配套的 E2B SDK,也沒有對應的 Kubernetes CRD,必須直接通過 HTTP 協議調用。

Team

Team 是 API Key 的授權邊界。在 Agent Sandbox容器版 中,Team 的身份由 Team 名稱唯一標識,且 Team 名稱直接映射到一個 Kubernetes Namespace。

  • 內建的 admin Team 是叢集級的,由管理員管理,其持有的 admin API Key 在 ack-sandbox-manager 啟動時一同初始化。

  • 其他任何 Team 名稱都必須對應一個已經存在的 Kubernetes Namespace。當租戶為 Team foo 建立 API Key 時,Namespace foo 必須預先存在,否則請求會返回錯誤。

Namespace 的唯一性已經提供了足夠的隔離邊界,因此 Team的唯一識別碼(UUID)僅作為展示用中繼資料保留,不參與鑒權和資源尋找。

API Key

API Key 是某個 Team 長期持有的訪問憑證。用戶端在調用 ack-sandbox-manager 任意介面時,都必須通過 X-API-KEY 要求標頭攜帶它。API Key 決定了:

  • 調用方屬於哪個 Team。

  • 調用方是普通租戶還是叢集管理員(即是否屬於 admin Team)。

  • 調用方可訪問的 Sandbox 範圍,普通租戶只能訪問由自身 API Key 建立的 Sandbox,管理員可以訪問全部 Sandbox。

授權模型

角色

列出當前Team 的 Key

列出 Teams

為當前Team 建立 Key

為其他 Team 建立 Key

刪除當前Team 的 Key

刪除 admin API Key

管理員(admin Team)

支援

支援(全部 Team)

支援

支援

支援

不支援(被拒絕)

普通租戶

支援

支援(僅自身所在 Team)

支援

不支援

支援

不支援

重要

內建的 admin API Key 在任何情況下都不能被刪除,以保護叢集的可控性。

準備工作

  • 前往目的地組群組件管理,確認已安裝ack-sandbox-manager且已升級至 v0.6.0 及以上版本。並在組件配置頁面進行如下配置:

    • 勾選Whether to enable E2B_API_KEY authentication,啟用API Key鑒權功能。

    • 配置adminApiKey(管理員API Key)。

端到端流程樣本

  1. 擷取叢集KubeConfig並通過kubectl工具串連叢集。

  2. 安裝JSON處理器jq。

  3. 以下指令碼完整示範了從管理員初始化資源環境與租戶憑證,到租戶自主實現團隊密鑰全生命週期管理的端到端商務程序。

    #!/usr/bin/env bash
    set -euo pipefail
    
    ADMIN_KEY="${ADMIN_KEY:?required}"
    # 支援兩種協議,樣本使用原生E2B協議地址 https://api.your.domain.com
    # 如需使用Agent Sandbox私人協議,將BASE_URL替換為 https://your.domain.com/kruise/api。
    BASE_URL="${BASE_URL:-https://api.your.domain.com}"
    TEAM_NAMESPACE="team-a"
    
    # 1. 管理員在叢集中建立 Team 對應的 Namespace
    kubectl create ns "${TEAM_NAMESPACE}"
    
    # 2. 管理員為 team-a 建立租戶 Key,記錄返回的明文 key
    TENANT_KEY=$(curl -fsS -X POST \
      -H "X-API-KEY: ${ADMIN_KEY}" \
      -H "Content-Type: application/json" \
      -d "{\"name\":\"ci-runner\",\"teamName\":\"${TEAM_NAMESPACE}\"}" \
      "${BASE_URL}/api-keys" | jq -r '.key')
    
    # 3. 租戶列出所屬 Team 與現有 Key
    curl -fsS -H "X-API-KEY: ${TENANT_KEY}" "${BASE_URL}/teams"
    curl -fsS -H "X-API-KEY: ${TENANT_KEY}" "${BASE_URL}/api-keys"
    
    # 4. 租戶為所屬 Team 建立子 Key(無需 teamName 欄位)
    SUB_KEY_ID=$(curl -fsS -X POST \
      -H "X-API-KEY: ${TENANT_KEY}" \
      -H "Content-Type: application/json" \
      -d '{"name":"my-sub-key"}' \
      "${BASE_URL}/api-keys" | jq -r '.id')
    
    # 5. 租戶刪除所屬 Team 的子 Key
    curl -fsS -X DELETE \
      -H "X-API-KEY: ${TENANT_KEY}" \
      "${BASE_URL}/api-keys/${SUB_KEY_ID}"

介面參考

Team列表

擷取目前使用者可見的 Team。普通租戶只能看到自身所屬的 Team;管理員可以看到所有 Team。

請求樣本:

curl -fsS \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/teams"
import os
import requests

resp = requests.get(
    "https://api.your.domain.com/teams",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
print(resp.json())

預期輸出:

[
  {
    "teamID": "550e8400-e29b-41d4-a716-446655449999",
    "name": "admin",
    "apiKey": "",
    "isDefault": true
  }
]

響應體為 JSON 數組,每個元素的欄位說明如下表。

欄位

類型

說明

teamID

string

Team 的 UUID,僅用於展示。

name

string

Team 名稱,與 Kubernetes Namespace 一致。

apiKey

string

該欄位始終返回Null 字元串,僅為相容 E2B SDK Schema 保留。如需擷取 API Key 明文,請使用 POST /api-keys 建立並立即儲存傳回值。

isDefault

boolean

是否為調用方的預設 Team。

API Key列表

擷取當前調用方所屬 Team 下的所有 API Key。

請求樣本:

curl -fsS \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/api-keys"
import os
import requests

resp = requests.get(
    "https://api.your.domain.com/api-keys",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
for key in resp.json():
    print(key["id"], key["name"], key["mask"])

響應欄位說明:

欄位

類型

說明

id

string

API Key 的 UUID,刪除時使用。

name

string

Key 的可讀名稱。

createdAt

string

Key 的建立時間。

createdBy.id

string

建立該 Key 的調用方 UUID。

lastUsed

string

Key 最近一次使用時間,從未使用時為 null。

建立 API Key

建立新的 API Key。響應體中的 key 欄位為剛剛產生的明文 Key。明文 key 欄位僅在建立時返回一次,後續無法再通過任何介面取回。請立即持久化儲存。

說明

運行樣本前,請確保 team-a 命名空間已經存在。如調用方為普通租戶,請刪除請求體中的 teamName 欄位。

請求樣本:

curl -fsS -X POST \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"name": "ci-runner", "teamName": "team-a"}' \
  "https://api.your.domain.com/api-keys"
import os
import requests

resp = requests.post(
    "https://api.your.domain.com/api-keys",
    headers={
        "X-API-KEY": os.environ["E2B_API_KEY"],
        "Content-Type": "application/json",
    },
    json={"name": "ci-runner", "teamName": "team-a"},
    timeout=10,
)
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
created = resp.json()
# 請立刻持久化 created["key"]-後續無法再次擷取。
print(created["id"], created["key"])

請求體欄位:

欄位

類型

是否必填

說明

name

string

是

Key 的可讀名稱。

teamName

string

否

目標 Team 名稱,預設為調用者自身所屬的 Team。僅管理員可指向其他 Team,且必須指向一個已經存在的 Kubernetes Namespace。普通租戶必須省略此欄位。

響應欄位:

欄位

類型

說明

id

string

新 Key 的 UUID,後續刪除時使用。

key

string

明文 Key,僅返回一次,必須立即儲存。

name

string

與請求體一致的 Key 名稱。

team.id

string

Key 實際歸屬的 Team UUID。

team.name

string

Key 實際歸屬的 Team 名稱(即對應的 Kubernetes Namespace),用於校正調用方意圖。

刪除 API Key

通過 UUID 刪除指定的 API Key。普通租戶只能刪除當前Team 下的 Key;管理員可以刪除 admin API Key 以外的任意 Key。嘗試刪除內建 admin API Key 會返回 403 Forbidden。

請求樣本:

API_KEY_ID="<uuid-from-list-api-keys>"
curl -fsS -X DELETE \
  -H "X-API-KEY: ${E2B_API_KEY}" \
  "https://api.your.domain.com/api-keys/${API_KEY_ID}"
import os
import requests

api_key_id = "<uuid-from-list-api-keys>"
resp = requests.delete(
    f"https://api.your.domain.com/api-keys/{api_key_id}",
    headers={"X-API-KEY": os.environ["E2B_API_KEY"]},
    timeout=10,
)
# 成功時返回 204 No Content。
try:
    resp.raise_for_status()
except requests.HTTPError:
    print(resp.text)
    raise
無效UUID 與不存在的 UUID 一律返回 404 Not Found,介面不區分這兩種情況。

錯誤碼

HTTP 狀態代碼

情境

400

請求體不合法(JSON 解析失敗)或目標 Namespace 不存在。

401

未攜帶 X-API-KEY 或 Key 無效。

403

非管理員對其他 Team 進行寫操作,或嘗試刪除 admin API Key。

404

指定 UUID 的 API Key 不存在,或路徑參數不是合法 UUID 字串。

500

伺服器內部錯誤,例如缺少必要欄位、Kubernetes API 不可用及持久化儲存不可達等。

錯誤響應體為 JSON,包含 code、message、request_id 三個欄位,便於定位問題:

{
  "code": 403,
  "message": "You are not allowed to create an API key for another team",
  "request_id": "c42c84d8-8420-4194-b48d-5bc5c8fe4ed6"
}