docs(cloud-console): document user authentication
This commit is contained in:
+33
-71
@@ -1,95 +1,57 @@
|
||||
# Cloud Console
|
||||
|
||||
Independent Vue 3 + Vite single-page app for the Cloud Control Plane
|
||||
(`apps/cloud-api`). Operators authenticate by pasting a pre-issued scoped
|
||||
bearer token; the console stores it in `sessionStorage`, attaches
|
||||
`Authorization: Bearer <token>` to every request, and clears it whenever the
|
||||
Cloud API responds `401` or `403`.
|
||||
Vue 3 + Vite single-page app for the Cloud Control Plane (`apps/cloud-api`).
|
||||
The primary flow is a Cloud user account: username/password login creates an
|
||||
expiring, revocable `HttpOnly` session cookie, while the frontend sends the
|
||||
separate CSRF cookie value on writes. The browser never stores the session
|
||||
secret in JavaScript.
|
||||
|
||||
The app talks only to the platform SDK surface (`/v1/...`) and consumes the
|
||||
two listing endpoints added by the `cloud-console` change (`GET /v1/tasks`,
|
||||
`GET /v1/tasks/{task_id}/attempts`) alongside the existing
|
||||
`/v1/devices`, `/v1/hosts`, `/v1/plugins`, and `POST /v1/plugins` routes.
|
||||
The login screen also offers **Use API token** for existing break-glass or
|
||||
automation credentials. That token is held only in `sessionStorage`; it remains
|
||||
compatible with the existing scoped `CLOUD_PUBLIC_CREDENTIALS_JSON` model.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 20+ (matching the existing `console/` SPA project)
|
||||
- A running Cloud API (`apps/cloud-api`) reachable from your browser
|
||||
- A bearer token issued via `CLOUD_PUBLIC_CREDENTIALS_JSON` whose scopes cover
|
||||
what you intend to do from the console. Recommended least-privilege set:
|
||||
- `tasks:read` — task list and attempt history views
|
||||
- `pool:read` — device and host views
|
||||
- `plugins:read` — plugin list
|
||||
- Add `tasks:submit`/`plugins:admin` only if you need the write actions from
|
||||
the same tab.
|
||||
- Node.js 20+
|
||||
- A current Cloud API database migration and at least one administrator created
|
||||
with `device-cloud-admin users create ...`
|
||||
- HTTPS for production: `CLOUD_SESSION_COOKIE_SECURE=true` is required in a
|
||||
production Cloud API. Terminate TLS at the origin serving `/console/`.
|
||||
|
||||
## Configure the backend CORS allow-list
|
||||
Accounts have fixed roles:
|
||||
|
||||
The Cloud API has no CORS middleware by default. Before a browser can call it
|
||||
cross-origin, set `CLOUD_CONSOLE_CORS_ORIGINS` to a comma-separated allow-list
|
||||
that includes the exact origin your dev server prints (scheme + host + port —
|
||||
no trailing slash):
|
||||
- `viewer`: task, device/host, and plugin read views
|
||||
- `operator`: viewer access plus task submission APIs
|
||||
- `admin`: all API scopes and the Console Users view
|
||||
|
||||
```bash
|
||||
# Example: allow the default Vite dev origin
|
||||
export CLOUD_CONSOLE_CORS_ORIGINS="http://127.0.0.1:5173"
|
||||
```
|
||||
|
||||
Restart `apps/cloud-api` after changing this env. Tokens are still required —
|
||||
the allow-list only says which browser origins may send them.
|
||||
|
||||
## Run the dev server
|
||||
## Local development
|
||||
|
||||
```bash
|
||||
cd cloud-console
|
||||
cp .env.example .env.local
|
||||
# Edit .env.local if your Cloud API is not at http://127.0.0.1:8001
|
||||
# Point this to the local Cloud API when it is not http://127.0.0.1:8001
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Vite prints a local URL (default `http://127.0.0.1:5173`). Open it, paste a
|
||||
bearer token, and the task/device/host/plugin dashboards become available.
|
||||
|
||||
`.env.local` overrides the default base URL via `VITE_CLOUD_API_BASE_URL`
|
||||
(defaults to `http://127.0.0.1:8001`).
|
||||
|
||||
## Build for production
|
||||
For a Vite origin such as `http://127.0.0.1:5173`, configure the API with the
|
||||
exact origin and disable secure cookies only in local/test mode:
|
||||
|
||||
```bash
|
||||
npm run build # type-checks with vue-tsc, then emits dist/
|
||||
npm run preview # serves the built bundle locally
|
||||
export CLOUD_CONSOLE_CORS_ORIGINS="http://127.0.0.1:5173"
|
||||
export CLOUD_SESSION_COOKIE_SECURE=false
|
||||
```
|
||||
|
||||
`dist/` is a static bundle — host it behind any static file server or CDN and
|
||||
point it at a deployed Cloud API via `VITE_CLOUD_API_BASE_URL` set at build
|
||||
time.
|
||||
The Console uses `credentials: include`. `401` returns to the login screen;
|
||||
`403` remains an authorization error so an otherwise valid session is retained.
|
||||
|
||||
## Token handling
|
||||
## Production
|
||||
|
||||
- The token is held in `sessionStorage` only. Closing the tab discards it.
|
||||
- Every API request attaches `Authorization: Bearer <token>` and targets only
|
||||
the configured `VITE_CLOUD_API_BASE_URL`.
|
||||
- A `401`/`403` response clears the stored token and returns the operator to
|
||||
the token-entry screen with the API's error detail.
|
||||
`npm run build` type-checks and creates `dist/`. The repository Dockerfile
|
||||
already builds this bundle into `/app/console-static`; `compose.yaml` and
|
||||
`compose.deploy.yaml` mount it at the same-origin `/console/` route. No CORS
|
||||
configuration is required in that deployment shape.
|
||||
|
||||
## Project layout
|
||||
|
||||
```
|
||||
cloud-console/
|
||||
├── src/
|
||||
│ ├── api.ts # API client wrapper (token storage, fetch, errors)
|
||||
│ ├── types.ts # TS interfaces mirroring the REST models
|
||||
│ ├── App.vue # Shell: token gate, nav, view router
|
||||
│ ├── main.ts # Vue bootstrap
|
||||
│ ├── style.css # Dark theme styles
|
||||
│ └── views/
|
||||
│ ├── TokenScreen.vue
|
||||
│ ├── TasksView.vue # list + detail with attempt history
|
||||
│ ├── DevicesView.vue # device pool + host registry
|
||||
│ └── PluginsView.vue # registry list + registration form
|
||||
├── index.html
|
||||
├── package.json
|
||||
├── tsconfig.json / tsconfig.node.json
|
||||
└── vite.config.ts
|
||||
```
|
||||
Administrators can create users, assign roles, enable/disable accounts, reset
|
||||
temporary passwords, and revoke sessions. All password inputs are cleared from
|
||||
the UI after a create/reset request succeeds or fails.
|
||||
|
||||
Reference in New Issue
Block a user