diff --git a/.gitignore b/.gitignore index 4d2d059..85eaa82 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,8 @@ /testdata/smtpserverfuzz/data/ /testdata/store/data/ /testdata/train/ +/testdata/quickstart/example-quickstart.zone +/testdata/quickstart/tmp-pebble-ca.pem /cover.out /cover.html /.go/ diff --git a/Makefile b/Makefile index 1a52f65..8657348 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ default: build build: # build early to catch syntax errors CGO_ENABLED=0 go build - CGO_ENABLED=0 go vet -tags integration ./... + CGO_ENABLED=0 go vet -tags quickstart ./... + CGO_ENABLED=0 go vet -tags quickstart quickstart_test.go ./gendoc.sh (cd http && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Admin) >http/adminapi.json (cd http && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >http/accountapi.json @@ -24,6 +25,8 @@ test-upgrade: check: staticcheck ./... staticcheck -tags integration + staticcheck -tags quickstart + GOARCH=386 CGO_ENABLED=0 go vet -tags integration ./... # having "err" shadowed is common, best to not have others check-shadow: @@ -43,8 +46,15 @@ fuzz: go test -fuzz FuzzParseRecord -fuzztime 5m ./tlsrpt go test -fuzz FuzzParseMessage -fuzztime 5m ./tlsrpt +test-integration: + docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail + -rm -r testdata/integration/data + docker-compose -f docker-compose-integration.yml run moxmail sh -c 'CGO_ENABLED=0 go test -tags integration' + docker-compose -f docker-compose-integration.yml down + +# like test-integration, but in separate steps integration-build: - docker-compose -f docker-compose-integration.yml build --no-cache moxmail + docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail integration-start: -rm -r testdata/integration/data @@ -55,8 +65,19 @@ integration-start: integration-test: CGO_ENABLED=0 go test -tags integration + +test-quickstart: + docker image build --pull -f Dockerfile -t mox_quickstart_moxmail . + docker image build --pull -f testdata/quickstart/Dockerfile.test -t mox_quickstart_test testdata/quickstart + -rm -rf testdata/quickstart/moxacmepebble/data + -rm -rf testdata/quickstart/moxmail2/data + -rm -f testdata/quickstart/tmp-pebble-ca.pem + MOX_UID=$$(id -u) docker-compose -f docker-compose-quickstart.yml run test + docker-compose -f docker-compose-quickstart.yml down --timeout 1 + + imaptest-build: - -docker-compose -f docker-compose-imaptest.yml build --no-cache mox + -docker-compose -f docker-compose-imaptest.yml build --no-cache --pull mox imaptest-run: -rm -r testdata/imaptest/data @@ -64,6 +85,7 @@ imaptest-run: docker-compose -f docker-compose-imaptest.yml run --entrypoint /usr/local/bin/imaptest imaptest host=mox port=1143 user=mjl@mox.example pass=testtest mbox=imaptest.mbox docker-compose -f docker-compose-imaptest.yml down + fmt: go fmt ./... gofmt -w -s *.go */*.go diff --git a/develop.txt b/develop.txt index e12f218..d004c45 100644 --- a/develop.txt +++ b/develop.txt @@ -85,7 +85,7 @@ Listeners: https://github.com/letsencrypt/pebble is useful for testing with ACME. Start a pebble instance that uses the localhost TLS cert/key created by cfssl for its TLS serving. Pebble generates a new CA certificate for its own use each time it -is started. Fetch it from https://localhost:14000/root, write it to a file, and +is started. Fetch it from https://localhost:15000/roots/0, write it to a file, and add it to mox.conf TLS.CA.CertFiles. See below. Setup pebble, run once: @@ -122,7 +122,7 @@ Write new CA bundle that includes pebble's temporary CA cert: export CURL_CA_BUNDLE=local/ca-bundle.pem # for curl export SSL_CERT_FILE=local/ca-bundle.pem # for go apps cat /etc/ssl/certs/ca-certificates.crt local/cfssl/ca.pem >local/ca-bundle.pem -curl https://localhost:14000/root >local/pebble/ca.pem # fetch temp pebble ca, DO THIS EVERY TIME PEBBLE IS RESTARTED! +curl https://localhost:15000/roots/0 >local/pebble/ca.pem # fetch temp pebble ca, DO THIS EVERY TIME PEBBLE IS RESTARTED! cat /etc/ssl/certs/ca-certificates.crt local/cfssl/ca.pem local/pebble/ca.pem >local/ca-bundle.pem # create new list that includes cfssl ca and temp pebble ca. rm -r local/*/data/acme/keycerts/pebble # remove existing pebble-signed certs in acme cert/key cache, they are invalid due to newly generated temp pebble ca. ``` diff --git a/docker-compose-quickstart.yml b/docker-compose-quickstart.yml new file mode 100644 index 0000000..8c4307e --- /dev/null +++ b/docker-compose-quickstart.yml @@ -0,0 +1,133 @@ +version: '3.7' +services: + # We run quickstart_test.go from this container, it connects to both mox instances. + test: + hostname: test.mox1.example + image: mox_quickstart_test + # We add our cfssl-generated CA (which is in the repo) and acme pebble CA + # (generated each time pebble starts) to the list of trusted CA's, so the TLS + # dials in quickstart_test.go succeed. + command: ["sh", "-c", "set -ex; cat /quickstart/tmp-pebble-ca.pem /quickstart/tls/ca.pem >>/etc/ssl/certs/ca-certificates.crt; go test -tags quickstart"] + volumes: + - ./.go:/.go + - ./testdata/quickstart/resolv.conf:/etc/resolv.conf + - ./testdata/quickstart:/quickstart + - .:/mox + environment: + GOCACHE: /.go/.cache/go-build + depends_on: + dns: + condition: service_healthy + # moxmail2 depends on moxacmepebble, we connect to both. + moxmail2: + condition: service_healthy + networks: + mailnet1: + ipv4_address: 172.28.1.50 + + # First mox instance that uses ACME with pebble. + moxacmepebble: + hostname: moxacmepebble.mox1.example + domainname: mox1.example + image: mox_quickstart_moxmail + environment: + MOX_UID: "${MOX_UID}" + command: ["sh", "-c", "/quickstart/moxacmepebble.sh"] + volumes: + - ./testdata/quickstart/resolv.conf:/etc/resolv.conf + - ./testdata/quickstart:/quickstart + healthcheck: + test: netstat -nlt | grep ':25 ' + interval: 1s + timeout: 1s + retries: 10 + depends_on: + dns: + condition: service_healthy + acmepebble: + condition: service_healthy + networks: + mailnet1: + ipv4_address: 172.28.1.10 + + # Second mox instance, with TLS cert/keys from files. + moxmail2: + hostname: moxmail2.mox2.example + domainname: mox2.example + image: mox_quickstart_moxmail + environment: + MOX_UID: "${MOX_UID}" + command: ["sh", "-c", "/quickstart/moxmail2.sh"] + volumes: + - ./testdata/quickstart/resolv.conf:/etc/resolv.conf + - ./testdata/quickstart:/quickstart + healthcheck: + test: netstat -nlt | grep ':25 ' + interval: 1s + timeout: 1s + retries: 10 + depends_on: + dns: + condition: service_healthy + acmepebble: + condition: service_healthy + # moxacmepebble creates tmp-pebble-ca.pem, needed by moxmail2 to trust the certificates offered by moxacmepebble. + moxacmepebble: + condition: service_healthy + networks: + mailnet1: + ipv4_address: 172.28.1.20 + + dns: + hostname: dns.example + build: + dockerfile: Dockerfile.dns + # todo: figure out how to build from dockerfile with empty context without creating empty dirs in file system. + context: testdata/quickstart + volumes: + - ./testdata/quickstart/resolv.conf:/etc/resolv.conf + - ./testdata/quickstart:/quickstart + # We start with a base example.zone, but moxacmepebble appends its records, + # followed by moxmail2. They restart unbound after appending records. + command: ["sh", "-c", "set -ex; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /quickstart/unbound.conf /etc/unbound/; chmod 755 /quickstart; chmod 644 /quickstart/*.zone; cp /quickstart/example.zone /quickstart/example-quickstart.zone; ls -ld /quickstart /quickstart/reverse.zone; unbound -d -p -v"] + healthcheck: + test: netstat -nlu | grep '172.28.1.30:53 ' + interval: 1s + timeout: 1s + retries: 10 + networks: + mailnet1: + ipv4_address: 172.28.1.30 + + # pebble is a small acme server useful for testing. It creates a new CA + # certificate each time it starts, so we go through some trouble to configure the + # certificate in moxacmepebble and moxmail2. + acmepebble: + hostname: acmepebble.example + image: docker.io/letsencrypt/pebble:v2.3.1@sha256:fc5a537bf8fbc7cc63aa24ec3142283aa9b6ba54529f86eb8ff31fbde7c5b258 + volumes: + - ./testdata/quickstart/resolv.conf:/etc/resolv.conf + - ./testdata/quickstart:/quickstart + command: ["sh", "-c", "set -ex; mount; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; pebble -config /quickstart/pebble-config.json"] + ports: + - 14000:14000 # ACME port + - 15000:15000 # Management port + healthcheck: + test: netstat -nlt | grep ':14000 ' + interval: 1s + timeout: 1s + retries: 10 + depends_on: + dns: + condition: service_healthy + networks: + mailnet1: + ipv4_address: 172.28.1.40 + +networks: + mailnet1: + driver: bridge + ipam: + driver: default + config: + - subnet: "172.28.1.0/24" diff --git a/docker-compose.yml b/docker-compose.yml index ae1652b..a2af6c1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,7 @@ version: '3.7' services: mox: - # Replace "latest" with the version you want to run, see https://r.xmox.nl/repo/mox/. + # Replace "latest" with the version you want to run, see https://r.xmox.nl/r/mox/. # Include the @sha256:... digest to ensure you get the listed image. image: r.xmox.nl/mox:latest environment: diff --git a/quickstart_test.go b/quickstart_test.go new file mode 100644 index 0000000..62c8792 --- /dev/null +++ b/quickstart_test.go @@ -0,0 +1,145 @@ +//go:build quickstart + +// Run this using docker-compose.yml, see Makefile. + +package main + +import ( + "bytes" + "crypto/tls" + "encoding/base64" + "fmt" + "os" + "strings" + "testing" + "time" + + "github.com/mjl-/mox/imapclient" + "github.com/mjl-/mox/mlog" + "github.com/mjl-/mox/mox-" + "github.com/mjl-/mox/smtpclient" +) + +var xlog = mlog.New("quickstart") + +func tcheck(t *testing.T, err error, msg string) { + t.Helper() + if err != nil { + t.Fatalf("%s: %s", msg, err) + } +} + +func TestDeliver(t *testing.T) { + mlog.Logfmt = true + + // smtpclient uses the hostname for outgoing connections. + var err error + mox.Conf.Static.HostnameDomain.ASCII, err = os.Hostname() + tcheck(t, err, "hostname") + + // Deliver submits a message over submissions, and checks with imap idle if the + // message is received by the destination mail server. + deliver := func(desthost, mailfrom, password, rcptto, imaphost, imapuser, imappassword string) { + t.Helper() + + // Connect to IMAP, execute IDLE command, which will return on deliver message. + // TLS certificates work because the container has the CA certificates configured. + imapconn, err := tls.Dial("tcp", imaphost+":993", nil) + tcheck(t, err, "dial imap") + defer imapconn.Close() + + imaperr := make(chan error, 1) + go func() { + go func() { + x := recover() + if x == nil { + return + } + imaperr <- x.(error) + }() + xcheck := func(err error, format string) { + if err != nil { + panic(fmt.Errorf("%s: %w", format, err)) + } + } + + imapc, err := imapclient.New(imapconn, false) + xcheck(err, "new imapclient") + + _, _, err = imapc.Login(imapuser, imappassword) + xcheck(err, "imap login") + + _, _, err = imapc.Select("Inbox") + xcheck(err, "imap select inbox") + + err = imapc.Commandf("", "idle") + xcheck(err, "write imap idle command") + _, _, _, err = imapc.ReadContinuation() + xcheck(err, "read imap continuation") + + done := make(chan error) + go func() { + defer func() { + x := recover() + if x != nil { + done <- fmt.Errorf("%v", x) + } + }() + untagged, err := imapc.ReadUntagged() + if err != nil { + done <- err + return + } + if _, ok := untagged.(imapclient.UntaggedExists); !ok { + done <- fmt.Errorf("expected imapclient.UntaggedExists, got %#v", untagged) + return + } + done <- nil + }() + + period := 30 * time.Second + timer := time.NewTimer(period) + defer timer.Stop() + select { + case err = <-done: + case <-timer.C: + err = fmt.Errorf("nothing within %v", period) + } + xcheck(err, "waiting for imap untagged repsonse to idle") + imaperr <- nil + }() + + conn, err := tls.Dial("tcp", desthost+":465", nil) + tcheck(t, err, "dial submission") + defer conn.Close() + + msg := fmt.Sprintf(`From: <%s> +To: <%s> +Subject: test message + +This is the message. +`, mailfrom, rcptto) + msg = strings.ReplaceAll(msg, "\n", "\r\n") + auth := bytes.Join([][]byte{nil, []byte(mailfrom), []byte(password)}, []byte{0}) + authLine := fmt.Sprintf("AUTH PLAIN %s", base64.StdEncoding.EncodeToString(auth)) + c, err := smtpclient.New(mox.Context, xlog, conn, smtpclient.TLSSkip, desthost, authLine) + tcheck(t, err, "smtp hello") + err = c.Deliver(mox.Context, mailfrom, rcptto, int64(len(msg)), strings.NewReader(msg), false, false) + tcheck(t, err, "deliver with smtp") + err = c.Close() + tcheck(t, err, "close smtpclient") + + err = <-imaperr + tcheck(t, err, "imap idle") + } + + xlog.Print("submitting email to moxacmepebble, waiting for imap notification at moxmail2, takes time because first-time sender") + t0 := time.Now() + deliver("moxacmepebble.mox1.example", "moxtest1@mox1.example", "accountpass1234", "moxtest2@mox2.example", "moxmail2.mox2.example", "moxtest2@mox2.example", "accountpass4321") + xlog.Print("success", mlog.Field("duration", time.Since(t0))) + + xlog.Print("submitting email to moxmail2, waiting for imap notification at moxacmepebble, takes time because first-time sender") + t0 = time.Now() + deliver("moxmail2.mox2.example", "moxtest2@mox2.example", "accountpass4321", "moxtest1@mox1.example", "moxacmepebble.mox1.example", "moxtest1@mox1.example", "accountpass1234") + xlog.Print("success", mlog.Field("duration", time.Since(t0))) +} diff --git a/testdata/quickstart/Dockerfile.dns b/testdata/quickstart/Dockerfile.dns new file mode 100644 index 0000000..c083d1d --- /dev/null +++ b/testdata/quickstart/Dockerfile.dns @@ -0,0 +1,2 @@ +FROM alpine:3.17 +RUN apk add unbound bind-tools mailx diff --git a/testdata/quickstart/Dockerfile.test b/testdata/quickstart/Dockerfile.test new file mode 100644 index 0000000..e615141 --- /dev/null +++ b/testdata/quickstart/Dockerfile.test @@ -0,0 +1,4 @@ +FROM golang:1-alpine AS build +WORKDIR /mox +RUN apk add make bind-tools bash unbound curl +env GOPROXY=off diff --git a/testdata/quickstart/example.zone b/testdata/quickstart/example.zone new file mode 100644 index 0000000..64377fc --- /dev/null +++ b/testdata/quickstart/example.zone @@ -0,0 +1,12 @@ +$ORIGIN example. +$TTL 5m + +@ IN SOA dns.example. webmaster.example. (1 0m 0m 0m 5m) + +@ NS dns.example. + +moxacmepebble.mox1 IN A 172.28.1.10 +moxmail2.mox2 IN A 172.28.1.20 +dns IN A 172.28.1.30 +acmepebble IN A 172.28.1.40 +test IN A 172.28.1.50 diff --git a/testdata/quickstart/moxacmepebble.sh b/testdata/quickstart/moxacmepebble.sh new file mode 100755 index 0000000..87e8d34 --- /dev/null +++ b/testdata/quickstart/moxacmepebble.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -x # print commands +set -e # exit on failed command + +apk add unbound curl + +(rm -r /tmp/mox 2>/dev/null || exit 0) # clean slate +mkdir /tmp/mox +cd /tmp/mox +mox quickstart moxtest1@mox1.example "$MOX_UID" > output.txt + +sed -i -e '/- 172.28.1.10/d' -e 's/- 0.0.0.0/- 172.28.1.10/' -e '/- ::/d' -e 's/letsencrypt:/pebble:/g' -e 's/: letsencrypt/: pebble/g' -e 's,DirectoryURL: https://acme-v02.api.letsencrypt.org/directory,DirectoryURL: https://acmepebble.example:14000/dir,' config/mox.conf +cat <>config/mox.conf + +TLS: + CA: + CertFiles: + # So certificates from moxmail2 are trusted, and pebble's certificate is trusted. + - /quickstart/tls/ca.pem +EOF + +(cat /quickstart/example.zone; sed -n '/^;/,/IN CAA/p' output.txt) >/quickstart/example-quickstart.zone +unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes + +CURL_CA_BUNDLE=/quickstart/tls/ca.pem curl -o /quickstart/tmp-pebble-ca.pem https://acmepebble.example:15000/roots/0 + +mox serve & +while true; do + if test -e data/ctl; then + echo -n accountpass1234 | mox setaccountpassword moxtest1@mox1.example + break + fi + sleep 0.1 +done +wait diff --git a/testdata/quickstart/moxmail2.sh b/testdata/quickstart/moxmail2.sh new file mode 100755 index 0000000..04ccfd0 --- /dev/null +++ b/testdata/quickstart/moxmail2.sh @@ -0,0 +1,36 @@ +#!/bin/sh +set -x # print commands +set -e # exit on failed command + +apk add unbound + +(rm -r /tmp/mox 2>/dev/null || exit 0) # clean slate +mkdir /tmp/mox +cd /tmp/mox +mox quickstart moxtest2@mox2.example "$MOX_UID" > output.txt + +sed -i -e '/- 172.28.1.20/d' -e 's/- 0.0.0.0/- 172.28.1.20/' -e '/- ::/d' -e 's,ACME: .*$,KeyCerts:\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/moxmail2.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/moxmail2-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/mox2-autoconfig.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/mox2-autoconfig-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/mox2-mtasts.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/mox2-mtasts-key.pem\n,' config/mox.conf +cat <>config/mox.conf + +TLS: + CA: + CertFiles: + # CA of our own certificates. + - /quickstart/tls/ca.pem + # CA used by moxacmepebble. + - /quickstart/tmp-pebble-ca.pem +EOF + +# A fresh file was set up by moxacmepebble. +sed -n '/^;/,/IN CAA/p' output.txt >>/quickstart/example-quickstart.zone +unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes + +mox serve & +while true; do + if test -e data/ctl; then + echo -n accountpass4321 | mox setaccountpassword moxtest2@mox2.example + break + fi + sleep 0.1 +done +wait diff --git a/testdata/quickstart/pebble-config.json b/testdata/quickstart/pebble-config.json new file mode 100644 index 0000000..1e0a4a9 --- /dev/null +++ b/testdata/quickstart/pebble-config.json @@ -0,0 +1,12 @@ +{ + "pebble": { + "listenAddress": "0.0.0.0:14000", + "managementListenAddress": "0.0.0.0:15000", + "certificate": "/quickstart/tls/acmepebble.pem", + "privateKey": "/quickstart/tls/acmepebble-key.pem", + "httpPort": 80, + "tlsPort": 443, + "ocspResponderURL": "", + "externalAccountBindingRequired": false + } +} diff --git a/testdata/quickstart/resolv.conf b/testdata/quickstart/resolv.conf new file mode 100644 index 0000000..039e06a --- /dev/null +++ b/testdata/quickstart/resolv.conf @@ -0,0 +1 @@ +nameserver 172.28.1.30 diff --git a/testdata/quickstart/reverse.zone b/testdata/quickstart/reverse.zone new file mode 100644 index 0000000..87f4ed3 --- /dev/null +++ b/testdata/quickstart/reverse.zone @@ -0,0 +1,10 @@ +$ORIGIN 28.172.in-addr.arpa. +$TTL 5m + +@ IN SOA dns.example. hostmaster.example. (1 0m 0m 0m 5m) + +10.1 IN PTR moxacmepebble.mox1.example. +20.1 IN PTR moxmail2.mox2.example. +30.1 IN PTR dns.example. +40.1 IN PTR acmepebble.example. +50.1 IN PTR test.example. diff --git a/testdata/quickstart/tls/Makefile b/testdata/quickstart/tls/Makefile new file mode 100644 index 0000000..1128c8b --- /dev/null +++ b/testdata/quickstart/tls/Makefile @@ -0,0 +1,6 @@ +default: + cfssl genkey -initca cfssl-ca-csr.json | cfssljson -bare ca + echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail2.mox2.example - | cfssljson -bare moxmail2 + echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname autoconfig.mox2.example - | cfssljson -bare mox2-autoconfig + echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname mta-sts.mox2.example - | cfssljson -bare mox2-mtasts + echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname acmepebble.example - | cfssljson -bare acmepebble diff --git a/testdata/quickstart/tls/acmepebble-key.pem b/testdata/quickstart/tls/acmepebble-key.pem new file mode 100644 index 0000000..0db3243 --- /dev/null +++ b/testdata/quickstart/tls/acmepebble-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIBN6Uqt7h2OnuUjS5PnDcCSYxUpRdv0lY8KSFZOMr2pxoAoGCCqGSM49 +AwEHoUQDQgAEGWJAbFk4aYVFUBI8/5xopAAk/5wwpdpFMwzLJqDmQMp75NkHvg1x +xBq8XB14nJ4pXD9CxsuK39vEjJQa7pygGA== +-----END EC PRIVATE KEY----- diff --git a/testdata/quickstart/tls/acmepebble.csr b/testdata/quickstart/tls/acmepebble.csr new file mode 100644 index 0000000..65abb8e --- /dev/null +++ b/testdata/quickstart/tls/acmepebble.csr @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHrMIGSAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQZYkBsWThphUVQ +Ejz/nGikACT/nDCl2kUzDMsmoOZAynvk2Qe+DXHEGrxcHXicnilcP0LGy4rf28SM +lBrunKAYoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHREEFjAUghJhY21lcGViYmxl +LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAI6/U6z4muc4KdeQOu6EHsWmdnFB +0g0+1jUvO7Cx8Lc6AiB9YmIoVsqVlFzXPDQsA85o6kllz16fWaFlYx9r7nG2hQ== +-----END CERTIFICATE REQUEST----- diff --git a/testdata/quickstart/tls/acmepebble.pem b/testdata/quickstart/tls/acmepebble.pem new file mode 100644 index 0000000..08096ef --- /dev/null +++ b/testdata/quickstart/tls/acmepebble.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBszCCAVmgAwIBAgIUH6qZrwVtV5tLNTekatsWnltvsXMwCgYIKoZIzj0EAwIw +FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1 +MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQZYkBsWThphUVQ +Ejz/nGikACT/nDCl2kUzDMsmoOZAynvk2Qe+DXHEGrxcHXicnilcP0LGy4rf28SM +lBrunKAYo4GYMIGVMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD +ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBShvR99VjgiaOFM4yaSUSBYDR+j0DAf +BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAgBgNVHREBAf8EFjAUghJh +Y21lcGViYmxlLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAKP2VOEt3kJi9FXd +IHTXfWwXSkMlniehO+jxYt448f8eAiAuXS25BJ09ztOUKNmpeu95MB6FXoReI2rW +LHHy2x6k0A== +-----END CERTIFICATE----- diff --git a/testdata/quickstart/tls/ca-key.pem b/testdata/quickstart/tls/ca-key.pem new file mode 100644 index 0000000..204a114 --- /dev/null +++ b/testdata/quickstart/tls/ca-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIGDc32mcAt+9t3WmJvmeCLZK9aDjD6CrLjOvZx4zlRzoAoGCCqGSM49 +AwEHoUQDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3HjsP7zi +e6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3A== +-----END EC PRIVATE KEY----- diff --git a/testdata/quickstart/tls/ca.csr b/testdata/quickstart/tls/ca.csr new file mode 100644 index 0000000..8d1a5d7 --- /dev/null +++ b/testdata/quickstart/tls/ca.csr @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHzMIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs +P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KAiMCAGCSqGSIb3DQEJDjETMBEw +DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAuAJlvbFItRqBOHMV +aqUz2HNGocVLeeBjY9yWvI//Mo0CIC3Lzbh32xwaBwASggudm1OVAhDcvfzVJE68 ++INvsUeP +-----END CERTIFICATE REQUEST----- diff --git a/testdata/quickstart/tls/ca.pem b/testdata/quickstart/tls/ca.pem new file mode 100644 index 0000000..40b8495 --- /dev/null +++ b/testdata/quickstart/tls/ca.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBcjCCARigAwIBAgIUE8iskCUxfwqpv6F+nsXp7D4uqeYwCgYIKoZIzj0EAwIw +FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1 +MjcxNTM1MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI +KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs +P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KNCMEAwDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKUFNkPBlmKeQdvgjR0ORFnDmuTt +MAoGCCqGSM49BAMCA0gAMEUCIQCpOIZyFiHyAYZyjzj7HQSAsCeXzV/XuUXCJ+hR +R7uB4QIgUd6M84/3KdbdO7JW5W8saBh0hZ+kMhfQj5NEXy0VUtU= +-----END CERTIFICATE----- diff --git a/testdata/quickstart/tls/cfssl-ca-csr.json b/testdata/quickstart/tls/cfssl-ca-csr.json new file mode 100644 index 0000000..bfc7766 --- /dev/null +++ b/testdata/quickstart/tls/cfssl-ca-csr.json @@ -0,0 +1,10 @@ +{ + "CN": "mox test ca", + "key": { + "algo": "ecdsa", + "size": 256 + }, + "ca": { + "expiry": "262800h" + } +} diff --git a/testdata/quickstart/tls/config.json b/testdata/quickstart/tls/config.json new file mode 100644 index 0000000..eb72f4d --- /dev/null +++ b/testdata/quickstart/tls/config.json @@ -0,0 +1,17 @@ +{ + "signing": { + "default": { + "expiry": "262800h" + }, + "profiles": { + "server": { + "expiry": "262800h", + "usages": [ + "signing", + "key encipherment", + "server auth" + ] + } + } + } +} diff --git a/testdata/quickstart/tls/mox2-autoconfig-key.pem b/testdata/quickstart/tls/mox2-autoconfig-key.pem new file mode 100644 index 0000000..1d8ab2b --- /dev/null +++ b/testdata/quickstart/tls/mox2-autoconfig-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHy5xFqGl/NTWocu7HuGnnYcklOK6Op4eXAwckXGjlF1oAoGCCqGSM49 +AwEHoUQDQgAEuFiWsi4NMSuphlXrk6yrfqFt5f7ER7enDraWRuOyuWTQD7l8ATj/ +00574hn+rln6gKzJQXPWPkpTDHXbV3dInw== +-----END EC PRIVATE KEY----- diff --git a/testdata/quickstart/tls/mox2-autoconfig.csr b/testdata/quickstart/tls/mox2-autoconfig.csr new file mode 100644 index 0000000..489a1cc --- /dev/null +++ b/testdata/quickstart/tls/mox2-autoconfig.csr @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHwMIGXAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4WJayLg0xK6mG +VeuTrKt+oW3l/sRHt6cOtpZG47K5ZNAPuXwBOP/TTnviGf6uWfqArMlBc9Y+SlMM +ddtXd0ifoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZghdhdXRvY29uZmln +Lm1veDIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiAbOqLdDtMvr7dV6P2FQyyN +AwDBEvNCdPnVWh3Uqja50gIhAJBow5blk9EXyUHK8oJll4skRi+SveegxpFh9nQ3 +mMAn +-----END CERTIFICATE REQUEST----- diff --git a/testdata/quickstart/tls/mox2-autoconfig.pem b/testdata/quickstart/tls/mox2-autoconfig.pem new file mode 100644 index 0000000..8fe1f0e --- /dev/null +++ b/testdata/quickstart/tls/mox2-autoconfig.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBuDCCAV6gAwIBAgIUSvk4EW3Uka5Xxccd9wHAUj7elA0wCgYIKoZIzj0EAwIw +FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1 +MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4WJayLg0xK6mG +VeuTrKt+oW3l/sRHt6cOtpZG47K5ZNAPuXwBOP/TTnviGf6uWfqArMlBc9Y+SlMM +ddtXd0ifo4GdMIGaMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD +ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBR6ffFYYDYERyNXrOhAj09nqV6ZBzAf +BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAlBgNVHREBAf8EGzAZghdh +dXRvY29uZmlnLm1veDIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiA5NZwu8Zjo +Ff1Z6nxi/i1lrhLOMveeMl0Ts01YBovZHAIhAN8JGT8k5oklXDP/e5JkwtGhILXW +Ug8Z9yi0Vl+xA0Ol +-----END CERTIFICATE----- diff --git a/testdata/quickstart/tls/mox2-mtasts-key.pem b/testdata/quickstart/tls/mox2-mtasts-key.pem new file mode 100644 index 0000000..efb4a1e --- /dev/null +++ b/testdata/quickstart/tls/mox2-mtasts-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPVpcRBI+sxcVLvFqalSth1Tr9ZZMwE+Mzyq8EVNcglhoAoGCCqGSM49 +AwEHoUQDQgAEG0S9ixtgwHXg5HxiHFdH/IRRZub0V6a4GN+eWtGyn1aFxrefEs/W +RqviSr+3qpdPXiWZdnZQTqVeEyo4zlTjGQ== +-----END EC PRIVATE KEY----- diff --git a/testdata/quickstart/tls/mox2-mtasts.csr b/testdata/quickstart/tls/mox2-mtasts.csr new file mode 100644 index 0000000..0395bf8 --- /dev/null +++ b/testdata/quickstart/tls/mox2-mtasts.csr @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHtMIGUAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQbRL2LG2DAdeDk +fGIcV0f8hFFm5vRXprgY355a0bKfVoXGt58Sz9ZGq+JKv7eql09eJZl2dlBOpV4T +KjjOVOMZoDIwMAYJKoZIhvcNAQkOMSMwITAfBgNVHREEGDAWghRtdGEtc3RzLm1v +eDIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiEAjYGleKHNVcx+hRbgKdnp13HN +EO3quH3xKgm7W6IPKEwCIH0BaRmhfwdGYNB1i8Y5H3EQ7GhSYnLVspQ7+cyTTePr +-----END CERTIFICATE REQUEST----- diff --git a/testdata/quickstart/tls/mox2-mtasts.pem b/testdata/quickstart/tls/mox2-mtasts.pem new file mode 100644 index 0000000..962a831 --- /dev/null +++ b/testdata/quickstart/tls/mox2-mtasts.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtTCCAVugAwIBAgIUGWgukCBUZxcxA7v8gacjEfyGvI8wCgYIKoZIzj0EAwIw +FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1 +MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQbRL2LG2DAdeDk +fGIcV0f8hFFm5vRXprgY355a0bKfVoXGt58Sz9ZGq+JKv7eql09eJZl2dlBOpV4T +KjjOVOMZo4GaMIGXMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD +ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQW4kxR4eTg5wlGpy9fzbrDGM6igTAf +BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAiBgNVHREBAf8EGDAWghRt +dGEtc3RzLm1veDIuZXhhbXBsZTAKBggqhkjOPQQDAgNIADBFAiAs1JcxHA1pQCft +XkdXljlRX82cbDLLxxO0p8hzV6Ez8gIhAMEwCo+64mpO861vV0FKd/mAxFtTvRe9 +EVCJpNuTJ1dS +-----END CERTIFICATE----- diff --git a/testdata/quickstart/tls/moxmail2-key.pem b/testdata/quickstart/tls/moxmail2-key.pem new file mode 100644 index 0000000..b522361 --- /dev/null +++ b/testdata/quickstart/tls/moxmail2-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICvD+j+bji24hVIcRFrWPbQd6sXKmAuMtFUq175VY6K7oAoGCCqGSM49 +AwEHoUQDQgAEZS5yh9kP/DgN94O+4hcNsyBt+CgQc8wZAE96GEhrNk+bgqwWpfTV +3ZiKfMKCvCqj+yKzwSi/3YyMAymghBMdng== +-----END EC PRIVATE KEY----- diff --git a/testdata/quickstart/tls/moxmail2.csr b/testdata/quickstart/tls/moxmail2.csr new file mode 100644 index 0000000..995c88d --- /dev/null +++ b/testdata/quickstart/tls/moxmail2.csr @@ -0,0 +1,8 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33 +g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD +KaCEEx2eoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t +b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAP6qbRb8RikC8x5cmUix0+yO +UjFMytNaZtGMKAvGceSbAiAZ8neHjd04tJEI7Y3a5TDXtwz4D66K5CGdnMC7MRam +5w== +-----END CERTIFICATE REQUEST----- diff --git a/testdata/quickstart/tls/moxmail2.pem b/testdata/quickstart/tls/moxmail2.pem new file mode 100644 index 0000000..b1fd9b2 --- /dev/null +++ b/testdata/quickstart/tls/moxmail2.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVygAwIBAgIUaowxow/mwlT7vGZQclZFCrJFTEIwCgYIKoZIzj0EAwIw +FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1 +MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33 +g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD +KaCEEx2eo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD +ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTD3lkc5vvR1/6nkYxgmKgYA33YNjAf +BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAjBgNVHREBAf8EGTAXghVt +b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAMBmK6kEflN6 +8U/Y5EbhpCn7X3uV5Fbh59IHFJm8uK7XAiBQ0VVzueEO70TCAiGLllnpqrZq86Fa +XWoHOzoczCmZBw== +-----END CERTIFICATE----- diff --git a/testdata/quickstart/tls/readme.txt b/testdata/quickstart/tls/readme.txt new file mode 100644 index 0000000..8ebd2f9 --- /dev/null +++ b/testdata/quickstart/tls/readme.txt @@ -0,0 +1,2 @@ +For TLS, keys are generated using https://github.com/cloudflare/cfssl +These private keys are published online, don't use them for anything other than local testing. diff --git a/testdata/quickstart/unbound.conf b/testdata/quickstart/unbound.conf new file mode 100644 index 0000000..2a301b8 --- /dev/null +++ b/testdata/quickstart/unbound.conf @@ -0,0 +1,19 @@ +server: + interface: 172.28.1.30 + access-control: 0.0.0.0/0 allow + logfile: "" + domain-insecure: "example" + local-zone: "28.172.in-addr.arpa." nodefault + +remote-control: + control-enable: yes + control-interface: 0.0.0.0 + control-use-cert: no + +auth-zone: + name: "example" + zonefile: "/quickstart/example-quickstart.zone" + +auth-zone: + name: "28.172.in-addr.arpa" + zonefile: "/quickstart/reverse.zone"