// Copyright (C) 2021 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)
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)"),
},
}
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)
})
}
}