Files
bear-cli/README.md
T
alex 0b18d76cfd feat: 實作 vault 指令群 status/unlock/lock/list/get/create/edit/delete/restore/purge/folders/sync/password/rescue(issue #17)
- 對接 alterminal/bear#41 的 /api/v1/vault JSON API(PAT Bearer)
- 客戶端端到端加密,格式與 Web Vault(P2)完全一致:
  - 加密字串 2.<iv>.<ct>.<mac>(AES-256-CBC+HMAC-SHA-256、PKCS#7、encrypt-then-MAC)
  - 主金鑰 PBKDF2-SHA512(迭代數取自 /vault/config 與 profile,不寫死;salt=email 小寫)
  - BIP39 助記詞(12 字、128-bit、英文詞表)+救援路徑
- K_user 僅存記憶體:vault unlock 匯出 BEAR_VAULT_SESSION(base64),
  同 Bitwarden CLI BW_SESSION 慣例;lock 提示 unset;不寫入任何檔案
- docs/commands.md 補 §3.11 規格;README 同步
- 測試:fake API 注入+Bear.Vault.Crypto 密文樣本交叉驗證(雙向);
  BIP39 官方向量;46 個新測試,全套 196 passed
2026-09-10 23:27:47 +08:00

144 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🐻 Bear CLI
**Bear CLI** 是 [澳特科技](https://alterminal.com)(Alter Technology)單點登入系統 [Bear](https://gitea.alterminal.com/alterminal/bear) 的**終端機(CLI)客戶端**:讓使用者在 Linux 終端機以 Bear 帳號登入(Device Flow 或個人存取權杖)、查詢身分、取得 Token,作為 SSO 的終端入口。
> **狀態:已實作 PAT 模式 MVP(Elixir + Req,issue #6)+ App 管理(#10)+ 個人自助指令群(#11)+ 管理端指令群(#12)+ Vault 密碼管理(#17)**。`login --token <PAT>`、`whoami`、`token`、`logout`、`status`、`apps`、`profile`/`password`/`email`/`sessions`/`tokens`/`mfa`、`jwks`/`accounts`/`audit-logs`、`vault` 已可用;Device Authorization Grant(RFC 8628)登入待伺服器端 P1(bear 倉庫)完成後再接。
> 伺服器端採用的 OIDC **Device Authorization Grant(RFC 8628)** 方向,詳見 bear 倉庫的設計文件 `docs/cli-feature-plan.md`(issue #17)。
> Bear 已支援**個人存取權杖(Personal Access Token,PAT)**;CLI 規劃以其作為完全免瀏覽器的替代登入方式(見下文)。
---
## 為什麼需要 CLI
Bear 目前所有流程都依賴「瀏覽器」:登入 `/login`、儀表板 Launch、Relying Party 走 Authorization Code Flow + PKCE。但**終端機沒有瀏覽器可互動**,無法完成 `redirect_uri` 回跳,因此需要一個為「無瀏覽器/輸入受限裝置」設計的登入流程,讓 `bear` 指令也能以 OIDC 身分登入並取用 Token。此外,Bear 現已支援**個人存取權杖(PAT)**,CLI 亦可直接以 PAT 登入,完全免瀏覽器,適合 CI/腳本/一次性使用。
---
## 指令總覽
| 指令 | 說明 | 階段 |
|------|------|------|
| `bear login` | 啟動 Device Flow 登入;或 `--token <PAT>` 以個人存取權杖登入 | P2 |
| `bear whoami` | 顯示目前登入身分(`GET /userinfo`) | P2 |
| `bear token [--refresh]` | 印出 access token(過期自動 refresh),供 pipe 給其他工具 | P2 |
| `bear logout` | 撤銷 refresh token(`POST /revoke`) | P2 |
| `bear status` | 顯示登入狀態與 token 剩餘效期 | P2 |
| `bear apps list/show/create/update/rotate-secret/toggle` | App 管理(需 bear App 管理 JSON API,PAT 登入、admin 限定) | P3(✅ 已實作) |
| `bear jwks list/show/create/toggle` | 簽章金鑰管理(admin 限定) | P3(✅ 已實作) |
| `bear accounts list/show/create/update/set-password/delete` | 帳號管理(admin 限定) | P3(✅ 已實作) |
| `bear audit-logs list` | 稽核日誌查詢(admin 限定) | P3(✅ 已實作) |
| `bear profile show/set` | 個人資料檢視/更新(需 bear 個人自助 JSON API) | P3(✅ 已實作) |
| `bear password change` | 變更密碼(互動輸入,不進 shell history) | P3(✅ 已實作) |
| `bear email change --new EMAIL` | 變更 email(雙向驗證碼流程) | P3(✅ 已實作) |
| `bear sessions list/revoke/revoke-others` | 管理網頁 session | P3(✅ 已實作) |
| `bear tokens list/create/revoke` | 管理 PAT(create 一次性顯示明文) | P3(✅ 已實作) |
| `bear mfa status/setup/disable/recovery-codes` | TOTP 兩因子管理 | P3(✅ 已實作) |
| `bear vault status/unlock/lock` | Vault 解鎖狀態與 K_user session(僅記憶體) | P3(✅ 已實作) |
| `bear vault list/get/create/edit` | 項目 CRUD(客戶端端到端加密,與 Web Vault 互操作) | P3(✅ 已實作) |
| `bear vault delete/restore/purge` | 回收桶(soft delete/還原/永久刪除) | P3(✅ 已實作) |
| `bear vault folders list/create/rename/delete` | 資料夾管理(名稱客戶端加密) | P3(✅ 已實作) |
| `bear vault sync` | 完整同步(伺服器為準) | P3(✅ 已實作) |
| `bear vault password change` | 變更 vault 主密碼(重新包裝 K_user,不動 cipher) | P3(✅ 已實作) |
| `bear vault rescue` | 助記詞救援(BIP39,重設主密碼) | P3(✅ 已實作) |
完整指令規格(選項、行為、輸出、退出碼)見 [`docs/commands.md`](docs/commands.md)。
---
## 實作狀態(PAT 模式 MVP)
目前已實作**個人存取權杖(PAT)模式**的最小可用版本(issue #6 骨架部分):
| 指令 | 狀態 |
|------|------|
| `bear login --token <PAT>` | ✅ 已實作(PAT 模式;Device Flow 待伺服器端 P1) |
| `bear whoami` | ✅ 已實作(`GET /userinfo`,Bearer PAT;支援 `BEAR_TOKEN` 環境變數) |
| `bear token` | ✅ 已實作(印出 PAT;`--refresh` 為用法錯誤) |
| `bear logout` | ✅ 已實作(清除本機憑證;PAT 需至網頁撤銷) |
| `bear status` | ✅ 已實作(純本機判定,顯示 PAT/環境變數模式) |
| `bear apps` | ✅ 已實作(`list`/`show`/`create`/`update`/`rotate-secret`/`toggle`;issue #10,對接 alterminal/bear#28 的 `/api/v1/apps` JSON API,admin PAT 限定) |
| `bear jwks` | ✅ 已實作(`list`/`show`/`create`/`toggle`;issue #12,對接 alterminal/bear#46 的 `/api/v1/jwks` JSON API,admin PAT 限定) |
| `bear accounts` | ✅ 已實作(`list`/`show`/`create`/`update`/`set-password`/`delete`;issue #12,對接 alterminal/bear#46 的 `/api/v1/accounts` JSON API;密碼不進命令列,初始/新密碼一次性輸出) |
| `bear audit-logs` | ✅ 已實作(`list` 含 `--category` 過濾與 emails 對照;issue #12,對接 alterminal/bear#46 的 `/api/v1/audit-logs` JSON API) |
| `bear profile`/`password`/`email`/`sessions`/`tokens`/`mfa` | ✅ 已實作(issue #11,對接 alterminal/bear#38 的 `/api/v1/profile*` JSON API,任何有效 PAT 皆可):`profile show/set`、`password change`、`email change --new`、`sessions list/revoke/revoke-others`、`tokens list/create/revoke`、`mfa status/setup/disable/recovery-codes`。規格見 `docs/commands.md` §3.7 |
| `bear vault` | ✅ 已實作(issue #17,對接 alterminal/bear#41 的 `/api/v1/vault` JSON API,任何有效 PAT 皆可):`status`/`unlock`/`lock`/`list`/`get`/`create`/`edit`/`delete`/`restore`/`purge`/`folders`/`sync`/`password change`/`rescue`。端到端加密全在客戶端(AES-256-CBC+HMAC-SHA-256 加密字串、PBKDF2-SHA512、BIP39 助記詞),格式與 Web Vault(P2)完全一致;K_user 僅存 shell 環境變數記憶體(`BEAR_VAULT_SESSION`),不落盤。規格見 `docs/commands.md` §3.11 |
### 建置與執行
```bash
mix deps.get # 安裝依賴(Req、Jason)
mix test # 跑單元測試
mix escript.build # 產生單檔可執行 `bear`
./bear --help
./bear login --token <PAT> --issuer https://alterminal.com
```
> 發行格式目前採 `mix escript`(目標機需 Erlang);self-contained release(bakeware/burrito)仍為待定方向(見 `docs/commands.md` §7)。
---
## 全域選項
| 選項 | 說明 | 預設 |
|------|------|------|
| `--issuer URL` | Bear(OIDC Provider)位址 | `https://alterminal.com` |
| `--config PATH` | 設定檔路徑 | `~/.config/bear/config.json` |
| `--json` | 機器可讀輸出(JSON) | — |
| `-v, --verbose` | 顯示詳細日誌 | — |
| `-h, --help` | 顯示說明 | — |
| `--version` | 顯示版本 | — |
---
## 登入流程(`bear login`,示意)
### Device Flow(預設)
```
$ bear login
正在向 https://alterminal.com 註冊裝置...
請在瀏覽器開啟:https://alterminal.com/device
輸入代碼:ABCD-EFGH
(等待授權中...)
已登入:alice@example.com
```
登入後,CLI 將 refresh token 寫入本機憑證檔(0600),access token 僅做短命快取。
### 個人存取權杖(PAT,免瀏覽器)
```
$ bear login --token <PAT>
已登入:alice@example.com
```
以 PAT 登入不產生 refresh token;CLI 直接將該 PAT 寫入憑證檔(0600)作為憑證,適合 CI/腳本等無瀏覽器情境。
---
## 憑證與設定檔
| 檔 | 路徑 | 內容 | 權限 |
|----|------|------|------|
| 設定 | `~/.config/bear/config.json` | `issuer`、`client_id`、`scope` | 0644 |
| 憑證 | `~/.local/state/bear/credentials.json` | Device Flow:`refresh_token`+快取 `access_token`/`expires_at`;PAT:直接存 `access_token`(無 refresh) | **0600** |
---
## 里程碑
| 階段 | 內容 |
|------|------|
| **P1 伺服器:Device Flow** | `device_codes` 資料表、`POST /device_authorization`、`GET/POST /device` 授權頁、token 端點 `device_code` grant、Discovery 更新(於 bear 倉庫) |
| **P2 CLI 登入** | 本倉庫實作 `login`(Device Flow 或 `--token <PAT>`)/`whoami`/`token`/`logout`/`status`、憑證儲存 0600 |
| **P3 進階** | `bear apps` 管理指令群(依賴 bear App 管理 JSON API)、個人自助指令群 `profile`/`password`/`email`/`sessions`/`tokens`/`mfa`(依賴 bear 個人自助 JSON API,#11)、QR 顯示、系統 keyring、發行二進位 |
---
## 技術方向(規劃)
- **語言**:Elixir(與 Bear 主專案一致),HTTP 一律使用 `Req`。
- **發行**:`mix escript`(單檔可執行)或 `mix release` 自包含二進位(待定)。
- **安全**:device_code 只存 SHA-256 雜湊、user_code 限流、憑證檔 0600、token 與 PAT 一律不入 log/commit;一次性明文(`apps` 的 client_secret、`tokens create` 的 PAT、`mfa` 的 recovery codes)僅在成功當下顯示一次;密碼與驗證碼一律互動輸入、不回顧。