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
+35 -5
View File
@@ -82,11 +82,9 @@ func (c controlPlane) carry(ctx context.Context, local, remote string) error {
// landed unreadable, `secret accept` failed with `permission denied`, and what depended on it
// crash-looped on material it never received. There is no shell in the image to chown it with.
//
// What goes through here is a module manifest and a store connection string. The connection is the
// same value the produced bundle already holds in the clear — a foundation names its own bootstrap
// credentials, and at genesis there is nowhere else for them to be — so this widens nothing. The
// file on the machine is removed at once, and the copy inside the container goes when the
// container does, which for the temporary control plane is step 10.
// What goes through here is a module manifest — public, the same bytes as in the catalogue. A
// value that is secret goes through carryingSecret below. The file on the machine is removed at
// once, and the copy inside the container goes when the container does.
func (c controlPlane) carrying(ctx context.Context, name string, content []byte, remote string) error {
local := filepath.Join(os.TempDir(), name)
if err := os.WriteFile(local, content, 0o644); err != nil {
@@ -96,6 +94,38 @@ func (c controlPlane) carrying(ctx context.Context, name string, content []byte,
return c.carry(ctx, local, remote)
}
// controlPlaneUID is the account the control plane's image runs as — `USER 65534:65534` in its
// Dockerfile — and so the only account inside the container that needs to read what is carried in.
const controlPlaneUID = 65534
// carryingSecret is carrying for a value that is a secret: staged in a directory only root can
// enter, at 0600, owned by the control plane's own account — which `docker cp` keeps, so inside
// the container the file is readable by the process that must read it and by nobody else. Since
// genesis makes the mesh's root credentials rather than copying the template's (rootsecrets.go),
// a store connection string or a broker password carried this way is a real secret, and 0644 in a
// shared temporary directory would hand it to any local user for the length of the copy.
func (c controlPlane) carryingSecret(ctx context.Context, name string, content []byte, remote string) error {
dir, err := os.MkdirTemp("", "mesh-carrying-")
if err != nil {
return fmt.Errorf("nowhere to stage %s before copying it into %s: %w", name, c.container, err)
}
defer os.RemoveAll(dir)
local := filepath.Join(dir, name)
if err := os.WriteFile(local, content, 0o600); err != nil {
return fmt.Errorf("nowhere to stage %s before copying it into %s: %w", name, c.container, err)
}
if err := os.Chown(local, controlPlaneUID, controlPlaneUID); err != nil {
// Not root — a test, or an installer run as a user, which no real genesis is. The
// directory is 0700, so nobody else on the machine can reach the file either way; inside
// the container the only account is the control plane's, so 0644 there is read by it and
// by nothing else. The narrower ownership is taken whenever it can be.
if err := os.Chmod(local, 0o644); err != nil {
return err
}
}
return c.carry(ctx, local, remote)
}
func indent(s string) string {
if s == "" {
return ""