Save and Load must agree, and did not

Pushed a failing test in the last commit -- my own gate reported it and I read
the count rather than the result. The failure was real and worth having.

Adding the membership requirement to Load made Generate produce an identity that
Save would write and Load would then refuse. A file that cannot be read back is
the worst shape this could take: it is read back on the next start, on a machine
nobody is watching, and by then the token that could have fixed it is spent.

Save now refuses exactly what Load refuses, and writes nothing when it does. The
round-trip test covers the membership too, since that is the half that lets a
node come back on its own.
This commit is contained in:
2026-08-29 16:24:57 +02:00
parent a488c76b5e
commit c192572f74
2 changed files with 58 additions and 18 deletions
+10
View File
@@ -148,6 +148,16 @@ func Save(path string, i Identity) error {
if len(i.Private) != ed25519.PrivateKeySize {
return errors.New("refusing to save an identity with no usable private key")
}
// Save refuses exactly what Load refuses. Without this, a caller can write a file that
// cannot be read back — and it would be read back on the next start, on a machine nobody is
// watching, by which time the token that could have fixed it is spent.
if strings.TrimSpace(i.Node) == "" {
return errors.New("refusing to save an identity that names no node")
}
if !i.Membership.Joined() {
return errors.New("refusing to save an identity that does not say how to reach its " +
"mesh: it could not be used after a restart, and Load will not accept it")
}
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return err
}