Installer review: secrets are staged privately, and a bundle is 0600 whether or not it existed

From review: the store and broker passwords genesis makes were carried into
the controller through a world-readable file in /tmp, a bundle left at 0644 by
an earlier installer kept that mode while now holding them, a mesh raised by
the old installer would have been handed new passwords its servers do not have,
and the broker-admin action's marker did not depend on the value. Secrets now
stage in a 0700 directory owned by the controller's account; the bundle is
chmod'd; an existing store or broker volume with no credential file is refused
by name; the marker holds the password's fingerprint. Also: one install path
for the store, broker and vault, no error-string matching for the operator
key, and no unreachable fallback for the superuser.
This commit is contained in:
2026-09-21 01:26:35 +02:00
parent 036af3cfdc
commit 70d0f36896
8 changed files with 175 additions and 155 deletions
+8 -15
View File
@@ -42,11 +42,14 @@ type OperatorKey struct {
// MakeOperatorKey makes the key if this machine has none, and tells the mesh its public half.
func MakeOperatorKey(ctx context.Context, o Options, control controlPlane, say func(string)) (OperatorKey, error) {
out := OperatorKey{Path: OperatorKeyFile(o)}
key, err := identity.LoadSealingKey(out.Path)
switch {
case err == nil:
var key identity.SealingKey
if _, err := os.Stat(out.Path); err == nil {
key, err = identity.LoadSealingKey(out.Path)
if err != nil {
return out, err
}
say(" operator key already at " + out.Path + " — kept")
case os.IsNotExist(underlying(err)) || strings.Contains(err.Error(), "no sealing key at"):
} else if os.IsNotExist(err) {
key, err = identity.GenerateSealingKey()
if err != nil {
return out, err
@@ -58,7 +61,7 @@ func MakeOperatorKey(ctx context.Context, o Options, control controlPlane, say f
return out, err
}
out.Made = true
default:
} else {
return out, err
}
sum := sha256.Sum256([]byte(key.Public))
@@ -77,16 +80,6 @@ func MakeOperatorKey(ctx context.Context, o Options, control controlPlane, say f
return out, nil
}
func underlying(err error) error {
for {
next, ok := err.(interface{ Unwrap() error })
if !ok || next.Unwrap() == nil {
return err
}
err = next.Unwrap()
}
}
// ExportRootSecrets writes the export beside the operator key: every secret sealed to it, as
// ciphertext, and the honest list of what is not. What the vault keeps on its disk, kept once
// more by the person who holds the key.