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 != "" {
|
if n.SealingKey != "" {
|
||||||
held := map[string]bool{}
|
held := map[string]bool{}
|
||||||
for _, r := range in.OwnSecrets {
|
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
|
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 {
|
"go", "build", "-o", bin, "./cmd/mesh-controller")...); err != nil {
|
||||||
return "", "the change's controller, which judges itself, does not build: " + firstLine(err.Error()), 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
|
return bin, "", nil
|
||||||
}
|
}
|
||||||
bin, _, err := judge(ctx, labelled, run, root, inToolchain, say)
|
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)
|
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
|
// 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
|
// 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.
|
// 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)
|
return "", "", fmt.Errorf("the controller the mesh runs does not build: %w", err)
|
||||||
}
|
}
|
||||||
if hasGate() {
|
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
|
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 {
|
if err := build("mesh-controller-main"); err != nil {
|
||||||
return "", "", fmt.Errorf("the controller's main does not build: %w", err)
|
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
|
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.
|
// its pin. A mesh-host member brings no validator (issue 1391), and its tree need hold none.
|
||||||
source = groupDir(spec, root, tree, "mesh-controller")
|
source = groupDir(spec, root, tree, "mesh-controller")
|
||||||
from = "the group's own controller, merge " + headAt(ctx, run, source)
|
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)
|
inputs = append(inputs, "group member "+spec.Repo+" "+judged.Head+" onto "+judged.Trunk)
|
||||||
for _, m := range judged.Members {
|
for _, m := range judged.Members {
|
||||||
inputs = append(inputs, "group member "+m.Repo+" "+m.Head+" onto "+m.Trunk)
|
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:
|
case spec.Judge != "self" && controller != nil:
|
||||||
source = filepath.Join(root, "mesh-controller")
|
source = filepath.Join(root, "mesh-controller")
|
||||||
from = merge("mesh-controller", 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:
|
default:
|
||||||
return "", "", false, nil
|
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