merge docker-compose-based quickstart and integration tests into a single integration test

the two were so similar it made sense to just have one that tests all. saves
building docker images.
This commit is contained in:
Mechiel Lukkien 2023-07-23 23:32:02 +02:00
parent dcb0f0a82c
commit f9e261e0fb
No known key found for this signature in database
60 changed files with 300 additions and 882 deletions

5
.gitignore vendored
View file

@ -11,7 +11,6 @@
/testdata/imap/data/ /testdata/imap/data/
/testdata/imapserverfuzz/data/ /testdata/imapserverfuzz/data/
/testdata/imaptest/data/ /testdata/imaptest/data/
/testdata/integration/data/
/testdata/junk/*.bloom /testdata/junk/*.bloom
/testdata/junk/*.db /testdata/junk/*.db
/testdata/queue/data/ /testdata/queue/data/
@ -24,8 +23,8 @@
/testdata/smtpserverfuzz/data/ /testdata/smtpserverfuzz/data/
/testdata/store/data/ /testdata/store/data/
/testdata/train/ /testdata/train/
/testdata/quickstart/example-quickstart.zone /testdata/integration/example-integration.zone
/testdata/quickstart/tmp-pebble-ca.pem /testdata/integration/tmp-pebble-ca.pem
/cover.out /cover.out
/cover.html /cover.html
/.go/ /.go/

View file

@ -5,7 +5,6 @@ build:
CGO_ENABLED=0 go build CGO_ENABLED=0 go build
CGO_ENABLED=0 go vet ./... CGO_ENABLED=0 go vet ./...
CGO_ENABLED=0 go vet -tags integration CGO_ENABLED=0 go vet -tags integration
CGO_ENABLED=0 go vet -tags quickstart
./gendoc.sh ./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 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 (cd http && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >http/accountapi.json
@ -26,7 +25,6 @@ test-upgrade:
check: check:
staticcheck ./... staticcheck ./...
staticcheck -tags integration staticcheck -tags integration
staticcheck -tags quickstart
GOARCH=386 CGO_ENABLED=0 go vet ./... GOARCH=386 CGO_ENABLED=0 go vet ./...
# having "err" shadowed is common, best to not have others # having "err" shadowed is common, best to not have others
@ -47,34 +45,15 @@ fuzz:
go test -fuzz FuzzParseRecord -fuzztime 5m ./tlsrpt go test -fuzz FuzzParseRecord -fuzztime 5m ./tlsrpt
go test -fuzz FuzzParseMessage -fuzztime 5m ./tlsrpt go test -fuzz FuzzParseMessage -fuzztime 5m ./tlsrpt
test-integration: test-integration:
docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail docker image build --pull -f Dockerfile -t mox_integration_moxmail .
-rm -r testdata/integration/data docker image build --pull -f testdata/integration/Dockerfile.test -t mox_integration_test testdata/integration
docker-compose -f docker-compose-integration.yml run moxmail sh -c 'CGO_ENABLED=0 go test -tags integration' -rm -rf testdata/integration/moxacmepebble/data
docker-compose -f docker-compose-integration.yml down -rm -rf testdata/integration/moxmail2/data
-rm -f testdata/integration/tmp-pebble-ca.pem
# like test-integration, but in separate steps MOX_UID=$$(id -u) docker-compose -f docker-compose-integration.yml run test
integration-build: docker-compose -f docker-compose-integration.yml down --timeout 1
docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail
integration-start:
-rm -r testdata/integration/data
-docker-compose -f docker-compose-integration.yml run moxmail /bin/bash
docker-compose -f docker-compose-integration.yml down
# run from within "make 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: imaptest-build:

View file

@ -166,12 +166,10 @@ testing purposes.
- Update features & roadmap in README.md - Update features & roadmap in README.md
- Write release notes, use instructions from updating.txt. - Write release notes, use instructions from updating.txt.
- Build and run tests with previous major Go release. - Build and run tests with previous major Go release.
- Run all (integration) tests, including with race detector. - Run tests, including with race detector.
- Test upgrades. - Run integration and upgrade tests.
- Run fuzzing tests for a while. - Run fuzzing tests for a while.
- Deploy to test environment. Test the update instructions. - Deploy to test environment. Test the update instructions.
- Test localserve.
- Generate a config with quickstart, check if it results in a working setup.
- Send and receive email through the major webmail providers, check headers. - Send and receive email through the major webmail providers, check headers.
- Send and receive email with imap4/smtp clients. - Send and receive email with imap4/smtp clients.
- Check DNS check admin page. - Check DNS check admin page.

View file

@ -1,19 +1,46 @@
version: '3.7' version: '3.7'
services: services:
moxmail: # We run integration_test.go from this container, it connects to both mox instances.
# todo: understand why hostname and/or domainname don't have any influence on the reverse dns set up by docker, requiring us to use our own /etc/resolv.conf... test:
hostname: moxmail1.mox1.example hostname: test.mox1.example
domainname: mox1.example image: mox_integration_test
build: # We add our cfssl-generated CA (which is in the repo) and acme pebble CA
dockerfile: Dockerfile.moxmail # (generated each time pebble starts) to the list of trusted CA's, so the TLS
context: testdata/integration # dials in integration_test.go succeed.
command: ["sh", "-c", "set -ex; cat /integration/tmp-pebble-ca.pem /integration/tls/ca.pem >>/etc/ssl/certs/ca-certificates.crt; go test -tags integration"]
volumes: volumes:
- ./.go:/.go - ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf - ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
- ./testdata/integration/moxsubmit.conf:/etc/moxsubmit.conf - ./testdata/integration/moxsubmit.conf:/etc/moxsubmit.conf
- .:/mox - .:/mox
environment: environment:
GOCACHE: /.go/.cache/go-build GOCACHE: /.go/.cache/go-build
depends_on:
dns:
condition: service_healthy
# moxmail2 depends on moxacmepebble, we connect to both.
moxmail2:
condition: service_healthy
postfixmail:
condition: service_healthy
localserve:
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_integration_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/integration/moxacmepebble.sh"]
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
healthcheck: healthcheck:
test: netstat -nlt | grep ':25 ' test: netstat -nlt | grep ':25 '
interval: 1s interval: 1s
@ -22,17 +49,64 @@ services:
depends_on: depends_on:
dns: dns:
condition: service_healthy condition: service_healthy
postfixmail: acmepebble:
condition: service_healthy
localserve:
condition: service_healthy condition: service_healthy
networks: networks:
mailnet1: mailnet1:
ipv4_address: 172.28.1.10 ipv4_address: 172.28.1.10
mailnet2:
ipv4_address: 172.28.2.10 # Second mox instance, with TLS cert/keys from files.
mailnet3: moxmail2:
ipv4_address: 172.28.3.10 hostname: moxmail2.mox2.example
domainname: mox2.example
image: mox_integration_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/integration/moxmail2.sh"]
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
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
localserve:
hostname: localserve.mox1.example
domainname: mox1.example
build:
dockerfile: Dockerfile.moxmail
context: testdata/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; go run . -- localserve -ip 172.28.1.60"]
volumes:
- ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
healthcheck:
test: netstat -nlt | grep ':1025 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.60
postfixmail: postfixmail:
hostname: postfixmail.postfix.example hostname: postfixmail.postfix.example
@ -54,32 +128,7 @@ services:
condition: service_healthy condition: service_healthy
networks: networks:
mailnet1: mailnet1:
ipv4_address: 172.28.1.20 ipv4_address: 172.28.1.70
localserve:
hostname: localserve.mox1.example
domainname: mox1.example
build:
dockerfile: Dockerfile.moxmail
context: testdata/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; go run . -- localserve -ip 172.28.1.50"]
volumes:
- ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
healthcheck:
test: netstat -nlt | grep ':1025 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.50
dns: dns:
hostname: dns.example hostname: dns.example
@ -90,7 +139,9 @@ services:
volumes: volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf - ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration - ./testdata/integration:/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /integration/unbound.conf /integration/*.zone /etc/unbound/; unbound -d -p -v"] # 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 /integration/unbound.conf /etc/unbound/; chmod 755 /integration; chmod 644 /integration/*.zone; cp /integration/example.zone /integration/example-integration.zone; ls -ld /integration /integration/reverse.zone; unbound -d -p -v"]
healthcheck: healthcheck:
test: netstat -nlu | grep '172.28.1.30:53 ' test: netstat -nlu | grep '172.28.1.30:53 '
interval: 1s interval: 1s
@ -100,6 +151,31 @@ services:
mailnet1: mailnet1:
ipv4_address: 172.28.1.30 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/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
command: ["sh", "-c", "set -ex; mount; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; pebble -config /integration/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: networks:
mailnet1: mailnet1:
driver: bridge driver: bridge
@ -107,15 +183,3 @@ networks:
driver: default driver: default
config: config:
- subnet: "172.28.1.0/24" - subnet: "172.28.1.0/24"
mailnet2:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.28.2.0/24"
mailnet3:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.28.3.0/24"

View file

@ -1,133 +0,0 @@
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"

View file

@ -1,11 +1,10 @@
//go:build integration //go:build integration
// Run this using docker-compose.yml, see Makefile.
package main package main
import ( import (
"context" "context"
"crypto/tls"
"fmt" "fmt"
"net" "net"
"os" "os"
@ -20,57 +19,25 @@ import (
"github.com/mjl-/mox/mox-" "github.com/mjl-/mox/mox-"
"github.com/mjl-/mox/sasl" "github.com/mjl-/mox/sasl"
"github.com/mjl-/mox/smtpclient" "github.com/mjl-/mox/smtpclient"
"github.com/mjl-/mox/store"
) )
var ctxbg = context.Background() var ctxbg = context.Background()
func tcheck(t *testing.T, err error, errmsg string) { func tcheck(t *testing.T, err error, errmsg string) {
if err != nil { if err != nil {
t.Helper()
t.Fatalf("%s: %s", errmsg, err) t.Fatalf("%s: %s", errmsg, err)
} }
} }
// Submit a message to mox, which sends it to postfix, which forwards back to mox.
// We check if we receive the message.
func TestDeliver(t *testing.T) { func TestDeliver(t *testing.T) {
xlog := mlog.New("integration")
mlog.Logfmt = true mlog.Logfmt = true
log := mlog.New("test")
// Remove state. hostname, err := os.Hostname()
os.RemoveAll("testdata/integration/data") tcheck(t, err, "hostname")
os.MkdirAll("testdata/integration/data", 0750) ourHostname, err := dns.ParseDomain(hostname)
tcheck(t, err, "parse hostname")
// Cleanup afterwards, these are owned by root, annoying to have around due to
// permission errors.
defer os.RemoveAll("testdata/integration/data")
// Load mox config.
mox.ConfigStaticPath = "testdata/integration/config/mox.conf"
if errs := mox.LoadConfig(ctxbg, true, false); len(errs) > 0 {
t.Fatalf("loading mox config: %v", errs)
}
// Create new accounts
createAccount := func(email, password string) {
t.Helper()
acc, _, err := store.OpenEmail(email)
tcheck(t, err, "open account")
err = acc.SetPassword(password)
tcheck(t, err, "setting password")
err = acc.Close()
tcheck(t, err, "closing account")
}
createAccount("moxtest1@mox1.example", "pass1234")
createAccount("moxtest2@mox2.example", "pass1234")
createAccount("moxtest3@mox3.example", "pass1234")
// Start mox.
const mtastsdbRefresher = false
const skipForkExec = true
err := start(mtastsdbRefresher, skipForkExec)
tcheck(t, err, "starting mox")
// Single update from IMAP IDLE. // Single update from IMAP IDLE.
type idleResponse struct { type idleResponse struct {
@ -78,30 +45,42 @@ func TestDeliver(t *testing.T) {
err error err error
} }
testDeliver := func(checkTime bool, imapaddr, imapuser, imappass string, fn func()) { // Deliver submits a message over submissions, and checks with imap idle if the
// message is received by the destination mail server.
deliver := func(checkTime bool, dialtls bool, imaphost, imapuser, imappassword string, send func()) {
t.Helper() t.Helper()
// Make IMAP connection, we'll wait for a delivery notification with IDLE. // Connect to IMAP, execute IDLE command, which will return on deliver message.
imapconn, err := net.Dial("tcp", imapaddr) // TLS certificates work because the container has the CA certificates configured.
tcheck(t, err, "dial imap server") var imapconn net.Conn
var err error
if dialtls {
imapconn, err = tls.Dial("tcp", imaphost, nil)
} else {
imapconn, err = net.Dial("tcp", imaphost)
}
tcheck(t, err, "dial imap")
defer imapconn.Close() defer imapconn.Close()
client, err := imapclient.New(imapconn, false)
imapc, err := imapclient.New(imapconn, false)
tcheck(t, err, "new imapclient") tcheck(t, err, "new imapclient")
_, _, err = client.Login(imapuser, imappass)
tcheck(t, err, "imap client login") _, _, err = imapc.Login(imapuser, imappassword)
_, _, err = client.Select("inbox") tcheck(t, err, "imap login")
_, _, err = imapc.Select("Inbox")
tcheck(t, err, "imap select inbox") tcheck(t, err, "imap select inbox")
err = client.Commandf("", "idle") err = imapc.Commandf("", "idle")
tcheck(t, err, "imap idle command") tcheck(t, err, "write imap idle command")
_, _, _, err = client.ReadContinuation() _, _, _, err = imapc.ReadContinuation()
tcheck(t, err, "read imap continuation") tcheck(t, err, "read imap continuation")
idle := make(chan idleResponse) idle := make(chan idleResponse)
go func() { go func() {
for { for {
untagged, err := client.ReadUntagged() untagged, err := imapc.ReadUntagged()
idle <- idleResponse{untagged, err} idle <- idleResponse{untagged, err}
if err != nil { if err != nil {
return return
@ -109,12 +88,12 @@ func TestDeliver(t *testing.T) {
} }
}() }()
defer func() { defer func() {
err := client.Writelinef("done") err := imapc.Writelinef("done")
tcheck(t, err, "aborting idle") tcheck(t, err, "aborting idle")
}() }()
t0 := time.Now() t0 := time.Now()
fn() send()
// Wait for notification of delivery. // Wait for notification of delivery.
select { select {
@ -127,13 +106,19 @@ func TestDeliver(t *testing.T) {
if d := time.Since(t0); checkTime && d < 1*time.Second { if d := time.Since(t0); checkTime && d < 1*time.Second {
t.Fatalf("delivery took %v, but should have taken at least 1 second, the first-time sender delay", d) t.Fatalf("delivery took %v, but should have taken at least 1 second, the first-time sender delay", d)
} }
case <-time.After(5 * time.Second): case <-time.After(30 * time.Second):
t.Fatalf("timeout after 5s waiting for IMAP IDLE notification of new message, should take about 1 second") t.Fatalf("timeout after 5s waiting for IMAP IDLE notification of new message, should take about 1 second")
} }
} }
submit := func(smtphost, smtpport, mailfrom, password, rcptto string) { submit := func(dialtls bool, mailfrom, password, desthost, rcptto string) {
conn, err := net.Dial("tcp", net.JoinHostPort(smtphost, smtpport)) var conn net.Conn
var err error
if dialtls {
conn, err = tls.Dial("tcp", desthost, nil)
} else {
conn, err = net.Dial("tcp", desthost)
}
tcheck(t, err, "dial submission") tcheck(t, err, "dial submission")
defer conn.Close() defer conn.Close()
@ -145,7 +130,7 @@ This is the message.
`, mailfrom, rcptto) `, mailfrom, rcptto)
msg = strings.ReplaceAll(msg, "\n", "\r\n") msg = strings.ReplaceAll(msg, "\n", "\r\n")
auth := []sasl.Client{sasl.NewClientPlain(mailfrom, password)} auth := []sasl.Client{sasl.NewClientPlain(mailfrom, password)}
c, err := smtpclient.New(mox.Context, log, conn, smtpclient.TLSOpportunistic, mox.Conf.Static.HostnameDomain, dns.Domain{ASCII: smtphost}, auth) c, err := smtpclient.New(mox.Context, xlog, conn, smtpclient.TLSSkip, ourHostname, dns.Domain{ASCII: desthost}, auth)
tcheck(t, err, "smtp hello") tcheck(t, err, "smtp hello")
err = c.Deliver(mox.Context, mailfrom, rcptto, int64(len(msg)), strings.NewReader(msg), false, false) err = c.Deliver(mox.Context, mailfrom, rcptto, int64(len(msg)), strings.NewReader(msg), false, false)
tcheck(t, err, "deliver with smtp") tcheck(t, err, "deliver with smtp")
@ -153,18 +138,42 @@ This is the message.
tcheck(t, err, "close smtpclient") tcheck(t, err, "close smtpclient")
} }
testDeliver(true, "moxmail1.mox1.example:143", "moxtest1@mox1.example", "pass1234", func() { // Make sure moxacmepebble has a TLS certificate.
submit("moxmail1.mox1.example", "587", "moxtest1@mox1.example", "pass1234", "root@postfix.example") conn, err := tls.Dial("tcp", "moxacmepebble.mox1.example:465", nil)
}) tcheck(t, err, "dial submission")
testDeliver(true, "moxmail1.mox1.example:143", "moxtest3@mox3.example", "pass1234", func() { defer conn.Close()
submit("moxmail2.mox2.example", "587", "moxtest2@mox2.example", "pass1234", "moxtest3@mox3.example")
})
testDeliver(false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() { xlog.Print("submitting email to moxacmepebble, waiting for imap notification at moxmail2")
submit("localserve.mox1.example", "1587", "mox@localhost", "moxmoxmox", "any@any.example") t0 := time.Now()
deliver(true, true, "moxmail2.mox2.example:993", "moxtest2@mox2.example", "accountpass4321", func() {
submit(true, "moxtest1@mox1.example", "accountpass1234", "moxacmepebble.mox1.example:465", "moxtest2@mox2.example")
}) })
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
testDeliver(false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() { xlog.Print("submitting email to moxmail2, waiting for imap notification at moxacmepebble")
t0 = time.Now()
deliver(true, true, "moxacmepebble.mox1.example:993", "moxtest1@mox1.example", "accountpass1234", func() {
submit(true, "moxtest2@mox2.example", "accountpass4321", "moxmail2.mox2.example:465", "moxtest1@mox1.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to postfix, waiting for imap notification at moxacmepebble")
t0 = time.Now()
deliver(true, true, "moxacmepebble.mox1.example:993", "moxtest1@mox1.example", "accountpass1234", func() {
submit(true, "moxtest1@mox1.example", "accountpass1234", "moxacmepebble.mox1.example:465", "root@postfix.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to localserve")
t0 = time.Now()
deliver(false, false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
submit(false, "mox@localhost", "moxmoxmox", "localserve.mox1.example:1587", "moxtest1@mox1.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to localserve")
t0 = time.Now()
deliver(false, false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
cmd := exec.Command("go", "run", ".", "sendmail", "mox@localhost") cmd := exec.Command("go", "run", ".", "sendmail", "mox@localhost")
const msg = `Subject: test const msg = `Subject: test
@ -174,7 +183,9 @@ a message.
var out strings.Builder var out strings.Builder
cmd.Stdout = &out cmd.Stdout = &out
err := cmd.Run() err := cmd.Run()
log.Print("sendmail", mlog.Field("output", out.String())) xlog.Print("sendmail", mlog.Field("output", out.String()))
tcheck(t, err, "sendmail") tcheck(t, err, "sendmail")
}) })
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
} }

View file

@ -1,145 +0,0 @@
//go:build quickstart
// Run this using docker-compose.yml, see Makefile.
package main
import (
"context"
"crypto/tls"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/mjl-/mox/dns"
"github.com/mjl-/mox/imapclient"
"github.com/mjl-/mox/mlog"
"github.com/mjl-/mox/mox-"
"github.com/mjl-/mox/sasl"
"github.com/mjl-/mox/smtpclient"
)
var ctxbg = context.Background()
func tcheck(t *testing.T, err error, errmsg string) {
if err != nil {
t.Fatalf("%s: %s", errmsg, err)
}
}
func TestDeliver(t *testing.T) {
xlog := mlog.New("quickstart")
mlog.Logfmt = true
hostname, err := os.Hostname()
tcheck(t, err, "hostname")
ourHostname, err := dns.ParseDomain(hostname)
tcheck(t, err, "parse 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 response 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 := []sasl.Client{sasl.NewClientPlain(mailfrom, password)}
c, err := smtpclient.New(mox.Context, xlog, conn, smtpclient.TLSSkip, ourHostname, dns.Domain{ASCII: desthost}, auth)
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")
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")
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)))
}

View file

@ -1,4 +0,0 @@
FROM golang:1-alpine AS build
WORKDIR /mox
RUN apk add make bind-tools bash
env GOPROXY=off

View file

@ -1,83 +0,0 @@
Domains:
mox1.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
mox2.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
DKIM:
Selectors:
mox2dkim0:
Hash: sha256
DontSealHeaders: false
Headers:
- From
- To
- Subject
PrivateKeyFile: ../dkim/mox2dkim0-key.pem
Sign:
- mox2dkim0
# todo: DMARC:
# todo: MTASTS:
# todo: TLSRPT:
mox3.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
DKIM:
Selectors:
mox3dkim0:
Hash: sha256
DontSealHeaders: false
Headers:
- From
- To
- Subject
PrivateKeyFile: ../dkim/mox3dkim0-key.pem
Sign:
- mox3dkim0
Accounts:
moxtest1:
Domain: mox1.example
Destinations:
moxtest1@mox1.example: nil
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1
moxtest2:
Domain: mox2.example
Destinations:
moxtest2@mox2.example: nil
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1
moxtest3:
Domain: mox3.example
Destinations:
moxtest3@mox3.example: nil
SubjectPass:
Period: 1h
RejectsMailbox: rejects
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1

View file

@ -1,73 +0,0 @@
DataDir: ../data
LogLevel: trace
Hostname: moxmail1.mox1.example
# only for integration test, where fork & exec is skipped
User: 0
TLS:
CA:
CertFiles:
- ../tls/ca.pem
Listeners:
mox1:
IPs:
- 172.28.1.10
Hostname: moxmail1.mox1.example
SMTP:
Enabled: true
NoSTARTTLS: true
FirstTimeSenderDelay: 1s
Submission:
Enabled: true
NoRequireSTARTTLS: true
IMAP:
Enabled: true
NoRequireSTARTTLS: true
mox2:
IPs:
- 172.28.2.10
Hostname: moxmail2.mox2.example
TLS:
KeyCerts:
-
CertFile: ../tls/moxmail2.pem
KeyFile: ../tls/moxmail2-key.pem
SMTP:
Enabled: true
Submission:
Enabled: true
NoRequireSTARTTLS: true
Submissions:
Enabled: true
IMAP:
Enabled: true
IMAPS:
Enabled: true
AdminHTTP:
Enabled: true
AdminHTTPS:
Enabled: true
MetricsHTTP:
Enabled: true
AutoconfigHTTPS:
Enabled: true
MTASTSHTTPS:
Enabled: true
mox3:
IPs:
- 172.28.3.10
Hostname: moxmail3.mox3.example
TLS:
KeyCerts:
-
CertFile: ../tls/moxmail3.pem
KeyFile: ../tls/moxmail3-key.pem
SMTP:
Enabled: true
FirstTimeSenderDelay: 1s
Submission:
Enabled: true
NoRequireSTARTTLS: true
Postmaster:
Account: moxtest1
Mailbox: postmaster

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEIAVskzmutHg8DvS8jaxYMHuoV1z9tNZmSC8+iI84WlTm
-----END PRIVATE KEY-----

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEINAds0VrnXkd/cUnAT4eQDKQoViHC1q6dBPEqG8SJxnz
-----END PRIVATE KEY-----

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEIPXYWvzg39zC8pkPzYZbTKCAk4TjIICZzaklMrOyADW+
-----END PRIVATE KEY-----

View file

@ -5,29 +5,14 @@ $TTL 5m
@ NS dns.example. @ NS dns.example.
moxmail1.mox1 IN A 172.28.1.10 moxacmepebble.mox1 IN A 172.28.1.10
moxmail2.mox2 IN A 172.28.2.10 moxmail2.mox2 IN A 172.28.1.20
moxmail3.mox3 IN A 172.28.3.10
postfixmail.postfix IN A 172.28.1.20
dns IN A 172.28.1.30 dns IN A 172.28.1.30
localserve.mox1 IN A 172.28.1.50 acmepebble IN A 172.28.1.40
test IN A 172.28.1.50
localserve.mox1 IN A 172.28.1.60
postfixmail.postfix IN A 172.28.1.70
mox1 MX 10 moxmail1.mox1.example.
mox2 MX 10 moxmail2.mox2.example.
mox3 MX 10 moxmail3.mox3.example.
postfix MX 10 postfixmail.postfix.example. postfix MX 10 postfixmail.postfix.example.
mox1dkim0._domainkey.mox1 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=nNs/2BSurEunCKJjfE61p0r2C4OMv/S8IDU/p7nL91c="
mox2dkim0._domainkey.mox2 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=gVAOjqEeNS2e6jjGX1c61zhCOPXMcX6o5If/AVI5STk="
mox3dkim0._domainkey.mox3 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=vzv50BpMhk6moYWq9jBNR+oHmlZcL2LARgL9144nJfk="
postfixdkim0._domainkey.postfix IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=a4IsBTuMsSQjU+xVyx8KEd8eObis4FrCiV72OaEkvDY=" postfixdkim0._domainkey.postfix IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=a4IsBTuMsSQjU+xVyx8KEd8eObis4FrCiV72OaEkvDY="
mox1 IN TXT "v=spf1 ip4:172.28.1.10 ip4:172.28.1.20 -all"
mox2 IN TXT "v=spf1 ip4:172.28.2.10 ip4:172.28.3.10 -all" ; 172.28.3.10 because that's where connections from mox to mox3 are going from. perhaps linux prefers to use same source ip if possible?
mox3 IN TXT "v=spf1 ip4:172.28.3.10 -all"
postfix IN TXT "v=spf1 ip4:172.28.1.20 -all" postfix IN TXT "v=spf1 ip4:172.28.1.20 -all"
_dmarc.mox1 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox1.example"
_dmarc.mox2 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox2.example"
_dmarc.mox3 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox3.example"
; _dmarc.mox4 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@postfix.example"

View file

@ -16,13 +16,18 @@ TLS:
CA: CA:
CertFiles: CertFiles:
# So certificates from moxmail2 are trusted, and pebble's certificate is trusted. # So certificates from moxmail2 are trusted, and pebble's certificate is trusted.
- /quickstart/tls/ca.pem - /integration/tls/ca.pem
EOF EOF
(cat /quickstart/example.zone; sed -n '/^;/,/IN CAA/p' output.txt) >/quickstart/example-quickstart.zone (
cat /integration/example.zone;
sed -n '/^;/,/IN CAA/p' output.txt |
# allow sending from postfix for mox1.example.
sed 's/mox1.example. *IN TXT "v=spf1 mx ~all"/mox1.example. IN TXT "v=spf1 mx ip4:172.28.1.70 ~all"/'
) >/integration/example-integration.zone
unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes 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 CURL_CA_BUNDLE=/integration/tls/ca.pem curl -o /integration/tmp-pebble-ca.pem https://acmepebble.example:15000/roots/0
mox serve & mox serve &
while true; do while true; do

View file

@ -9,20 +9,20 @@ mkdir /tmp/mox
cd /tmp/mox cd /tmp/mox
mox quickstart moxtest2@mox2.example "$MOX_UID" > output.txt 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,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf 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: /integration/tls/moxmail2.pem\n\t\t\t\t\tKeyFile: /integration/tls/moxmail2-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-autoconfig.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-autoconfig-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-mtasts.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-mtasts-key.pem\n,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf
cat <<EOF >>config/mox.conf cat <<EOF >>config/mox.conf
TLS: TLS:
CA: CA:
CertFiles: CertFiles:
# CA of our own certificates. # CA of our own certificates.
- /quickstart/tls/ca.pem - /integration/tls/ca.pem
# CA used by moxacmepebble. # CA used by moxacmepebble.
- /quickstart/tmp-pebble-ca.pem - /integration/tmp-pebble-ca.pem
EOF EOF
# A fresh file was set up by moxacmepebble. # A fresh file was set up by moxacmepebble.
sed -n '/^;/,/IN CAA/p' output.txt >>/quickstart/example-quickstart.zone sed -n '/^;/,/IN CAA/p' output.txt >>/integration/example-integration.zone
unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes
mox serve & mox serve &

View file

@ -2,8 +2,8 @@
"pebble": { "pebble": {
"listenAddress": "0.0.0.0:14000", "listenAddress": "0.0.0.0:14000",
"managementListenAddress": "0.0.0.0:15000", "managementListenAddress": "0.0.0.0:15000",
"certificate": "/quickstart/tls/acmepebble.pem", "certificate": "/integration/tls/acmepebble.pem",
"privateKey": "/quickstart/tls/acmepebble-key.pem", "privateKey": "/integration/tls/acmepebble-key.pem",
"httpPort": 80, "httpPort": 80,
"tlsPort": 443, "tlsPort": 443,
"ocspResponderURL": "", "ocspResponderURL": "",

View file

@ -3,8 +3,10 @@ $TTL 5m
@ IN SOA dns.example. hostmaster.example. (1 0m 0m 0m 5m) @ IN SOA dns.example. hostmaster.example. (1 0m 0m 0m 5m)
10.1 IN PTR moxmail1.mox1.example. 10.1 IN PTR moxacmepebble.mox1.example.
10.2 IN PTR moxmail2.mox2.example. 20.1 IN PTR moxmail2.mox2.example.
10.3 IN PTR moxmail3.mox3.example.
20.1 IN PTR postfixmail.postfix.example.
30.1 IN PTR dns.example. 30.1 IN PTR dns.example.
40.1 IN PTR acmepebble.example.
50.1 IN PTR test.example.
60.1 IN PTR localserve.mox1.example.
70.1 IN PTR postfixmail.postfix.example.

View file

@ -1,6 +1,7 @@
default: default:
cfssl genkey -initca cfssl-ca-csr.json | cfssljson -bare ca 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 moxmail1.mox1.example - | cfssljson -bare moxmail1
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 moxmail2.mox2.example - | cfssljson -bare moxmail2
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail3.mox3.example - | cfssljson -bare moxmail3 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
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname postfixmail.postfix.example - | cfssljson -bare postfixmail echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname postfixmail.postfix.example - | cfssljson -bare postfixmail

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY----- -----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAIxWviXAT3jP2y0nbypyq+r9SoToR1Z8l4/ShXFalyPoAoGCCqGSM49 MHcCAQEEIIGDc32mcAt+9t3WmJvmeCLZK9aDjD6CrLjOvZx4zlRzoAoGCCqGSM49
AwEHoUQDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQczZEba AwEHoUQDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3HjsP7zi
6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+Q== e6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3A==
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST----- -----BEGIN CERTIFICATE REQUEST-----
MIH0MIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI MIHzMIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQcz KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
ZEba6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+aAiMCAGCSqGSIb3DQEJDjETMBEw P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KAiMCAGCSqGSIb3DQEJDjETMBEw
DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAtwFHGm+7zqxnpj6i DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAuAJlvbFItRqBOHMV
EwLMRlXOY0U23xQajcLA/IknZkQCIQCB5ynsMvFJ49EmkcrfRALSqHIHZneH9p0Q aqUz2HNGocVLeeBjY9yWvI//Mo0CIC3Lzbh32xwaBwASggudm1OVAhDcvfzVJE68
1CHHfQj6Fg== +INvsUeP
-----END CERTIFICATE REQUEST----- -----END CERTIFICATE REQUEST-----

View file

@ -1,10 +1,10 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIBcjCCARigAwIBAgIUZhjg/4oAiX7YspAARmOjFojGseQwCgYIKoZIzj0EAwIw MIIBcjCCARigAwIBAgIUE8iskCUxfwqpv6F+nsXp7D4uqeYwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1 FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxODM3MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI MjcxNTM1MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQcz KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
ZEba6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+aNCMEAwDgYDVR0PAQH/BAQDAgEG P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KNCMEAwDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFO2GIS1aM4NtFS+a+DrMcmjWiKYB MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKUFNkPBlmKeQdvgjR0ORFnDmuTt
MAoGCCqGSM49BAMCA0gAMEUCIQCvkuuvPMAW1d3Xns7TYjSa/NFxSjFyiGKsaaJX MAoGCCqGSM49BAMCA0gAMEUCIQCpOIZyFiHyAYZyjzj7HQSAsCeXzV/XuUXCJ+hR
ohvCLgIgUkSVYc71RHa5AB3geVbXmmwrFF40+gB1cW7oGwkScBM= R7uB4QIgUd6M84/3KdbdO7JW5W8saBh0hZ+kMhfQj5NEXy0VUtU=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOZXlR9z/jixe9bjSjHOURN0EFLTr9Wumw7W3Zr+XMPmoAoGCCqGSM49
AwEHoUQDQgAEjzxO852bzPodARDVgWUk+/Xy+G4SEImtN/5De0KgcUWXvVuJFjGg
ruBgyBAoHEkYau53Jcu3ZjHRFdi9RkwlbA==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASPPE7znZvM+h0B
ENWBZST79fL4bhIQia03/kN7QqBxRZe9W4kWMaCu4GDIECgcSRhq7ncly7dmMdEV
2L1GTCVsoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMS5t
b3gxLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAKng26zqtKmRJtpkIdJNQD4C
hIBp+0jUC6apWFW8bvdFAiA/l0HfqQ1/OApMdgM8gNxZSwl13ZCqJlacTwYfkm4r
1Q==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtjCCAVygAwIBAgIUeowpo7RMCenGjlCR+4SEza90HVIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASPPE7znZvM+h0B
ENWBZST79fL4bhIQia03/kN7QqBxRZe9W4kWMaCu4GDIECgcSRhq7ncly7dmMdEV
2L1GTCVso4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBReQyt9RscC4SFTh6RPr1uxYSUWjDAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt
b3htYWlsMS5tb3gxLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgC2+MAUGSugMc
ffJ698+eTVHlxpR8C9PCs8udQVv2noYCIQC4ubNYPW3ZYdvQlRf2Svf3Al2vRl1N
pqt76JJVh9NTMA==
-----END CERTIFICATE-----

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY----- -----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOw1oRBmOXVQd5MZiN1LzPqvqyoCoUpOc3GhO60WRgKFoAoGCCqGSM49 MHcCAQEEICvD+j+bji24hVIcRFrWPbQd6sXKmAuMtFUq175VY6K7oAoGCCqGSM49
AwEHoUQDQgAEraCc8aRtk7kusBZ1FK/DMPiicc9FEjvbtHWT8lCPMAXjKWU/wG31 AwEHoUQDQgAEZS5yh9kP/DgN94O+4hcNsyBt+CgQc8wZAE96GEhrNk+bgqwWpfTV
OktPDzfzu3Unvw1HT+/ljUahJ94InlSDZQ== 3ZiKfMKCvCqj+yKzwSi/3YyMAymghBMdng==
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST----- -----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoJzxpG2TuS6w MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
FnUUr8Mw+KJxz0USO9u0dZPyUI8wBeMpZT/AbfU6S08PN/O7dSe/DUdP7+WNRqEn g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
3gieVINloDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t KaCEEx2eoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t
b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgbFop/kVfFLIWtKVZEvy2YSJU b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAP6qbRb8RikC8x5cmUix0+yO
6zheYeteOTvIuwgcK+UCIQCOXHT/WxsqCUorpT08WHAvfaIgKCOz0PLTL7MtdJED UjFMytNaZtGMKAvGceSbAiAZ8neHjd04tJEI7Y3a5TDXtwz4D66K5CGdnMC7MRam
rQ== 5w==
-----END CERTIFICATE REQUEST----- -----END CERTIFICATE REQUEST-----

View file

@ -1,12 +1,12 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIBtTCCAVygAwIBAgIUc136y8tcpMqkiAC9g4isvHRFrgMwCgYIKoZIzj0EAwIw MIIBtjCCAVygAwIBAgIUaowxow/mwlT7vGZQclZFCrJFTEIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1 FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoJzxpG2TuS6w MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
FnUUr8Mw+KJxz0USO9u0dZPyUI8wBeMpZT/AbfU6S08PN/O7dSe/DUdP7+WNRqEn g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
3gieVINlo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD KaCEEx2eo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBS8ILNAqiWwz+hdmGG5gJ29JZKgdDAf ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTD3lkc5vvR1/6nkYxgmKgYA33YNjAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAjBgNVHREBAf8EGTAXghVt
b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDRwAwRAIgSCdO0boA280B b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAMBmK6kEflN6
fOGKeWl8+TAA/Lx7HJSza0fmO33ndWgCIGyw+LOgYchONeCGfG0YLz5y2v2J5hme 8U/Y5EbhpCn7X3uV5Fbh59IHFJm8uK7XAiBQ0VVzueEO70TCAiGLllnpqrZq86Fa
31FhVsoqAcq4 XWoHOzoczCmZBw==
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEO5gTEH/gvyLz3Gjck5bjeno8Lt7agmk15u2Jv0Pd1xoAoGCCqGSM49
AwEHoUQDQgAEI1hS7Pkx6LJwkTGQ2pPME3J4F1IsyuWM9rrFzWoziBxof4rhqxhU
EkDjDMqJSEj+f/0W6IUSmkou1khyAOu7Og==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHvMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQjWFLs+THosnCR
MZDak8wTcngXUizK5Yz2usXNajOIHGh/iuGrGFQSQOMMyolISP5//RbohRKaSi7W
SHIA67s6oDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMy5t
b3gzLmV4YW1wbGUwCgYIKoZIzj0EAwIDSQAwRgIhALYlavlUXSDyql3djjXmkivJ
vP2o6/UYvycCD5Zs41LyAiEA5Dl/BUou/9mdQZ1wtO7dECV2og3LFqbux9HH5hhq
CHQ=
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtzCCAVygAwIBAgIUYsOfXT2yt+VXzQdYJZ6xDrpduyUwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQjWFLs+THosnCR
MZDak8wTcngXUizK5Yz2usXNajOIHGh/iuGrGFQSQOMMyolISP5//RbohRKaSi7W
SHIA67s6o4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTgWT5PO/9Hs25S2/AEIh8Kbt2Y+DAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt
b3htYWlsMy5tb3gzLmV4YW1wbGUwCgYIKoZIzj0EAwIDSQAwRgIhAN4LwY0/jkr7
Q9kCV2EeTgvja2XKu6kwdptBGacRRezdAiEAtmjbVuUk6OgF40a2IgJD1tbRRF55
M4T7VRdZJTdIDHQ=
-----END CERTIFICATE-----

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY----- -----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJo/6dn+2V2ffJgRScOIX6waHFPNUaDOCR05BW0vHeDsoAoGCCqGSM49 MHcCAQEEIDZojp22U22aP2yhoReSgYeVdFgQMXjoOjPAkvGZ7D2UoAoGCCqGSM49
AwEHoUQDQgAEw4QmYTaA5csyzcmJ2V/40xGkJ7woQxxmIyU5OzpYRCz4ejcVQPrg AwEHoUQDQgAEW6LWFaeb6BBYsUMA13PUe/9JSre4qSgJQNLkRAlHUoyopTwjlDZw
4/3LS3Tr1SoUJXr/a8NoduQDOX/KvkAadg== PbnRqqYMt7Y+DJlj+OVtImExXSufvo66yQ==
-----END EC PRIVATE KEY----- -----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST----- -----BEGIN CERTIFICATE REQUEST-----
MIHzMIGbAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATDhCZhNoDlyzLN MIH0MIGbAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbotYVp5voEFix
yYnZX/jTEaQnvChDHGYjJTk7OlhELPh6NxVA+uDj/ctLdOvVKhQlev9rw2h25AM5 QwDXc9R7/0lKt7ipKAlA0uRECUdSjKilPCOUNnA9udGqpgy3tj4MmWP45W0iYTFd
f8q+QBp2oDkwNwYJKoZIhvcNAQkOMSowKDAmBgNVHREEHzAdghtwb3N0Zml4bWFp K5++jrrJoDkwNwYJKoZIhvcNAQkOMSowKDAmBgNVHREEHzAdghtwb3N0Zml4bWFp
bC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDRwAwRAIgEHqFqWnzkb+AuQSy bC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhANTF3PngKdGDEPpm
g5WbGDmWV0PC3cn3ZrhnKph+JRYCICHIOwP30IrU2vZlRw7hSJfF73Kp97bZnKnx G2SmWmtY/rfVfK5tIJyOZF6c5Yt7AiBZYYgP2YkM/4U1n3z4pPJLI9HFkELIlgU+
hKFU2mu2 H9tLemIc/Q==
-----END CERTIFICATE REQUEST----- -----END CERTIFICATE REQUEST-----

View file

@ -1,12 +1,12 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIBvDCCAWKgAwIBAgIUenc5veQllvPUqrUPTtB8eFtJvHkwCgYIKoZIzj0EAwIw MIIBvDCCAWKgAwIBAgIUC0PorNW2+71N4VeYmYlbKt66Jg8wCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1 FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNzIzMjAwNzAwWhgPMjA1MzA3
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATDhCZhNoDlyzLN MTUyMDA3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbotYVp5voEFix
yYnZX/jTEaQnvChDHGYjJTk7OlhELPh6NxVA+uDj/ctLdOvVKhQlev9rw2h25AM5 QwDXc9R7/0lKt7ipKAlA0uRECUdSjKilPCOUNnA9udGqpgy3tj4MmWP45W0iYTFd
f8q+QBp2o4GhMIGeMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD K5++jrrJo4GhMIGeMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRvX8dsWXBuohuUI6tMLaGRKG6j6jAf ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRb1GaGZrZmbnOli4xUMg9mfkxgUDAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATApBgNVHREBAf8EHzAdghtw BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TApBgNVHREBAf8EHzAdghtw
b3N0Zml4bWFpbC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgdqqP b3N0Zml4bWFpbC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAIzx
rKV8yZ+XjDDzj9qp9VNZRqDRfVfYJoMY7c0qx1ECIQCMVEKWwyR0s7dsy7CAibBm DFc5uy7d8qviR2HrjHA9XLviW2PwaGQJrNAalNmuAiB2CEaJ7RJL37bWddCi4L1T
oaIOieBYkklXb1cnraoZsg== JZLoZIrbKuAb5nd7/GTcNw==
-----END CERTIFICATE----- -----END CERTIFICATE-----

View file

@ -1,15 +1,19 @@
server: server:
interface: 172.28.1.30 interface: 172.28.1.30
access-control: 0.0.0.0/0 allow access-control: 0.0.0.0/0 allow
logfile: /dev/stdout logfile: ""
use-syslog: no
domain-insecure: "example" domain-insecure: "example"
local-zone: "28.172.in-addr.arpa." nodefault 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: auth-zone:
name: "example" name: "example"
zonefile: "/etc/unbound/example.zone" zonefile: "/integration/example-integration.zone"
auth-zone: auth-zone:
name: "28.172.in-addr.arpa" name: "28.172.in-addr.arpa"
zonefile: "/etc/unbound/reverse.zone" zonefile: "/integration/reverse.zone"

View file

@ -1,2 +0,0 @@
FROM alpine:3.17
RUN apk add unbound bind-tools mailx

View file

@ -1,12 +0,0 @@
$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

View file

@ -1 +0,0 @@
nameserver 172.28.1.30

View file

@ -1,10 +0,0 @@
$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.

View file

@ -1,6 +0,0 @@
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

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIGDc32mcAt+9t3WmJvmeCLZK9aDjD6CrLjOvZx4zlRzoAoGCCqGSM49
AwEHoUQDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3HjsP7zi
e6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3A==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHzMIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KAiMCAGCSqGSIb3DQEJDjETMBEw
DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAuAJlvbFItRqBOHMV
aqUz2HNGocVLeeBjY9yWvI//Mo0CIC3Lzbh32xwaBwASggudm1OVAhDcvfzVJE68
+INvsUeP
-----END CERTIFICATE REQUEST-----

View file

@ -1,10 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBcjCCARigAwIBAgIUE8iskCUxfwqpv6F+nsXp7D4uqeYwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KNCMEAwDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKUFNkPBlmKeQdvgjR0ORFnDmuTt
MAoGCCqGSM49BAMCA0gAMEUCIQCpOIZyFiHyAYZyjzj7HQSAsCeXzV/XuUXCJ+hR
R7uB4QIgUd6M84/3KdbdO7JW5W8saBh0hZ+kMhfQj5NEXy0VUtU=
-----END CERTIFICATE-----

View file

@ -1,10 +0,0 @@
{
"CN": "mox test ca",
"key": {
"algo": "ecdsa",
"size": 256
},
"ca": {
"expiry": "262800h"
}
}

View file

@ -1,17 +0,0 @@
{
"signing": {
"default": {
"expiry": "262800h"
},
"profiles": {
"server": {
"expiry": "262800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
}
}
}
}

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICvD+j+bji24hVIcRFrWPbQd6sXKmAuMtFUq175VY6K7oAoGCCqGSM49
AwEHoUQDQgAEZS5yh9kP/DgN94O+4hcNsyBt+CgQc8wZAE96GEhrNk+bgqwWpfTV
3ZiKfMKCvCqj+yKzwSi/3YyMAymghBMdng==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t
b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAP6qbRb8RikC8x5cmUix0+yO
UjFMytNaZtGMKAvGceSbAiAZ8neHjd04tJEI7Y3a5TDXtwz4D66K5CGdnMC7MRam
5w==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtjCCAVygAwIBAgIUaowxow/mwlT7vGZQclZFCrJFTEIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTD3lkc5vvR1/6nkYxgmKgYA33YNjAf
BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAjBgNVHREBAf8EGTAXghVt
b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAMBmK6kEflN6
8U/Y5EbhpCn7X3uV5Fbh59IHFJm8uK7XAiBQ0VVzueEO70TCAiGLllnpqrZq86Fa
XWoHOzoczCmZBw==
-----END CERTIFICATE-----

View file

@ -1,2 +0,0 @@
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.

View file

@ -1,19 +0,0 @@
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"