This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
## 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.
|
||||
Reference in New Issue
Block a user