109 lines
3.5 KiB
Go
109 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestParseExports(t *testing.T) {
|
|
text := `# comment
|
|
/srv/media 192.0.2.0/24(rw,sync,root_squash) 198.51.100.7(ro)
|
|
"/srv/with space" -ro,sync host.example \
|
|
other.example(rw)
|
|
/srv/bare
|
|
`
|
|
got := ParseExports(text, "/etc/exports")
|
|
want := []Export{
|
|
{"/srv/media", "192.0.2.0/24", "rw,sync,root_squash", "/etc/exports", 2},
|
|
{"/srv/media", "198.51.100.7", "ro", "/etc/exports", 2},
|
|
{"/srv/with space", "host.example", "ro,sync", "/etc/exports", 3},
|
|
{"/srv/with space", "other.example", "rw", "/etc/exports", 3},
|
|
{"/srv/bare", "*", "", "/etc/exports", 5},
|
|
}
|
|
if len(got) != len(want) {
|
|
t.Fatalf("got %d, want %d: %+v", len(got), len(want), got)
|
|
}
|
|
for i := range want {
|
|
if got[i] != want[i] {
|
|
t.Errorf("export %d = %+v, want %+v", i, got[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseSMBConfLeavesSecretsOut(t *testing.T) {
|
|
text := `[global]
|
|
workgroup = WORKGROUP
|
|
passdb backend = tdbsam
|
|
; comment
|
|
[media]
|
|
comment = Media
|
|
path = /srv/media/
|
|
valid users = media
|
|
Read Only = no
|
|
force user = media
|
|
smb encrypt = required
|
|
username map script = /bin/secret
|
|
[homes]
|
|
browseable = no
|
|
`
|
|
got := ParseSMBConf(text)
|
|
if len(got) != 2 || got[0].Name != "media" || got[0].Path != "/srv/media/" {
|
|
t.Fatalf("got %+v", got)
|
|
}
|
|
if got[0].Settings["read only"] != "no" || got[0].Settings["force user"] != "media" {
|
|
t.Errorf("settings = %+v", got[0].Settings)
|
|
}
|
|
b, _ := json.Marshal(got)
|
|
for _, leak := range []string{"tdbsam", "WORKGROUP", "/bin/secret"} {
|
|
if strings.Contains(string(b), leak) {
|
|
t.Errorf("%q was answered: %s", leak, b)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExports(t *testing.T) {
|
|
f := newFake(t)
|
|
f.zfs = true
|
|
f.file("/etc/exports", "# only comments\n")
|
|
f.file("/etc/exports.d/zfs.exports", "/storage/media 192.0.2.0/24(sec=sys,rw,no_subtree_check,mountpoint)\n")
|
|
f.file("/var/lib/nfs/etab", "/storage/media\t192.0.2.0/24(rw,sync,root_squash,sec=sys)\n/old\t198.51.100.0/24(ro)\n")
|
|
f.file("/etc/samba/smb.conf", "[global]\nworkgroup = W\n[media]\npath = /storage/media/\nvalid users = media\nforce user = media\n")
|
|
f.answers["systemctl is-active nfs-server.service smb.service"] = "active\ninactive\n"
|
|
f.answers["zfs get -H -o name,property,value,source -t filesystem sharenfs,sharesmb"] =
|
|
"storage\tsharenfs\toff\tdefault\nstorage/media\tsharenfs\trw=@192.0.2.0/24\tlocal\nstorage/media\tsharesmb\ton\tlocal\n"
|
|
r := f.machine().Exports()
|
|
said := strings.Join(r.Said, "\n")
|
|
for _, want := range []string{
|
|
"nfs-server.service: active",
|
|
"smb.service: inactive",
|
|
"NFS /storage/media to 192.0.2.0/24 (sec=sys,rw,no_subtree_check,mountpoint), in /etc/exports.d/zfs.exports",
|
|
"NFS /old to 198.51.100.0/24 is live but in no exports file",
|
|
"ZFS storage/media sharenfs=rw=@192.0.2.0/24 (local)",
|
|
"SMB [media] /storage/media/, for media, writes as media",
|
|
} {
|
|
if !strings.Contains(said, want) {
|
|
t.Errorf("said lacks %q:\n%s", want, said)
|
|
}
|
|
}
|
|
if len(r.ZFS) != 2 {
|
|
t.Errorf("a share property that is off must be left out: %+v", r.ZFS)
|
|
}
|
|
}
|
|
|
|
func TestExportsUnreadableIsSaid(t *testing.T) {
|
|
r := newFake(t).machine().Exports()
|
|
notes := strings.Join(r.Notes, "\n")
|
|
for _, want := range []string{"/etc/exports: not present", "/var/lib/nfs/etab: not present", "/etc/samba/smb.conf: not present"} {
|
|
if !strings.Contains(notes, want) {
|
|
t.Errorf("notes lack %q: %s", want, notes)
|
|
}
|
|
}
|
|
if r.Services["nfs-server.service"] != "not read" {
|
|
t.Errorf("services = %+v", r.Services)
|
|
}
|
|
if !strings.Contains(strings.Join(r.Said, "\n"), "shares nothing") {
|
|
t.Errorf("said = %v", r.Said)
|
|
}
|
|
}
|