package render import ( "strings" "testing" "jarl/internal/model" ) func TestViewKeys(t *testing.T) { s := model.NewState() s.Views[1] = &model.View{ID: 1, Name: "internal", Position: 0, MatchClients: []string{"homelab", "localhost"}} s.Views[2] = &model.View{ID: 2, Name: "external", Position: 1} p := Paths{ConfigDir: "/etc/bind/jarl", ZoneDir: "/var/lib/bind/jarl", CacheDir: "/var/cache/bind/jarl"} seed := []byte("0123456789abcdef0123456789abcdef") files := func(x Extras) (conf, keys string) { for _, f := range Render(s, p, x).Files { switch f.Kind { case KindConfig: conf = string(f.Content) case KindKeys: keys = string(f.Content) } } return } conf, keys := files(Extras{ViewKeySeed: seed}) for _, want := range []string{ // An earlier view mustn't take a later view's key. "match-clients {\n\t\t!key jarl-view-external;\n\t\tkey jarl-view-internal;\n\t\thomelab;\n\t\tlocalhost;\n\t};", // A view without a list matched everyone: it still does. "match-clients { key jarl-view-external; any; };", } { if !strings.Contains(conf, want) { t.Errorf("named.conf lacks\n%s\n---\n%s", want, conf) } } sec := ViewKeySecret(seed, 2) if !strings.Contains(keys, "key \"jarl-view-external\" {\n\talgorithm hmac-sha256;\n\tsecret \""+sec+"\";\n};") || !strings.Contains(keys, "jarl-view-internal") { t.Errorf("keys.conf:\n%s", keys) } // The same seed gives the same secret; another seed doesn't. if ViewKeySecret(seed, 2) != sec || ViewKeySecret([]byte("other"), 2) == sec || ViewKeySecret(seed, 1) == sec { t.Error("secrets aren't derived from the seed and the view") } // Without a seed (or without views), nothing changes. conf, keys = files(Extras{}) if strings.Contains(conf, "jarl-view-") || strings.Contains(keys, "jarl-view-") { t.Errorf("view keys without a seed:\n%s", conf) } }