Scert/backend/internal/adminconsole/invocation_linux_test.go

84 lines
2.9 KiB
Go

//go:build linux
package adminconsole
import (
"os"
"strconv"
"strings"
"testing"
)
func TestAdminCommandRequiresExplicitInteractiveStart(t *testing.T) {
tests := []struct {
command string
targets bool
allowed bool
}{
{"systemctl start Scert-admin", true, true},
{"/usr/bin/systemctl --system start Scert-admin.service --no-pager", true, true},
{"systemctl --wait --quiet start Scert-admin", true, true},
{"systemctl restart Scert-admin", true, false},
{"systemctl reload Scert-admin", true, false},
{"systemctl stop Scert-admin", true, false},
{"systemctl try-restart Scert-admin", true, false},
{"systemctl reload-or-restart Scert-admin", true, false},
{"systemctl try-reload-or-restart Scert-admin", true, false},
{"systemctl force-reload Scert-admin", true, false},
{"systemctl --no-block start Scert-admin", true, false},
{"systemctl --no-ask-password start Scert-admin", true, false},
{"systemctl --user start Scert-admin", true, false},
{"systemctl --host=other start Scert-admin", true, false},
{"systemctl start Scert-admin smail", true, false},
{"systemctl start Scert-*", true, false},
{"systemctl restart Scert-*", true, false},
{"systemctl status Scert-admin", false, false},
{"systemctl show Scert-admin", false, false},
{"systemctl list-jobs", false, false},
{"systemctl restart smail", false, false},
}
for _, test := range tests {
t.Run(test.command, func(t *testing.T) {
targets, allowed := classifyAdminCommand(strings.Fields(test.command))
if targets != test.targets || allowed != test.allowed {
t.Fatalf("target=%v allowed=%v", targets, allowed)
}
})
}
}
func TestCallerIdentityIncludesStartTimeAndTerminal(t *testing.T) {
fields := strings.Fields("S 1 123 123 34817 123 0 0 0 0 0 0 0 0 0 0 0 1 0 9000")
data := "123 (name with ) spaces) " + strings.Join(fields, " ")
caller, err := parseCallerIdentity(123, data)
if err != nil || caller.pid != 123 || caller.started != 9000 || caller.group != 123 || caller.terminal != 34817 || caller.foreground != 123 {
t.Fatalf("identity=%+v err=%v", caller, err)
}
fields[19] = "9001"
reused, err := parseCallerIdentity(123, "123 (systemctl) "+strings.Join(fields, " "))
if err != nil || reused == caller {
t.Fatal("PID 重用未被识别")
}
fields[0] = "Z"
if _, err := parseCallerIdentity(123, "123 (systemctl) "+strings.Join(fields, " ")); err == nil {
t.Fatal("僵尸进程被接受")
}
self, err := readCallerIdentity(os.Getpid())
if err != nil || self.pid != os.Getpid() || self.started == 0 {
t.Fatalf("真实进程标识读取失败:%+v %v", self, err)
}
}
func TestCallerRequiresRootIdentity(t *testing.T) {
if !rootProcessStatus("Name:\tsystemctl\nUid:\t0\t0\t0\t0\n") {
t.Fatal("root 身份未通过")
}
for index := 0; index < 4; index++ {
ids := []string{"0", "0", "0", "0"}
ids[index] = strconv.Itoa(1000)
if rootProcessStatus("Uid:\t" + strings.Join(ids, "\t")) {
t.Fatal("非 root 身份被接受")
}
}
}