Re-make an own secret sealed to a key the machine lost, and name the validator's mesh-sdk pin in a check
This commit is contained in:
@@ -204,7 +204,9 @@ func prepareSend(ctx context.Context, open *stores, node string) ([]string, erro
|
||||
if n.SealingKey != "" {
|
||||
held := map[string]bool{}
|
||||
for _, r := range in.OwnSecrets {
|
||||
if r.Node == node {
|
||||
// Held only when sealed to the key the machine has now, or given by a person (which is not the mesh's
|
||||
// to make again): a made row under an old key is re-made, as SecretForModule did.
|
||||
if r.Node == node && (r.SealedTo == n.SealingKey || r.Origin == inventory.OriginAccepted) {
|
||||
held[r.Module+"/"+r.Name] = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,3 +195,41 @@ func TestAFinishedSendMakesNothingTheSecondTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Review round 1, finding 1: a machine that rejoined with a new sealing key keeps its made rows sealed to the old key. A
|
||||
// send re-makes them for the new key, as SecretForModule did on main, and the file naming the secret is not refused.
|
||||
func TestASendReMakesAnOwnSecretSealedToAKeyTheMachineNoLongerHas(t *testing.T) {
|
||||
open := aMesh(t)
|
||||
ctx := t.Context()
|
||||
inv := open.inventory
|
||||
register(t, open, aBot("bot", false))
|
||||
if _, err := assign(ctx, open, "laptop", "bot"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := composeSend(ctx, open, "laptop"); err != nil {
|
||||
t.Fatalf("the first send is refused: %v", err)
|
||||
}
|
||||
if err := inv.RecordSealingKey(ctx, nodeID(t, open, "laptop"), aPublicKey(t)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := composeSend(ctx, open, "laptop"); err != nil {
|
||||
t.Fatalf("a machine that rejoined cannot be sent to: %v", err)
|
||||
}
|
||||
in, err := readComposeInput(ctx, open)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
n, _ := nodeOf(in.Input, "laptop")
|
||||
found := false
|
||||
for _, r := range in.OwnSecrets {
|
||||
if r.Node == "laptop" && r.Module == "bot" && r.Name == "token" {
|
||||
found = true
|
||||
if r.SealedTo != n.SealingKey {
|
||||
t.Fatalf("the own secret is still sealed to a key the machine no longer has")
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("the own secret has no row")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1194,7 +1194,7 @@ func judgeFor(ctx context.Context, labelled, run Runner, spec CheckSpec, root, t
|
||||
"go", "build", "-o", bin, "./cmd/mesh-controller")...); err != nil {
|
||||
return "", "the change's controller, which judges itself, does not build: " + firstLine(err.Error()), nil
|
||||
}
|
||||
say("check", "judged by the change's own controller")
|
||||
say("check", "judged by the change's own controller, with %s", validatorAt(tree))
|
||||
return bin, "", nil
|
||||
}
|
||||
bin, _, err := judge(ctx, labelled, run, root, inToolchain, say)
|
||||
@@ -1637,6 +1637,37 @@ func dialable(ctx context.Context, address string) error {
|
||||
return fmt.Errorf("nothing took a connection at %s", address)
|
||||
}
|
||||
|
||||
// sdkPin is the mesh-sdk version the controller in dir takes (its go.mod's go requirement), or "" when it names none.
|
||||
func sdkPin(dir string) string {
|
||||
body, err := os.ReadFile(filepath.Join(dir, "go.mod"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, line := range strings.Split(string(body), "\n") {
|
||||
f := strings.Fields(strings.TrimPrefix(strings.TrimSpace(line), "require "))
|
||||
if len(f) >= 2 && f[0] == "git.novox.be/novox/mesh-sdk/go" {
|
||||
return f[1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// validatorAt names the validator of the controller in dir as mesh-sdk's at that controller's pin (issue 1391).
|
||||
func validatorAt(dir string) string {
|
||||
if v := sdkPin(dir); v != "" {
|
||||
return "mesh-sdk's validator at " + v
|
||||
}
|
||||
return "mesh-sdk's validator at the controller's pin"
|
||||
}
|
||||
|
||||
// pinNote is the version of that pin, for a sentence that already says "the pin of": ", " and the version, or nothing.
|
||||
func pinNote(dir string) string {
|
||||
if v := sdkPin(dir); v != "" {
|
||||
return " (" + v + ")"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// judge builds the controller that judges a change: the one the mesh runs, beside the check as
|
||||
// mesh-controller — or, when that one predates the merge gate, the controller's main, said. It answers
|
||||
// the binary and the directory it was built from.
|
||||
@@ -1658,7 +1689,7 @@ func judge(ctx context.Context, run, plain Runner, root string, inToolchain func
|
||||
return "", "", fmt.Errorf("the controller the mesh runs does not build: %w", err)
|
||||
}
|
||||
if hasGate() {
|
||||
say("check", "judged by the controller the mesh runs")
|
||||
say("check", "judged by the controller the mesh runs, with %s", validatorAt(filepath.Join(root, "mesh-controller")))
|
||||
return bin, "mesh-controller", nil
|
||||
}
|
||||
}
|
||||
@@ -1668,7 +1699,8 @@ func judge(ctx context.Context, run, plain Runner, root string, inToolchain func
|
||||
if err := build("mesh-controller-main"); err != nil {
|
||||
return "", "", fmt.Errorf("the controller's main does not build: %w", err)
|
||||
}
|
||||
say("check", "judged by the controller's main: the one the mesh runs predates the merge gate")
|
||||
say("check", "judged by the controller's main: the one the mesh runs predates the merge gate, with %s",
|
||||
validatorAt(filepath.Join(root, "mesh-controller-main")))
|
||||
return bin, "mesh-controller-main", nil
|
||||
}
|
||||
|
||||
@@ -1783,7 +1815,7 @@ func judgeFromTheGroup(ctx context.Context, labelled, run Runner, spec CheckSpec
|
||||
// its pin. A mesh-host member brings no validator (issue 1391), and its tree need hold none.
|
||||
source = groupDir(spec, root, tree, "mesh-controller")
|
||||
from = "the group's own controller, merge " + headAt(ctx, run, source)
|
||||
validator = "mesh-sdk's validator at the pin of the group's controller"
|
||||
validator = "mesh-sdk's validator at the pin of the group's controller" + pinNote(source)
|
||||
inputs = append(inputs, "group member "+spec.Repo+" "+judged.Head+" onto "+judged.Trunk)
|
||||
for _, m := range judged.Members {
|
||||
inputs = append(inputs, "group member "+m.Repo+" "+m.Head+" onto "+m.Trunk)
|
||||
@@ -1791,7 +1823,7 @@ func judgeFromTheGroup(ctx context.Context, labelled, run Runner, spec CheckSpec
|
||||
case spec.Judge != "self" && controller != nil:
|
||||
source = filepath.Join(root, "mesh-controller")
|
||||
from = merge("mesh-controller", controller)
|
||||
validator = "mesh-sdk's validator at the pin of " + merge("mesh-controller", controller)
|
||||
validator = "mesh-sdk's validator at the pin of " + merge("mesh-controller", controller) + pinNote(source)
|
||||
default:
|
||||
return "", "", false, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Issue 1391, AC5: what a check says names the validator as mesh-sdk's at the controller's pin, with the version from the
|
||||
// judge's own go.mod.
|
||||
func TestTheValidatorIsNamedAsMeshSDKsAtTheControllersPin(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
mod := "module example.test/c\n\ngo 1.25\n\nrequire (\n\tgit.novox.be/novox/mesh-sdk/go v0.1.14-0.20261020085642-ab0c16ddad26\n)\n"
|
||||
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte(mod), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := validatorAt(dir), "mesh-sdk's validator at v0.1.14-0.20261020085642-ab0c16ddad26"; got != want {
|
||||
t.Fatalf("the check says %q, not %q", got, want)
|
||||
}
|
||||
if got, want := pinNote(dir), " (v0.1.14-0.20261020085642-ab0c16ddad26)"; got != want {
|
||||
t.Fatalf("the pin note is %q, not %q", got, want)
|
||||
}
|
||||
if got := validatorAt(t.TempDir()); got != "mesh-sdk's validator at the controller's pin" {
|
||||
t.Fatalf("a controller with no go.mod is said as %q", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user