mesh/merge-gate head 5a2bc0391054 merged into trunk ce1b97ad973d — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
mesh/repo-check head 5a2bc0391054 merged into trunk ce1b97ad973d — pass: its merge-check.sh passed
mesh/delivery delivered
159 lines
7.5 KiB
Go
159 lines
7.5 KiB
Go
package apply
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/declaration"
|
|
)
|
|
|
|
// A module that declares its own system account and a .ssh in that account's home is placed (novox/hq issue 1542):
|
|
// the account is not in the user database yet when the declaration is judged, and its home is under /var/lib.
|
|
func declaredHomeFixture(t *testing.T) (home string, user *declaration.User) {
|
|
t.Helper()
|
|
dir := t.TempDir()
|
|
passwd := filepath.Join(dir, "passwd")
|
|
if err := os.WriteFile(passwd, []byte("root:x:0:0::/root:/bin/sh\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before := passwdFile
|
|
passwdFile = passwd
|
|
t.Cleanup(func() { passwdFile = before })
|
|
home = filepath.Join(dir, "lib", "mesh-build-go")
|
|
return home, &declaration.User{ID: "mesh-build-go.account", Type: declaration.TypeUser, Name: "mesh-build-go",
|
|
Shell: "/usr/bin/nologin", Home: home}
|
|
}
|
|
|
|
// 1542/AC1: the .ssh of a declared account, owned by it, is refused by nothing.
|
|
func TestIssue1542ADeclaredAccountsSSHIsPlaced(t *testing.T) {
|
|
home, user := declaredHomeFixture(t)
|
|
ssh := &declaration.Directory{ID: "mesh-build-go.ssh-dir", Type: declaration.TypeDirectory, Path: home + "/.ssh",
|
|
Mode: "0700", Owner: "mesh-build-go"}
|
|
refused := refusedPlaces([]declaration.Resource{user, ssh})
|
|
if len(refused) != 0 {
|
|
t.Fatalf("a declared account's own .ssh was refused: %v", refused)
|
|
}
|
|
if err := (inputs{refused: refused}).refused[filepath.Clean(ssh.Path)]; err != nil {
|
|
t.Fatalf("the apply-time check refuses it: %v", err)
|
|
}
|
|
if line := JudgeDirectories(&declaration.Declaration{Resources: []declaration.Resource{user, ssh}}); strings.Contains(line, "refused already by the placement guard: ") {
|
|
t.Fatalf("the read-only judgement refuses it: %s", line)
|
|
}
|
|
}
|
|
|
|
// 1542/AC2: another account's directory below the declared home is refused as below any home, and a .ssh below
|
|
// no home of the machine or the declaration is refused with today's words.
|
|
func TestIssue1542OnlyTheDeclaredAccountsOwnIsPlaced(t *testing.T) {
|
|
home, user := declaredHomeFixture(t)
|
|
other := &declaration.Directory{ID: "notes.ssh-dir", Type: declaration.TypeDirectory, Path: home + "/.ssh",
|
|
Mode: "0700", Owner: "intruder"}
|
|
refused := refusedPlaces([]declaration.Resource{user, other})
|
|
err := refused[filepath.Clean(other.Path)]
|
|
if err == nil || !strings.Contains(err.Error(), "below mesh-build-go's home and declared intruder's") {
|
|
t.Fatalf("another account's directory below a declared home: %v", err)
|
|
}
|
|
stray := &declaration.Directory{ID: "mesh-build-go.ssh-dir", Type: declaration.TypeDirectory,
|
|
Path: filepath.Join(filepath.Dir(home), "elsewhere", ".ssh"), Mode: "0700", Owner: "mesh-build-go"}
|
|
refused = refusedPlaces([]declaration.Resource{user, stray})
|
|
err = refused[filepath.Clean(stray.Path)]
|
|
if err == nil || !strings.Contains(err.Error(), "a .ssh directory is placed only below its account's home, as that account's") {
|
|
t.Fatalf("a .ssh below no home: %v", err)
|
|
}
|
|
// Not a .ssh: a root-owned directory below the declared home is placed exactly as on main.
|
|
data := &declaration.Directory{ID: "mesh-build-go.data", Type: declaration.TypeDirectory, Path: home + "/data",
|
|
Mode: "0755", Owner: "root"}
|
|
if refused := refusedPlaces([]declaration.Resource{user, data}); len(refused) != 0 {
|
|
t.Fatalf("a root-owned directory below a declared home, not a .ssh, was refused: %v", refused)
|
|
}
|
|
// And without the account declared, the same .ssh is refused as it was.
|
|
own := &declaration.Directory{ID: "mesh-build-go.ssh-dir", Type: declaration.TypeDirectory, Path: home + "/.ssh",
|
|
Mode: "0700", Owner: "mesh-build-go"}
|
|
if refusedPlaces([]declaration.Resource{own})[filepath.Clean(own.Path)] == nil {
|
|
t.Fatal("a .ssh below an account nobody makes was placed")
|
|
}
|
|
}
|
|
|
|
// 1542/AC3: a declared account is no home to anyone but the directory placement guard.
|
|
func TestIssue1542DeclaredAccountsAreNotHomesToTheOtherGuards(t *testing.T) {
|
|
home, user := declaredHomeFixture(t)
|
|
_ = refusedPlaces([]declaration.Resource{user})
|
|
if _, ok := accountsOfHomes()[home]; ok {
|
|
t.Fatal("a declared account became a home of the machine")
|
|
}
|
|
if homeAbove(home+"/.ssh") != "" {
|
|
t.Fatal("a declared account became a home for the links and the move-out")
|
|
}
|
|
}
|
|
|
|
// A declared account is added as a home and never takes one over (reviewer, issue 1542): the person's own .ssh
|
|
// stays refused to every other account, whatever a declaration says about a user.
|
|
func TestIssue1542ADeclaredAccountTakesNoExistingHome(t *testing.T) {
|
|
dir := t.TempDir()
|
|
passwd := filepath.Join(dir, "passwd")
|
|
body := "root:x:0:0::/root:/bin/sh\njochen:x:1000:1000::/home/jochen:/bin/sh\n" +
|
|
"svc:x:998:998::/var/lib/svc:/usr/bin/nologin\n"
|
|
if err := os.WriteFile(passwd, []byte(body), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before := passwdFile
|
|
passwdFile = passwd
|
|
t.Cleanup(func() { passwdFile = before })
|
|
newHome := filepath.Join(dir, "lib", "mesh-build-go")
|
|
ssh := func(path, owner string) *declaration.Directory {
|
|
return &declaration.Directory{ID: "x.ssh", Type: declaration.TypeDirectory, Path: path, Mode: "0700", Owner: owner}
|
|
}
|
|
user := func(name, home string) *declaration.User {
|
|
return &declaration.User{ID: "x.user", Type: declaration.TypeUser, Name: name, Home: home}
|
|
}
|
|
// A declared user over a person's home, whoever it is named for.
|
|
for _, name := range []string{"evil", "postgres", "root"} {
|
|
d := ssh("/home/jochen/.ssh", name)
|
|
if refusedPlaces([]declaration.Resource{user(name, "/home/jochen"), d})[d.Path] == nil {
|
|
t.Errorf("%s, declared over jochen's home, was given jochen's .ssh", name)
|
|
}
|
|
}
|
|
// A declared home below a person's home.
|
|
d := ssh("/home/jochen/sub/.ssh", "evil")
|
|
if refusedPlaces([]declaration.Resource{user("evil", "/home/jochen/sub"), d})[d.Path] == nil {
|
|
t.Error("a home declared below jochen's home was counted")
|
|
}
|
|
// A name the machine has already, declared with another home: that is not its home.
|
|
d = ssh(newHome+"/e/.ssh", "svc")
|
|
if refusedPlaces([]declaration.Resource{user("svc", newHome+"/e"), d})[d.Path] == nil {
|
|
t.Error("an existing account's declared home was counted")
|
|
}
|
|
// A number is no name: chown -1 leaves the owner as it was.
|
|
for _, owner := range []string{"-1", "-1:0", "0", "1001"} {
|
|
d := ssh(newHome+"/.ssh", owner)
|
|
if refusedPlaces([]declaration.Resource{user("mesh-build-go", newHome), d})[d.Path] == nil {
|
|
t.Errorf("owner %q was placed below a declared home", owner)
|
|
}
|
|
}
|
|
// And the account that is new, by name, still is.
|
|
d = ssh(newHome+"/.ssh", "mesh-build-go")
|
|
if got := refusedPlaces([]declaration.Resource{user("mesh-build-go", newHome), d}); len(got) != 0 {
|
|
t.Errorf("a new account's own .ssh was refused: %v", got)
|
|
}
|
|
}
|
|
|
|
// The account the mesh made, as declared, is judged the same at the next apply (issue 1542): once it is in the
|
|
// user database with exactly the declared home, its .ssh is still placed.
|
|
func TestIssue1542TheAccountTheMeshMadeIsStillPlacedAtTheNextApply(t *testing.T) {
|
|
home, user := declaredHomeFixture(t)
|
|
ssh := &declaration.Directory{ID: "mesh-build-go.ssh-dir", Type: declaration.TypeDirectory, Path: home + "/.ssh",
|
|
Mode: "0700", Owner: "mesh-build-go"}
|
|
resources := []declaration.Resource{user, ssh}
|
|
if got := refusedPlaces(resources); len(got) != 0 {
|
|
t.Fatalf("first apply, the account not yet made: %v", got)
|
|
}
|
|
body := "root:x:0:0::/root:/bin/sh\nmesh-build-go:x:998:998::" + home + ":/usr/bin/nologin\n"
|
|
if err := os.WriteFile(passwdFile, []byte(body), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := refusedPlaces(resources); len(got) != 0 {
|
|
t.Fatalf("second apply, the account made as declared: %v", got)
|
|
}
|
|
}
|