Smail/backend/cmd/smail-admin/systemd_policy_test.go
smail c9aa63fd74
Some checks are pending
Security Checks / security (push) Waiting to run
同步Smail服务权限回归断言
使systemd回归用例匹配当前为Linux插件隔离保留的root运行和文件访问能力。
2026-09-29 19:25:20 +08:00

132 lines
3.8 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestSystemdUnitIsManualStartOnly(t *testing.T) {
root := filepath.Clean(filepath.Join("..", "..", ".."))
unit, err := os.ReadFile(filepath.Join(root, "deploy", "systemd", "smail-admin.service"))
if err != nil {
t.Fatal(err)
}
content := string(unit)
for _, forbidden := range []string{
"[Install]",
"WantedBy=",
"RequiredBy=",
"Alias=",
"Restart=always",
"Restart=on-failure",
"ExecReload=",
"ReadWritePaths=/run/systemd/ask-password",
"PartOf=",
"BindsTo=",
"Wants=",
"Requires=",
"Upholds=",
"PropagatesReloadTo=",
"ReloadPropagatedFrom=",
} {
if strings.Contains(content, forbidden) {
t.Fatalf("smail-admin unit contains forbidden directive %q", forbidden)
}
}
for _, required := range []string{
"Type=oneshot",
"RemainAfterExit=no",
"Requisite=smail.service",
"Restart=no",
"PrivateNetwork=true",
"RestrictAddressFamilies=AF_UNIX",
"KillMode=mixed",
} {
if !strings.Contains(content, required) {
t.Fatalf("smail-admin unit is missing %q", required)
}
}
}
func TestInstallerDisablesAdminAutostart(t *testing.T) {
root := filepath.Clean(filepath.Join("..", "..", ".."))
installer, err := os.ReadFile(filepath.Join(root, "deploy", "install-systemd.sh"))
if err != nil {
t.Fatal(err)
}
content := string(installer)
for _, forbidden := range []string{
"systemctl enable smail-admin",
"systemctl enable --now smail-admin",
"systemctl start smail-admin",
"systemctl restart smail-admin",
} {
if strings.Contains(content, forbidden) {
t.Fatalf("installer contains forbidden smail-admin action %q", forbidden)
}
}
if strings.Contains(content, "systemctl preset smail-admin") {
t.Fatal("installer enables smail-admin")
}
if !strings.Contains(content, "systemctl disable smail-admin") {
t.Fatal("installer does not clear legacy smail-admin enablement")
}
}
func TestInstallerManagesProtectedEnvironmentFile(t *testing.T) {
root := filepath.Clean(filepath.Join("..", "..", ".."))
installer, err := os.ReadFile(filepath.Join(root, "deploy", "install-systemd.sh"))
if err != nil {
t.Fatal(err)
}
content := string(installer)
for _, required := range []string{
"/etc/smail/smail.env",
"install -d -o root -g root -m 0750 /etc/smail",
"if [ ! -e /etc/smail/smail.env ]; then",
"'SMAIL_ROOT=/opt/smail'",
"chmod 0600 /etc/smail/smail.env",
"cp -p -- /etc/smail/smail.env \"$backup_dir/smail.env\"",
} {
if !strings.Contains(content, required) {
t.Fatalf("installer is missing protected environment-file behavior %q", required)
}
}
}
func TestSmailServiceRetainsPluginIsolationCapabilities(t *testing.T) {
root := filepath.Clean(filepath.Join("..", "..", ".."))
unit, err := os.ReadFile(filepath.Join(root, "deploy", "systemd", "smail.service"))
if err != nil {
t.Fatal(err)
}
content := string(unit)
for _, required := range []string{
"User=root",
"Group=root",
"EnvironmentFile=/etc/smail/smail.env",
"NoNewPrivileges=true",
"AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER",
"CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SYS_CHROOT CAP_SETUID CAP_SETGID CAP_CHOWN CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER",
} {
if !strings.Contains(content, required) {
t.Fatalf("smail unit is missing %q", required)
}
}
usesEnvironmentFile := false
for _, line := range strings.Split(content, "\n") {
if strings.TrimSpace(line) == "EnvironmentFile=/etc/smail/smail.env" {
usesEnvironmentFile = true
break
}
}
if !usesEnvironmentFile {
t.Fatal("smail unit must define EnvironmentFile as a standalone directive")
}
if strings.Count(content, "CAP_NET_BIND_SERVICE") != 2 {
t.Fatal("smail unit does not retain the expected bind capability entries")
}
}