daemon: rewrite authsync + image seeding on ext4 toolkit

ensureAuthorizedKeyOnWorkDisk and seedAuthorizedKeyOnExt4Image both
drove mount + sudo mkdir/chmod/chown/cat/install to patch
/.ssh/authorized_keys into a work disk or work-seed. Both now delegate
to a shared provisionAuthorizedKey helper that uses the ext4 toolkit
introduced in 7704396 — EnsureExt4RootPerms + MkdirExt4 +
Ext4PathExists/ReadExt4File + WriteExt4FileOwned. No mount, no sudo,
no host-path staging.

Drops ~10 sudo call sites from the VM create and image pull flows
and deletes the TestEnsureAuthorizedKeyOnWorkDiskRepairsNestedRootLayout
premise (flattenNestedWorkHome will disappear entirely in the next
commit — the no-seed path no longer copies /root, and the work-seed
path produces flat seeds).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Thales Maciel 2026-04-23 18:21:50 -03:00
parent 0e28504892
commit f0685366ec
No known key found for this signature in database
GPG key ID: 33112E6833C34679
3 changed files with 34 additions and 163 deletions

View file

@ -3,13 +3,10 @@ package daemon
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"banger/internal/guest"
"banger/internal/model"
"banger/internal/system"
)
func (s *ImageService) seedAuthorizedKeyOnExt4Image(ctx context.Context, imagePath string) (string, error) {
@ -24,56 +21,7 @@ func (s *ImageService) seedAuthorizedKeyOnExt4Image(ctx context.Context, imagePa
if err != nil {
return "", fmt.Errorf("derive authorized ssh key: %w", err)
}
mountDir, cleanup, err := system.MountTempDir(ctx, s.runner, imagePath, false)
if err != nil {
return "", err
}
defer cleanup()
if err := flattenNestedWorkHome(ctx, s.runner, mountDir); err != nil {
return "", err
}
// Same rationale as in ensureAuthorizedKeyOnWorkDisk — the seed's
// filesystem root becomes /root inside the guest, and sshd's
// StrictModes check walks its ownership and mode.
if err := normaliseHomeDirPerms(ctx, s.runner, mountDir); err != nil {
return "", err
}
sshDir := filepath.Join(mountDir, ".ssh")
if _, err := s.runner.RunSudo(ctx, "mkdir", "-p", sshDir); err != nil {
return "", err
}
if _, err := s.runner.RunSudo(ctx, "chmod", "700", sshDir); err != nil {
return "", err
}
if _, err := s.runner.RunSudo(ctx, "chown", "0:0", sshDir); err != nil {
return "", err
}
authorizedKeysPath := filepath.Join(sshDir, "authorized_keys")
existing, err := s.runner.RunSudo(ctx, "cat", authorizedKeysPath)
if err != nil {
existing = nil
}
merged := mergeAuthorizedKey(existing, publicKey)
tmpFile, err := os.CreateTemp("", "banger-image-authorized-keys-*")
if err != nil {
return "", err
}
tmpPath := tmpFile.Name()
if _, err := tmpFile.Write(merged); err != nil {
_ = tmpFile.Close()
_ = os.Remove(tmpPath)
return "", err
}
if err := tmpFile.Close(); err != nil {
_ = os.Remove(tmpPath)
return "", err
}
defer os.Remove(tmpPath)
if _, err := s.runner.RunSudo(ctx, "install", "-m", "600", tmpPath, authorizedKeysPath); err != nil {
if err := provisionAuthorizedKey(ctx, s.runner, imagePath, publicKey); err != nil {
return "", err
}
return fingerprint, nil