@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 01:00 UTC

master
go 131 lines 3.96 KB
Raw
1 package caddytls
2
3 import (
4 "context"
5 "crypto/ecdsa"
6 "crypto/elliptic"
7 "crypto/rand"
8 "crypto/x509"
9 "net/http"
10 "net/http/httptest"
11 "sync/atomic"
12 "testing"
13 "time"
14
15 "github.com/caddyserver/caddy/v2"
16 _ "github.com/caddyserver/caddy/v2/modules/internal/network"
17 "github.com/caddyserver/certmagic"
18 "github.com/mholt/acmez/v3/acme"
19 "go.uber.org/zap"
20 )
21
22 func TestACMEIssuerExpandPlaceholders(t *testing.T) {
23 t.Setenv("CADDY_TEST_CA_URL", "https://acme.example.com/directory")
24 t.Setenv("CADDY_TEST_TEST_CA_URL", "https://acme2.example.com/directory")
25 t.Setenv("CADDY_TEST_EAB_KEY_ID", "example-key-id")
26 t.Setenv("CADDY_TEST_EAB_MAC_KEY", "example-mac-key")
27
28 caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
29 defer cancel()
30
31 iss := &ACMEIssuer{
32 CA: "{env.CADDY_TEST_CA_URL}",
33 TestCA: "{env.CADDY_TEST_TEST_CA_URL}",
34 ExternalAccount: &acme.EAB{
35 KeyID: "{env.CADDY_TEST_EAB_KEY_ID}",
36 MACKey: "{env.CADDY_TEST_EAB_MAC_KEY}",
37 },
38 }
39
40 if err := iss.Provision(caddyCtx); err != nil {
41 t.Fatalf("Provision() returned unexpected error: %v", err)
42 }
43
44 if want := "https://acme.example.com/directory"; iss.CA != want {
45 t.Errorf("CA: got %q, want %q", iss.CA, want)
46 }
47 if want := "https://acme2.example.com/directory"; iss.TestCA != want {
48 t.Errorf("TestCA: got %q, want %q", iss.TestCA, want)
49 }
50 if want := "example-key-id"; iss.ExternalAccount.KeyID != want {
51 t.Errorf("ExternalAccount.KeyID: got %q, want %q", iss.ExternalAccount.KeyID, want)
52 }
53 if want := "example-mac-key"; iss.ExternalAccount.MACKey != want {
54 t.Errorf("ExternalAccount.MACKey: got %q, want %q", iss.ExternalAccount.MACKey, want)
55 }
56 }
57
58 // The HTTP app provisions ACME issuers again to fill in its ports and then
59 // rebuilds the CertMagic config; requests must still use the configured proxy (#8283).
60 func TestACMEIssuerNetworkProxyAfterRebuildCertMagic(t *testing.T) {
61 var proxied atomic.Int32
62 proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
63 if r.Method == http.MethodConnect && r.Host == "acme.invalid:443" {
64 proxied.Add(1)
65 }
66 http.Error(w, "test proxy", http.StatusBadGateway)
67 }))
68 defer proxy.Close()
69
70 certCacheMu.Lock()
71 prevCache := certCache
72 certCache = certmagic.NewCache(certmagic.CacheOptions{
73 GetConfigForCert: func(certmagic.Certificate) (*certmagic.Config, error) { return nil, nil },
74 })
75 certCacheMu.Unlock()
76 defer func() {
77 certCacheMu.Lock()
78 certCache.Stop()
79 certCache = prevCache
80 certCacheMu.Unlock()
81 }()
82
83 caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
84 defer cancel()
85 tlsApp := &TLS{ctx: caddyCtx, logger: zap.NewNop()}
86
87 iss := &ACMEIssuer{
88 CA: "https://acme.invalid/directory",
89 NetworkProxyRaw: []byte(`{"from":"url","url":"` + proxy.URL + `"}`),
90 }
91 if err := iss.Provision(caddyCtx); err != nil {
92 t.Fatalf("provisioning issuer: %v", err)
93 }
94 ap := &AutomationPolicy{
95 Issuers: []certmagic.Issuer{iss},
96 storage: &certmagic.FileStorage{Path: t.TempDir()},
97 }
98 if err := ap.Provision(tlsApp); err != nil {
99 t.Fatalf("provisioning automation policy: %v", err)
100 }
101
102 // what the HTTP app's fillInACMEIssuer and createAutomationPolicies do
103 if err := iss.Provision(caddyCtx); err != nil {
104 t.Fatalf("re-provisioning issuer: %v", err)
105 }
106 if err := ap.RebuildCertMagic(tlsApp); err != nil {
107 t.Fatalf("rebuilding certmagic config: %v", err)
108 }
109
110 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
111 if err != nil {
112 t.Fatal(err)
113 }
114 csrDER, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{DNSNames: []string{"example.com"}}, key)
115 if err != nil {
116 t.Fatal(err)
117 }
118 csr, err := x509.ParseCertificateRequest(csrDER)
119 if err != nil {
120 t.Fatal(err)
121 }
122
123 ctx, cancelIssue := context.WithTimeout(t.Context(), 10*time.Second)
124 defer cancelIssue()
125 if _, err := iss.Issue(ctx, csr); err == nil {
126 t.Fatal("expected issuance to fail against the test proxy")
127 }
128 if proxied.Load() == 0 {
129 t.Error("ACME request did not go through the configured network proxy")
130 }
131 }