119 lines
6.0 KiB
Markdown
119 lines
6.0 KiB
Markdown
## Context
|
|
|
|
The Cloud API currently chains configured bearer credentials, browser user
|
|
sessions, and repository-backed Host credentials. Three JSON environment
|
|
variables populate the first provider and a second provider protects first Host
|
|
enrollment. The deployment image already contains the Console bundle, but
|
|
Compose separately supplies its fixed location. The Console also retains a
|
|
bearer-token compatibility screen and an administrator-only Users view.
|
|
|
|
The intended deployment has one trusted Cloud endpoint. A human operator signs
|
|
in with a Cloud account created or recovered through `device-cloud-admin`; a
|
|
new Host Agent registers itself once, generates its own high-entropy Host
|
|
secret, and persists the returned Host identity locally. Subsequent Host
|
|
requests continue to authenticate against the stored digest.
|
|
|
|
## Goals / Non-Goals
|
|
|
|
**Goals:**
|
|
- Start Cloud production without any static credential JSON or startup
|
|
requirement for one.
|
|
- Authorize browser operations by the existing user session and preserve its
|
|
role, CSRF, expiry, audit, and interactive CLI controls.
|
|
- Accept direct first Host registration, then strictly bind all later Host
|
|
operations to the registered Host identity and persisted secret.
|
|
- Remove obsolete Console and Compose configuration paths while keeping the
|
|
Jenkins-built Console available at `/console/`.
|
|
|
|
**Non-Goals:**
|
|
- No personal-access-token, service-account, or replacement SDK credential
|
|
scheme in this change.
|
|
- No user-directory view in the Console. Account provisioning and recovery
|
|
remain administration-CLI operations.
|
|
- No Host enrollment approval, rate limiting, or multi-tenant trust policy.
|
|
Network reachability to the trusted Cloud endpoint remains the boundary
|
|
explicitly chosen for this deployment.
|
|
- No change to durable task, lease, device, or user database schema.
|
|
|
|
## Decisions
|
|
|
|
### D1. Remove configured bearer providers instead of leaving empty compatibility configuration
|
|
|
|
`CloudControlConfig` will no longer parse the three credential JSON variables
|
|
or require credentials in production. The Cloud application will compose public
|
|
authorization from `UserSessionAuthProvider` only, while Host operational
|
|
authorization remains `RepositoryHostAuthProvider`. An empty production user
|
|
table is allowed so an administrator can execute the interactive bootstrap CLI
|
|
after migrations complete.
|
|
|
|
Leaving the variables optional was rejected because it preserves two
|
|
authentication modes and makes operators believe a deployed secret is needed.
|
|
Adding user-issued API tokens was rejected because the requested outcome is no
|
|
manual token configuration and it introduces a separate credential lifecycle.
|
|
|
|
### D2. Direct enrollment is a single unauthenticated bootstrap operation
|
|
|
|
The enrollment endpoint accepts a fresh Host's generated instance identifier
|
|
and candidate secret without an `Authorization` header. It stores only the
|
|
candidate secret digest and returns a generated `host_id`; the Host persists
|
|
that result atomically. The configured enrollment-token provider and static
|
|
Host configuration are removed. Heartbeat, device enrollment, claim, renewal,
|
|
and result endpoints remain Host-bound and require the persisted bearer secret.
|
|
|
|
An opt-in enrollment flag was rejected because the target deployment always
|
|
uses direct trust and the flag is another operational switch that can silently
|
|
block first-run setup. Keeping token enrollment as a fallback was rejected for
|
|
the same reason as D1.
|
|
|
|
### D3. Keep user administration off the Console, not out of the control plane
|
|
|
|
The Console retains login, logout, current-account display, and password
|
|
change. It removes bearer-token controls, token storage, and all Users routes,
|
|
navigation, client calls, and components. The authenticated user administration
|
|
API and `device-cloud-admin` CLI remain available for controlled provisioning
|
|
and recovery; the CLI is the documented initial-admin path.
|
|
|
|
Removing the administration API entirely was rejected because it would make
|
|
recovery tooling less complete and is unrelated to eliminating deployment
|
|
tokens.
|
|
|
|
### D4. Treat packaged static assets as an image contract
|
|
|
|
The Dockerfile sets `CLOUD_CONSOLE_STATIC_DIR=/app/console-static` after copying
|
|
the built SPA. Compose does not repeat this invariant. Application code keeps
|
|
the variable optional for source-based local development, where no bundled
|
|
directory exists.
|
|
|
|
## Risks / Trade-offs
|
|
|
|
- **[Risk] Any network caller can create a Host identity.** → The accepted
|
|
mitigation is reverse-proxy/firewall control of the trusted Cloud endpoint;
|
|
every operation after enrollment still requires the Host-generated secret.
|
|
- **[Risk] Existing integrations using static bearer tokens stop working.** →
|
|
This is intentional; create Cloud user accounts before deployment and migrate
|
|
human workflows to session login.
|
|
- **[Risk] An upgrade before an administrator exists leaves no human API
|
|
access.** → Run the documented interactive `device-cloud-admin users create`
|
|
command immediately after migration and before exposing the Console.
|
|
- **[Risk] Existing static or token-enrolled Hosts cannot rely on removed
|
|
configuration after upgrade.** → Preserve their already persisted dynamic
|
|
identities where present; otherwise perform a fresh direct enrollment.
|
|
|
|
## Migration Plan
|
|
|
|
1. Build and deploy the image with the schema migration already included.
|
|
2. Start the Cloud API using only database, production, and network settings.
|
|
3. Run `device-cloud-admin users create` interactively to bootstrap an
|
|
administrator, then verify Console login over HTTPS.
|
|
4. Start each new Host Agent with its persistent identity path; it directly
|
|
enrolls once and then uses its durable secret for future starts.
|
|
5. Remove the legacy credential JSON values from the deployment secret store.
|
|
|
|
Rollback requires restoring an earlier image and its matching static
|
|
credentials before restarting any Host that lacks a durable enrolled identity.
|
|
|
|
## Open Questions
|
|
|
|
- None. The user explicitly accepts direct Host enrollment behind the network
|
|
perimeter and does not require a Console user-directory surface.
|