R-861: narrow the agent's root grants — exact sudo patterns, felhom-priv-apply content checker, fixed hook/parent files in the bundle, signed self-update verified as root, escrow root reads pinned
gates / gates (push) Successful in 20s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 12:00:43 +02:00
parent 61345790ed
commit 6ab1e7c56c
39 changed files with 1657 additions and 400 deletions
+9 -1
View File
@@ -33,6 +33,8 @@ const (
DropinDir = "/etc/dnsmasq.d"
// BaseDropin holds the host-wide listen/upstream config (one per host).
BaseDropin = "felhom-resolver-base.conf"
// PrivApply is the root content checker that installs a drop-in (R-861).
PrivApply = "/usr/local/sbin/felhom-priv-apply"
)
// RenderBase returns the host-wide dnsmasq drop-in: bind to the host LAN IP (+ loopback), no-resolv,
@@ -263,7 +265,13 @@ func (m *Manager) writeFileIfChanged(ctx context.Context, path, content, mode st
return false, fmt.Errorf("write temp: %w", err)
}
tmp.Close()
if _, errOut, err := m.runner.Run(ctx, "install", "-m", mode, tmpName, path); err != nil {
// R-861 (v0.146.0): a dnsmasq drop-in reaches /etc/dnsmasq.d only through the root checker, which allows exactly
// the lines RenderBase/RenderGuestDropin write (a `dhcp-script=` would run as root). Mode is fixed (0644) there.
_ = mode
if filepath.Dir(path) != DropinDir {
return false, fmt.Errorf("drop-in %s is not in %s", path, DropinDir)
}
if _, errOut, err := m.runner.Run(ctx, PrivApply, "dnsmasq", tmpName, filepath.Base(path)); err != nil {
return false, fmt.Errorf("install %s: %s: %w", path, strings.TrimSpace(string(errOut)), err)
}
return true, nil
@@ -0,0 +1,22 @@
package lanresolver
import (
"strings"
"testing"
"gitea.dooplex.hu/admin/felhom-agent/internal/privapplytest"
)
// R-861: both drop-ins the resolver renders are accepted by the root checker; a dhcp-script line is not.
func TestPrivApply_AcceptsTheRenderedDropins(t *testing.T) {
if got := privapplytest.Check(t, "dnsmasq", BaseDropin, RenderBase("192.168.0.104", []string{"1.1.1.1", "8.8.8.8"})); got != "OK" {
t.Errorf("base drop-in: %s", got)
}
if got := privapplytest.Check(t, "dnsmasq", DropinName("demo-hp"), RenderGuestDropin("demo-hp", "enkisfelhom.hu", "192.168.0.138")); got != "OK" {
t.Errorf("guest drop-in: %s", got)
}
evil := RenderGuestDropin("demo-hp", "enkisfelhom.hu", "192.168.0.138") + "dhcp-script=/var/lib/felhom-agent/x\n"
if got := privapplytest.Check(t, "dnsmasq", "felhom-x.conf", evil); !strings.HasPrefix(got, "REFUSED") {
t.Fatalf("control: dhcp-script was not refused: %s", got)
}
}