Carry the machine's tunnel key on its enrolment, so the holder places it on the operator's yes
The operator's decision of 2026-11-02 01:05: the tunnel key is given at issue. Enrolment gains overlay-key, required at every stage and refused unless it is 32 bytes in base64. Tested as rows of TestNodeRecord; no new test function (1438 unit tests). (issue 774, review round 1b) Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -58,6 +58,9 @@ type Enrolment struct {
|
||||
Issued time.Time `json:"issued"`
|
||||
Expires time.Time `json:"expires"`
|
||||
KeysDigest string `json:"keys-digest,omitempty"`
|
||||
// OverlayKey is the machine's tunnel public key, given at issue (the operator's decision of 2026-11-02 01:05),
|
||||
// base64 of 32 bytes: at every stage, since the node enters placement with it on the operator's yes.
|
||||
OverlayKey string `json:"overlay-key"`
|
||||
}
|
||||
|
||||
// EnrolmentAddress is one key `address.<address>`: the node the address is reserved for, and nothing else.
|
||||
@@ -101,6 +104,9 @@ func (e Enrolment) check() error {
|
||||
if strings.TrimSpace(e.Why) == "" || strings.TrimSpace(e.Caller) == "" {
|
||||
return fmt.Errorf("delivery: the enrolment of %s names no why or no caller", e.Node)
|
||||
}
|
||||
if k, err := base64.StdEncoding.DecodeString(e.OverlayKey); err != nil || len(k) != 32 {
|
||||
return fmt.Errorf("delivery: the enrolment of %s names no tunnel key of 32 bytes in base64", e.Node)
|
||||
}
|
||||
switch e.Stage {
|
||||
case EnrolmentAsked, EnrolmentLive:
|
||||
if e.KeysDigest != "" {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package delivery
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -72,11 +73,13 @@ func TestNodeRecord(t *testing.T) {
|
||||
// 774/S35/AC1: an enrolment key and an address key read back equal, and neither names a field like a secret: the
|
||||
// grants part reads them (ADR 0587 §2).
|
||||
issued := time.Date(2026, 11, 2, 1, 0, 0, 0, time.UTC)
|
||||
// The tunnel key given at issue, at every stage.
|
||||
wg := base64.StdEncoding.EncodeToString(make([]byte, 32))
|
||||
for _, e := range []Enrolment{
|
||||
{Node: "lab", Address: "10.0.0.7", Why: "a new machine", Caller: "mesh-enrolment", Ask: "a1", Stage: EnrolmentLive,
|
||||
Issued: issued, Expires: issued.Add(DefaultTokenLife)},
|
||||
OverlayKey: wg, Issued: issued, Expires: issued.Add(DefaultTokenLife)},
|
||||
{Node: "lab", Address: "10.0.0.7", Why: "a new machine", Caller: "mesh-enrolment", Ask: "a1", Stage: EnrolmentRedeeming,
|
||||
Issued: issued, Expires: issued.Add(MostTokenLife), KeysDigest: KeysDigest("pub", "overlay", "sealing", "serving")},
|
||||
OverlayKey: wg, Issued: issued, Expires: issued.Add(MostTokenLife), KeysDigest: KeysDigest("pub", "overlay", "sealing", "serving")},
|
||||
} {
|
||||
raw, err := EncodeEnrolment(e)
|
||||
if err != nil {
|
||||
@@ -95,11 +98,15 @@ func TestNodeRecord(t *testing.T) {
|
||||
}
|
||||
for name, e := range map[string]Enrolment{
|
||||
"keys before redeem": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: EnrolmentLive,
|
||||
Issued: issued, Expires: issued.Add(time.Hour), KeysDigest: KeysDigest("a", "b", "c", "d")},
|
||||
OverlayKey: wg, Issued: issued, Expires: issued.Add(time.Hour), KeysDigest: KeysDigest("a", "b", "c", "d")},
|
||||
"no keys at redeem": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: EnrolmentRedeeming,
|
||||
Issued: issued, Expires: issued.Add(time.Hour)},
|
||||
"no address": {Node: "lab", Why: "w", Caller: "c", Stage: EnrolmentAsked, Issued: issued, Expires: issued.Add(time.Hour)},
|
||||
"other stage": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: "spent", Issued: issued,
|
||||
OverlayKey: wg, Issued: issued, Expires: issued.Add(time.Hour)},
|
||||
"no address": {Node: "lab", Why: "w", Caller: "c", Stage: EnrolmentAsked, OverlayKey: wg, Issued: issued, Expires: issued.Add(time.Hour)},
|
||||
"no tunnel key": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: EnrolmentAsked, Issued: issued,
|
||||
Expires: issued.Add(time.Hour)},
|
||||
"a tunnel key not of 32 bytes": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: EnrolmentAsked,
|
||||
OverlayKey: base64.StdEncoding.EncodeToString(make([]byte, 31)), Issued: issued, Expires: issued.Add(time.Hour)},
|
||||
"other stage": {Node: "lab", Address: "10.0.0.7", Why: "w", Caller: "c", Stage: "spent", OverlayKey: wg, Issued: issued,
|
||||
Expires: issued.Add(time.Hour)},
|
||||
} {
|
||||
if _, err := EncodeEnrolment(e); err == nil {
|
||||
|
||||
Reference in New Issue
Block a user