@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 262 lines 7.97 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddytls
16
17 import (
18 "crypto/rand"
19 "crypto/x509"
20 "crypto/x509/pkix"
21 "encoding/pem"
22 "fmt"
23 "os"
24 "path/filepath"
25 "testing"
26 "time"
27
28 "github.com/caddyserver/caddy/v2"
29 "github.com/caddyserver/caddy/v2/modules/caddypki"
30 "go.uber.org/zap"
31
32 "go.step.sm/crypto/keyutil"
33 "go.step.sm/crypto/pemutil"
34 )
35
36 func TestInternalIssuer_Issue(t *testing.T) {
37 rootSigner, err := keyutil.GenerateDefaultSigner()
38 if err != nil {
39 t.Fatalf("Creating root signer failed: %v", err)
40 }
41
42 tmpl := &x509.Certificate{
43 Subject: pkix.Name{CommonName: "test-root"},
44 IsCA: true,
45 MaxPathLen: 3,
46 NotAfter: time.Now().Add(7 * 24 * time.Hour),
47 NotBefore: time.Now().Add(-7 * 24 * time.Hour),
48 }
49 rootBytes, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, rootSigner.Public(), rootSigner)
50 if err != nil {
51 t.Fatalf("Creating root certificate failed: %v", err)
52 }
53
54 root, err := x509.ParseCertificate(rootBytes)
55 if err != nil {
56 t.Fatalf("Parsing root certificate failed: %v", err)
57 }
58
59 firstIntermediateSigner, err := keyutil.GenerateDefaultSigner()
60 if err != nil {
61 t.Fatalf("Creating intermedaite signer failed: %v", err)
62 }
63
64 firstIntermediateBytes, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
65 Subject: pkix.Name{CommonName: "test-first-intermediate"},
66 IsCA: true,
67 MaxPathLen: 2,
68 NotAfter: time.Now().Add(24 * time.Hour),
69 NotBefore: time.Now().Add(-24 * time.Hour),
70 }, root, firstIntermediateSigner.Public(), rootSigner)
71 if err != nil {
72 t.Fatalf("Creating intermediate certificate failed: %v", err)
73 }
74
75 firstIntermediate, err := x509.ParseCertificate(firstIntermediateBytes)
76 if err != nil {
77 t.Fatalf("Parsing intermediate certificate failed: %v", err)
78 }
79
80 secondIntermediateSigner, err := keyutil.GenerateDefaultSigner()
81 if err != nil {
82 t.Fatalf("Creating second intermedaite signer failed: %v", err)
83 }
84
85 secondIntermediateBytes, err := x509.CreateCertificate(rand.Reader, &x509.Certificate{
86 Subject: pkix.Name{CommonName: "test-second-intermediate"},
87 IsCA: true,
88 MaxPathLen: 2,
89 NotAfter: time.Now().Add(24 * time.Hour),
90 NotBefore: time.Now().Add(-24 * time.Hour),
91 }, firstIntermediate, secondIntermediateSigner.Public(), firstIntermediateSigner)
92 if err != nil {
93 t.Fatalf("Creating second intermediate certificate failed: %v", err)
94 }
95
96 secondIntermediate, err := x509.ParseCertificate(secondIntermediateBytes)
97 if err != nil {
98 t.Fatalf("Parsing second intermediate certificate failed: %v", err)
99 }
100
101 dir := t.TempDir()
102 storageDir := filepath.Join(dir, "certmagic")
103 rootCertFile := filepath.Join(dir, "root.pem")
104 if _, err = pemutil.Serialize(root, pemutil.WithFilename(rootCertFile)); err != nil {
105 t.Fatalf("Failed serializing root certificate: %v", err)
106 }
107 intermediateCertFile := filepath.Join(dir, "intermediate.pem")
108 if _, err = pemutil.Serialize(firstIntermediate, pemutil.WithFilename(intermediateCertFile)); err != nil {
109 t.Fatalf("Failed serializing intermediate certificate: %v", err)
110 }
111 intermediateKeyFile := filepath.Join(dir, "intermediate.key")
112 if _, err = pemutil.Serialize(firstIntermediateSigner, pemutil.WithFilename(intermediateKeyFile)); err != nil {
113 t.Fatalf("Failed serializing intermediate key: %v", err)
114 }
115
116 var intermediateChainContents []byte
117 intermediateChain := []*x509.Certificate{secondIntermediate, firstIntermediate}
118 for _, cert := range intermediateChain {
119 b, err := pemutil.Serialize(cert)
120 if err != nil {
121 t.Fatalf("Failed serializing intermediate certificate: %v", err)
122 }
123 intermediateChainContents = append(intermediateChainContents, pem.EncodeToMemory(b)...)
124 }
125 intermediateChainFile := filepath.Join(dir, "intermediates.pem")
126 if err := os.WriteFile(intermediateChainFile, intermediateChainContents, 0644); err != nil {
127 t.Fatalf("Failed writing intermediate chain: %v", err)
128 }
129 intermediateChainKeyFile := filepath.Join(dir, "intermediates.key")
130 if _, err = pemutil.Serialize(secondIntermediateSigner, pemutil.WithFilename(intermediateChainKeyFile)); err != nil {
131 t.Fatalf("Failed serializing intermediate key: %v", err)
132 }
133
134 signer, err := keyutil.GenerateDefaultSigner()
135 if err != nil {
136 t.Fatalf("Failed creating signer: %v", err)
137 }
138
139 csrBytes, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
140 Subject: pkix.Name{CommonName: "test"},
141 }, signer)
142 if err != nil {
143 t.Fatalf("Failed creating CSR: %v", err)
144 }
145
146 csr, err := x509.ParseCertificateRequest(csrBytes)
147 if err != nil {
148 t.Fatalf("Failed parsing CSR: %v", err)
149 }
150
151 t.Run("generated-with-defaults", func(t *testing.T) {
152 caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
153 t.Cleanup(cancel)
154 logger := zap.NewNop()
155
156 ca := &caddypki.CA{
157 StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
158 }
159 if err := ca.Provision(caddyCtx, "local-test-generated", logger); err != nil {
160 t.Fatalf("Failed provisioning CA: %v", err)
161 }
162
163 iss := InternalIssuer{
164 SignWithRoot: false,
165 ca: ca,
166 logger: logger,
167 }
168
169 c, err := iss.Issue(t.Context(), csr)
170 if err != nil {
171 t.Fatalf("Failed issuing certificate: %v", err)
172 }
173
174 chain, err := pemutil.ParseCertificateBundle(c.Certificate)
175 if err != nil {
176 t.Errorf("Failed issuing certificate: %v", err)
177 }
178 if len(chain) != 2 {
179 t.Errorf("Expected 2 certificates in chain; got %d", len(chain))
180 }
181 })
182
183 t.Run("single-intermediate-from-disk", func(t *testing.T) {
184 caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
185 t.Cleanup(cancel)
186 logger := zap.NewNop()
187
188 ca := &caddypki.CA{
189 Root: &caddypki.KeyPair{
190 Certificate: rootCertFile,
191 },
192 Intermediate: &caddypki.KeyPair{
193 Certificate: intermediateCertFile,
194 PrivateKey: intermediateKeyFile,
195 },
196 StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
197 }
198
199 if err := ca.Provision(caddyCtx, "local-test-single-intermediate", logger); err != nil {
200 t.Fatalf("Failed provisioning CA: %v", err)
201 }
202
203 iss := InternalIssuer{
204 ca: ca,
205 SignWithRoot: false,
206 logger: logger,
207 }
208
209 c, err := iss.Issue(t.Context(), csr)
210 if err != nil {
211 t.Fatalf("Failed issuing certificate: %v", err)
212 }
213
214 chain, err := pemutil.ParseCertificateBundle(c.Certificate)
215 if err != nil {
216 t.Errorf("Failed issuing certificate: %v", err)
217 }
218 if len(chain) != 2 {
219 t.Errorf("Expected 2 certificates in chain; got %d", len(chain))
220 }
221 })
222
223 t.Run("multiple-intermediates-from-disk", func(t *testing.T) {
224 caddyCtx, cancel := caddy.NewContext(caddy.Context{Context: t.Context()})
225 t.Cleanup(cancel)
226 logger := zap.NewNop()
227
228 ca := &caddypki.CA{
229 Root: &caddypki.KeyPair{
230 Certificate: rootCertFile,
231 },
232 Intermediate: &caddypki.KeyPair{
233 Certificate: intermediateChainFile,
234 PrivateKey: intermediateChainKeyFile,
235 },
236 StorageRaw: []byte(fmt.Sprintf(`{"module": "file_system", "root": %q}`, storageDir)),
237 }
238
239 if err := ca.Provision(caddyCtx, "local-test", zap.NewNop()); err != nil {
240 t.Fatalf("Failed provisioning CA: %v", err)
241 }
242
243 iss := InternalIssuer{
244 ca: ca,
245 SignWithRoot: false,
246 logger: logger,
247 }
248
249 c, err := iss.Issue(t.Context(), csr)
250 if err != nil {
251 t.Fatalf("Failed issuing certificate: %v", err)
252 }
253
254 chain, err := pemutil.ParseCertificateBundle(c.Certificate)
255 if err != nil {
256 t.Errorf("Failed issuing certificate: %v", err)
257 }
258 if len(chain) != 3 {
259 t.Errorf("Expected 3 certificates in chain; got %d", len(chain))
260 }
261 })
262 }