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
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:
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user