//go:build linux && rootrunner package host import ( "bytes" "os" "os/exec" "path/filepath" "syscall" "testing" "github.com/carlosframework/platform/internal/caps" "github.com/carlosframework/platform/internal/release" "github.com/carlosframework/platform/internal/rootparticipation" "github.com/carlosframework/platform/internal/rootstate" ) func TestPlan14RootCapabilitiesBothPaths(t *testing.T) { if action := os.Getenv("PLAN14_CAPS_HOSTILE"); action != "" { path := filepath.Join(rootparticipation.Namespace, "census.json") var err error if action == "renamed" { err = os.Rename(path, path+"-old") } else { err = os.Remove(path) } if !os.IsPermission(err) { t.Fatal("service UID mutated census", err) } return } if os.Geteuid() != 0 { t.Fatal("root required") } if _, err := os.Lstat("/var/lib/carlos-claims"); !os.IsNotExist(err) { t.Fatal("existing authority", err) } opt := t.TempDir() o, effects := passOps(t) rt := capsUnitRoute("keymail.dev", "keymail") rt.Caps, rt.Channel = "port:25", "canary/x" reg := openReg(t, rt) set := &caps.Set{V: 1, Daemon: true, Ports: []caps.Port{{Port: 25}}} store := release.NewDirStore(t.TempDir()) seed, public, _ := release.GenerateKey() priv, _ := release.ParseSigningKey(seed, "test") pub, _ := release.ParsePublicKey(public, "test") for _, v := range []string{"aaaaaaa", "bbbbbbb"} { m := release.Manifest{Schema: 1, App: rt.App, Version: v, Kind: "binary", Capabilities: set, Artifacts: map[string]release.Artifact{runtimePlatform(): {}}} if err := release.Ship(t.Context(), store, release.OpsAccount, m, map[string][]byte{runtimePlatform(): []byte(v)}); err != nil { t.Fatal(err) } } promote := func(v string) { t.Helper() if err := release.Promote(t.Context(), store, priv, release.OpsAccount, rt.App, rt.Channel, v); err != nil { t.Fatal(err) } } adopt := func() { t.Helper() if err := release.Pass(t.Context(), reg, store, pub, opt, nil, release.WithCapabilities(o)); err != nil { t.Fatal(err) } } promote("aaaaaaa") adopt() if v, _ := release.LiveVersion(opt, rt.Host); v != "aaaaaaa" { t.Fatal("no-census adoption refused", v) } if err := capabilityPass(reg, opt, o); err != nil { t.Fatal(err) } svc, sock := readDropIns(t, o, rt.Host) if sock == "" { t.Fatal("legacy fixture made no drop-in") } if err := os.Mkdir("/var/lib/carlos-claims", 0700); err != nil { t.Fatal(err) } defer os.RemoveAll("/var/lib/carlos-claims") state, err := rootstate.Open(rootparticipation.Namespace, true, false) if err != nil { t.Fatal(err) } defer state.Close() if err = state.Write("census.json", []byte(`{"schema":1}`)); err != nil { t.Fatal(err) } callbacks := 0 o.Authorize = func() error { callbacks++; return nil } promote("bbbbbbb") for _, grant := range []string{"host-role", "doc-engine", "", "port:25,port:587"} { t.Run(grant, func(t *testing.T) { current, err := reg.Get(rt.Host) if err != nil || current == nil { t.Fatal(err) } if err := reg.SetCaps(rt.Host, current.Caps, grant); err != nil { t.Fatal(err) } effects.calls, effects.users = nil, nil if err := capabilityPass(reg, opt, o); err != nil { t.Fatal(err) } adopt() a, b := readDropIns(t, o, rt.Host) if a != svc || b != sock || len(effects.calls) != 0 || len(effects.users) != 0 || callbacks != 0 { t.Fatal("census permitted unit mutation", effects) } if v, _ := release.LiveVersion(opt, rt.Host); v != "aaaaaaa" { t.Fatal("refused adoption repointed", v) } }) } guarded := o if err := caps.Restore(guarded, caps.Snapshot{Host: rt.Host}); err == nil { t.Fatal("restore bypass") } if err := caps.Restart(guarded, caps.Plan{Host: rt.Host}); err == nil { t.Fatal("restart bypass") } for _, hostile := range []string{"corrupt", "renamed", "erased"} { t.Run(hostile, func(t *testing.T) { path := filepath.Join(rootparticipation.Namespace, "census.json") if hostile == "corrupt" { if err := os.WriteFile(path, []byte("corrupt"), 0600); err != nil { t.Fatal(err) } } else { binary, err := os.Open(os.Args[0]) if err != nil { t.Fatal(err) } defer binary.Close() cmd := exec.Command("/proc/self/fd/3", "-test.run=^TestPlan14RootCapabilitiesBothPaths$") cmd.ExtraFiles = []*os.File{binary} cmd.Env = append(os.Environ(), "PLAN14_CAPS_HOSTILE="+hostile) cmd.SysProcAttr = &syscall.SysProcAttr{Credential: &syscall.Credential{Uid: 65534, Gid: 65534}} if out, err := cmd.CombinedOutput(); err != nil { t.Fatal(err, string(out)) } } if _, err := caps.Converge(guarded, caps.Plan{Host: rt.Host}); err == nil { t.Fatal("retained census permitted converge") } }) } a, b := readDropIns(t, o, rt.Host) if !bytes.Equal([]byte(a+b), []byte(svc+sock)) { t.Fatal("fixed unit changed") } }