// Copyright (C) 2021-2024 Simon Ruderich // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . package config import ( "fmt" "io/fs" "os" "testing" "ruderich.org/simon/safcm" "ruderich.org/simon/safcm/testutil" ) func TestLoadPermissions(t *testing.T) { cwd, err := os.Getwd() if err != nil { t.Fatal(err) } defer os.Chdir(cwd) //nolint:errcheck err = os.Chdir("../testdata/project") if err != nil { t.Fatal(err) } tests := []struct { group string exp map[string]*safcm.File expErr error }{ { "empty", nil, nil, }, { "group", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755 | fs.ModeSetgid, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/.hidden": { Path: "/etc/.hidden", Mode: 0100 | fs.ModeSetuid | fs.ModeSetgid | fs.ModeSticky, Uid: -1, Gid: -1, Data: []byte("..."), }, "/etc/motd": { Path: "/etc/motd", Mode: 0644, Uid: -1, Gid: -1, Data: []byte(`Welcome to {{- if .IsHost "host1.example.org"}} Host ONE {{- else if "host2"}} Host TWO {{- end}} {{if .InGroup "detected_linux"}} This is GNU/Linux host {{end}} {{if .InGroup "detected_freebsd"}} This is FreeBSD host {{end}} {{if .InGroup "all"}} all {{end}} {{if .InGroup "host1.example.org"}} host1.example.org {{end}} {{if .InGroup "host2"}} host2 {{end}} {{if .InGroup "host3.example.net"}} host3.example.net {{end}} `), }, "/etc/rc.local": { Path: "/etc/rc.local", Mode: 0700, Uid: -1, Gid: -1, Data: []byte("#!/bin/sh\n"), }, "/etc/resolv.conf": { Path: "/etc/resolv.conf", Mode: 0641, User: "user", Uid: -1, Group: "group", Gid: -1, Data: []byte("nameserver ::1\n"), }, "/etc/test": { Path: "/etc/test", Mode: fs.ModeSymlink | 0777, Uid: -1, Gid: -1, Data: []byte("doesnt-exist"), }, }, nil, }, { "permissions-invalid-execute", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/rc.local": { Path: "/etc/rc.local", Mode: 0755, Uid: -1, Gid: -1, Data: []byte("#!/bin/sh\n"), }, }, fmt.Errorf("permissions-invalid-execute/permissions.yaml: \"/etc/rc.local\": trying to remove +x from file, manually chmod -x in files/"), }, { "permissions-invalid-line", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/resolv.conf": { Path: "/etc/resolv.conf", Mode: 0644, Uid: -1, Gid: -1, Data: []byte("nameserver ::1\n"), }, }, fmt.Errorf("permissions-invalid-line/permissions.yaml: invalid line \"invalid line\" (expected [ ])"), }, { "permissions-invalid-path", nil, fmt.Errorf("permissions-invalid-path/permissions.yaml: \"/does/not/exist\" does not exist in files/"), }, { "permissions-invalid-permission", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/resolv.conf": { Path: "/etc/resolv.conf", Mode: 0644, Uid: -1, Gid: -1, Data: []byte("nameserver ::1\n"), }, }, fmt.Errorf("permissions-invalid-permission/permissions.yaml: invalid permission \"u=rwg=r\" (expected e.g. \"0644\" or \"01777\")"), }, { "permissions-invalid-permission-int", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/resolv.conf": { Path: "/etc/resolv.conf", Mode: 0644, Uid: -1, Gid: -1, Data: []byte("nameserver ::1\n"), }, }, fmt.Errorf("permissions-invalid-permission-int/permissions.yaml: invalid permission 066066 (expected e.g. 0644 or 01777)"), }, { "permissions-invalid-permission-negative", map[string]*safcm.File{ "/": { Path: "/", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc": { Path: "/etc", Mode: fs.ModeDir | 0755, Uid: -1, Gid: -1, }, "/etc/resolv.conf": { Path: "/etc/resolv.conf", Mode: 0644, Uid: -1, Gid: -1, Data: []byte("nameserver ::1\n"), }, }, fmt.Errorf("permissions-invalid-permission-negative/permissions.yaml: invalid permission -042 (expected e.g. 0644 or 01777)"), }, } for _, tc := range tests { t.Run(tc.group, func(t *testing.T) { // Use LoadFiles() so we work on real data and don't // make any mistakes generating it files, err := LoadFiles(tc.group) if err != nil { t.Fatalf("err = %#v, want nil", err) } err = LoadPermissions(tc.group, files) testutil.AssertEqual(t, "res", files, tc.exp) testutil.AssertErrorEqual(t, "err", err, tc.expErr) }) } }