hecate: preserve known_hosts ownership during key repair
This commit is contained in:
parent
b5f27a79e0
commit
4c03be1e9b
@ -8,6 +8,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -134,11 +135,14 @@ func RepairKnownHosts(ctx context.Context, logger *log.Logger, knownHostsFiles [
|
|||||||
}
|
}
|
||||||
|
|
||||||
func removeKnownHostEntry(ctx context.Context, logger *log.Logger, file string, entry string) {
|
func removeKnownHostEntry(ctx context.Context, logger *log.Logger, file string, entry string) {
|
||||||
|
uid, gid, mode := captureOwnership(file)
|
||||||
|
|
||||||
runCtx, cancel := context.WithTimeout(ctx, 8*time.Second)
|
runCtx, cancel := context.WithTimeout(ctx, 8*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
cmd := exec.CommandContext(runCtx, "ssh-keygen", "-R", entry, "-f", file)
|
cmd := exec.CommandContext(runCtx, "ssh-keygen", "-R", entry, "-f", file)
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
|
restoreOwnership(file, file+".old", uid, gid, mode)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logf(logger, "known_hosts repaired: removed %s from %s", entry, file)
|
logf(logger, "known_hosts repaired: removed %s from %s", entry, file)
|
||||||
return
|
return
|
||||||
@ -151,6 +155,36 @@ func removeKnownHostEntry(ctx context.Context, logger *log.Logger, file string,
|
|||||||
logf(logger, "warning: known_hosts cleanup failed for %s in %s: %v: %s", entry, file, err, strings.TrimSpace(string(out)))
|
logf(logger, "warning: known_hosts cleanup failed for %s in %s: %v: %s", entry, file, err, strings.TrimSpace(string(out)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func captureOwnership(path string) (int, int, os.FileMode) {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
return -1, -1, 0
|
||||||
|
}
|
||||||
|
st, ok := info.Sys().(*syscall.Stat_t)
|
||||||
|
if !ok {
|
||||||
|
return -1, -1, info.Mode().Perm()
|
||||||
|
}
|
||||||
|
return int(st.Uid), int(st.Gid), info.Mode().Perm()
|
||||||
|
}
|
||||||
|
|
||||||
|
func restoreOwnership(path string, backupPath string, uid int, gid int, mode os.FileMode) {
|
||||||
|
if uid < 0 || gid < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, candidate := range []string{path, backupPath} {
|
||||||
|
if candidate == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(candidate); err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_ = os.Chown(candidate, uid, gid)
|
||||||
|
if mode != 0 {
|
||||||
|
_ = os.Chmod(candidate, mode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func logf(logger *log.Logger, format string, args ...any) {
|
func logf(logger *log.Logger, format string, args ...any) {
|
||||||
if logger != nil {
|
if logger != nil {
|
||||||
logger.Printf(format, args...)
|
logger.Printf(format, args...)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user