Node records, and the right to join once
The next step after the schema: inventory now holds node records and enrolment tokens, and mesh-control has the commands to work with them. A token is issued for a node record, which is where re-enrolment gets decided -- what an identity binds to is settled when the token is made, not when it is presented, so the machine presenting one does not need to know whether it is joining or returning. What the token guarantees, each with a test confirmed to fail when the behaviour is removed: the secret is 256 random bits, shown once and stored only as a hash; it works exactly once; it stops working when it expires; issuing again for a node invalidates the outstanding one, because two live tokens are two machines able to join as the same node. Redemption is a single statement that finds and spends together, so eight concurrent attempts on one secret produce exactly one winner rather than a race between a check and a write. Refusals are deliberately identical for unknown, spent and expired. Somebody guessing must not learn which guess was a real token that had merely aged out. SHA-256 rather than a password hash, and that is a choice not a shortcut: the secret is high-entropy random, so there is nothing to guess and a slow hash would buy nothing while making every redemption expensive. It stops before what a node receives in exchange. What a machine presents afterwards to prove it is that node is not decided anywhere, and a migration is the most expensive place here to guess. So a token carries one of the four things ADR 0004 requires. The command prints the secret and then says exactly that -- the broker's address, its certificate fingerprint and the control plane's signing identity do not exist yet. Better than emitting something that looks complete and silently cannot be used.
This commit is contained in:
@@ -25,18 +25,42 @@ argument that is not settled there.
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `inventory` | the node records — **the schema exists** |
|
||||
| `inventory` | node records and enrolment tokens — **built, as far as identity** |
|
||||
| `config`, `connectivity`, `provisioning`, `delivery`, `observability`, `identity` | not built |
|
||||
| the interface every surface speaks to | not built; its shape is not decided |
|
||||
|
||||
```
|
||||
mesh-control migrate bring each context's schema up to date
|
||||
mesh-control version what this binary is
|
||||
mesh-control migrate bring each context's schema up to date
|
||||
mesh-control node add <name> create a node record
|
||||
mesh-control node list the nodes this mesh knows about
|
||||
mesh-control token issue --node <name> a one-time right to join, for an existing record
|
||||
mesh-control token issue --new <name> create the record and issue for it
|
||||
mesh-control version what this binary is
|
||||
```
|
||||
|
||||
`migrate` is **step 3 of the substrate bootstrap** — the step the first node cannot get past, run
|
||||
against a database raised moments earlier from the bundle the host carries.
|
||||
|
||||
### Tokens, and what they are missing
|
||||
|
||||
A token is **a one-time right to join, issued for a node record** — which is where re-enrolment is
|
||||
decided, since what an identity binds to is settled when the token is made rather than when it is
|
||||
presented.
|
||||
|
||||
What is built: the secret is 256 bits from the system's random source, shown once, and **stored
|
||||
only as a hash**, so a copy of this database is not a set of working credentials. It is usable
|
||||
exactly once and only before it expires, and both are read from the row rather than from a status
|
||||
something would have had to write. Issuing again for the same node invalidates the outstanding
|
||||
one — two live tokens are two machines able to join as the same node.
|
||||
|
||||
Redemption is a single statement that both finds a live token and spends it, so eight concurrent
|
||||
attempts on one secret produce exactly one winner. There is a test that runs them.
|
||||
|
||||
**What a token is missing is three of its four parts.** ADR 0004 requires the broker's address,
|
||||
the fingerprint of its certificate, and the control plane's signing identity. None of the three
|
||||
exists yet, so `token issue` prints the secret **and says so**, rather than producing something
|
||||
that looks complete and cannot be used.
|
||||
|
||||
### Where this stops, and why there
|
||||
|
||||
At **identity**. A node's own identity is the next thing needed and its cryptographic form is not
|
||||
|
||||
Reference in New Issue
Block a user