mox/autotls/autotls_test.go
Mechiel Lukkien bddc8e4062
also configure acme validation with http-01, and fix a bug that caused tls cert refresh at startup to not always run
we already do acme tls-alpn-01 validation, and still require it (we could relax
this at some point). http-01 is easy to add.

the bug was that the list of acme managers and hosts to refresh was overwritten
by another listener. the listeners are a map, and we range over it, so the
order we handle them is random. if the public listener was handled first, and
an internal handler later, the list was reset again.
2023-03-10 17:55:37 +01:00

100 lines
3.7 KiB
Go

package autotls
import (
"context"
"errors"
"os"
"reflect"
"testing"
"golang.org/x/crypto/acme/autocert"
"github.com/mjl-/mox/dns"
)
func TestAutotls(t *testing.T) {
os.RemoveAll("../testdata/autotls")
os.MkdirAll("../testdata/autotls", 0770)
shutdown := make(chan struct{})
m, err := Load("test", "../testdata/autotls", "mox@localhost", "https://localhost/", shutdown)
if err != nil {
t.Fatalf("load manager: %v", err)
}
l := m.Hostnames()
if len(l) != 0 {
t.Fatalf("hostnames, got %v, expected empty list", l)
}
if err := m.HostPolicy(context.Background(), "mox.example"); err == nil || !errors.Is(err, errHostNotAllowed) {
t.Fatalf("hostpolicy, got err %v, expected errHostNotAllowed", err)
}
m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil, false)
l = m.Hostnames()
if !reflect.DeepEqual(l, []dns.Domain{{ASCII: "mox.example"}}) {
t.Fatalf("hostnames, got %v, expected single mox.example", l)
}
if err := m.HostPolicy(context.Background(), "mox.example"); err != nil {
t.Fatalf("hostpolicy, got err %v, expected no error", err)
}
if err := m.HostPolicy(context.Background(), "mox.example:80"); err != nil {
t.Fatalf("hostpolicy, got err %v, expected no error", err)
}
if err := m.HostPolicy(context.Background(), "other.mox.example"); err == nil || !errors.Is(err, errHostNotAllowed) {
t.Fatalf("hostpolicy, got err %v, expected errHostNotAllowed", err)
}
ctx := context.Background()
cache := m.Manager.Cache
if _, err := cache.Get(ctx, "mox.example"); err == nil || !errors.Is(err, autocert.ErrCacheMiss) {
t.Fatalf("cache get for absent entry: got err %v, expected autocert.ErrCacheMiss", err)
}
if err := cache.Put(ctx, "mox.example", []byte("test")); err != nil {
t.Fatalf("cache put for absent entry: got err %v, expected error", err)
}
if data, err := cache.Get(ctx, "mox.example"); err != nil || string(data) != "test" {
t.Fatalf("cache get: got err %v data %q, expected nil, 'test'", err, data)
}
if err := cache.Put(ctx, "mox.example", []byte("test2")); err != nil {
t.Fatalf("cache put for absent entry: got err %v, expected error", err)
}
if data, err := cache.Get(ctx, "mox.example"); err != nil || string(data) != "test2" {
t.Fatalf("cache get: got err %v data %q, expected nil, 'test2'", err, data)
}
if err := cache.Delete(ctx, "mox.example"); err != nil {
t.Fatalf("cache delete: got err %v, expected no error", err)
}
if _, err := cache.Get(ctx, "mox.example"); err == nil || !errors.Is(err, autocert.ErrCacheMiss) {
t.Fatalf("cache get for absent entry: got err %v, expected autocert.ErrCacheMiss", err)
}
close(shutdown)
if err := m.HostPolicy(context.Background(), "mox.example"); err == nil {
t.Fatalf("hostpolicy, got err %v, expected error due to shutdown", err)
}
key0 := m.Manager.Client.Key
m, err = Load("test", "../testdata/autotls", "mox@localhost", "https://localhost/", shutdown)
if err != nil {
t.Fatalf("load manager again: %v", err)
}
if !reflect.DeepEqual(m.Manager.Client.Key, key0) {
t.Fatalf("private key changed after reload")
}
m.shutdown = make(chan struct{})
m.SetAllowedHostnames(dns.StrictResolver{}, map[dns.Domain]struct{}{{ASCII: "mox.example"}: {}}, nil, false)
if err := m.HostPolicy(context.Background(), "mox.example"); err != nil {
t.Fatalf("hostpolicy, got err %v, expected no error", err)
}
m2, err := Load("test2", "../testdata/autotls", "mox@localhost", "https://localhost/", shutdown)
if err != nil {
t.Fatalf("load another manager: %v", err)
}
if reflect.DeepEqual(m.Manager.Client.Key, m2.Manager.Client.Key) {
t.Fatalf("private key reused between managers")
}
// Only remove in case of success.
os.RemoveAll("../testdata/autotls")
}