git.iko.soy/typeable/oauth2-proxy
on 7b41c8e help sign in
1321 lines 40 kB history raw
1package http
3import (
4 "context"
5 "errors"
6 "fmt"
7 "io"
8 "net"
9 "net/http"
10 "os"
12 "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
13 . "github.com/onsi/ginkgo/v2"
14 . "github.com/onsi/gomega"
15 . "github.com/onsi/gomega/gleak"
18const hello = "Hello World!"
20var _ = Describe("Server", func() {
22 handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
23 rw.Write([]byte(hello))
24 })
25 Context("NewServer", func() {
26 type newServerTableInput struct {
27 opts Opts
28 expectedErr error
29 expectHTTPListener bool
30 expectTLSListener bool
31 fdAddr string
32 ipv6 bool
33 }
35 DescribeTable("When creating the new server from the options", func(in *newServerTableInput) {
36 if in.ipv6 {
37 skipDevContainer()
38 }
40 if in.fdAddr != "" {
41 l, err := net.Listen("tcp", in.fdAddr)
42 Expect(err).ToNot(HaveOccurred())
43 f, err := l.(*net.TCPListener).File()
44 Expect(err).ToNot(HaveOccurred())
45 in.opts.fdFiles = []*os.File{f}
46 }
48 srv, err := NewServer(in.opts)
49 if in.expectedErr != nil {
50 Expect(err).To(MatchError(ContainSubstring(in.expectedErr.Error())))
51 Expect(srv).To(BeNil())
52 return
53 }
55 Expect(err).ToNot(HaveOccurred())
57 s, ok := srv.(*server)
58 Expect(ok).To(BeTrue())
60 Expect(s.listener != nil).To(Equal(in.expectHTTPListener))
61 if in.expectHTTPListener {
62 Expect(s.listener.Close()).To(Succeed())
63 }
64 Expect(s.tlsListener != nil).To(Equal(in.expectTLSListener))
65 if in.expectTLSListener {
66 Expect(s.tlsListener.Close()).To(Succeed())
67 }
68 },
69 Entry("with a valid non-lowercase fd IPv4 bind address", &newServerTableInput{
70 opts: Opts{
71 Handler: handler,
72 BindAddress: "Fd:3",
73 },
74 expectedErr: nil,
75 expectHTTPListener: true,
76 expectTLSListener: false,
77 fdAddr: "127.0.0.1:0",
78 }),
79 Entry("with a valid fd IPv4 bind address", &newServerTableInput{
80 opts: Opts{
81 Handler: handler,
82 BindAddress: "fd:3",
83 },
84 expectedErr: nil,
85 expectHTTPListener: true,
86 expectTLSListener: false,
87 fdAddr: "127.0.0.1:0",
88 }),
89 Entry("with a invalid fd named bind address", &newServerTableInput{
90 opts: Opts{
91 Handler: handler,
92 BindAddress: "fd:hello",
93 },
94 expectedErr: fmt.Errorf("error setting up listener: listen (file, %s) failed: listen failed: fd with name is not implemented yet", "hello"),
95 expectHTTPListener: true,
96 expectTLSListener: false,
97 fdAddr: "127.0.0.1:0",
98 }),
99 Entry("with a invalid fd IPv4 bind address", &newServerTableInput{
100 opts: Opts{
101 Handler: handler,
102 BindAddress: "fd:4",
103 },
104 expectedErr: fmt.Errorf("error setting up listener: listen (file, %d) failed: listen failed: fd outside of range of available file descriptors", 4),
105 expectHTTPListener: true,
106 expectTLSListener: false,
107 fdAddr: "127.0.0.1:0",
108 }),
109 Entry("with an ipv4 valid http bind address", &newServerTableInput{
110 opts: Opts{
111 Handler: handler,
112 BindAddress: "127.0.0.1:0",
113 },
114 expectedErr: nil,
115 expectHTTPListener: true,
116 expectTLSListener: false,
117 }),
118 Entry("with an ipv4 valid https bind address, with no TLS config", &newServerTableInput{
119 opts: Opts{
120 Handler: handler,
121 SecureBindAddress: "127.0.0.1:0",
122 },
123 expectedErr: errors.New("error setting up TLS listener: no TLS config provided"),
124 expectHTTPListener: false,
125 expectTLSListener: false,
126 }),
127 Entry("with an ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
128 opts: Opts{
129 Handler: handler,
130 SecureBindAddress: "127.0.0.1:0",
131 TLS: &options.TLS{
132 Key: &ipv4KeyDataSource,
133 Cert: &ipv4CertDataSource,
134 },
135 },
136 expectedErr: nil,
137 expectHTTPListener: false,
138 expectTLSListener: true,
139 }),
140 Entry("with a both a fd valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
141 opts: Opts{
142 Handler: handler,
143 BindAddress: "fd:3",
144 SecureBindAddress: "127.0.0.1:0",
145 TLS: &options.TLS{
146 Key: &ipv4KeyDataSource,
147 Cert: &ipv4CertDataSource,
148 },
149 },
150 expectedErr: nil,
151 expectHTTPListener: true,
152 expectTLSListener: true,
153 fdAddr: "127.0.0.1:0",
154 }),
155 Entry("with a both a ipv4 valid http and ipv4 valid https bind address, and valid TLS config", &newServerTableInput{
156 opts: Opts{
157 Handler: handler,
158 BindAddress: "127.0.0.1:0",
159 SecureBindAddress: "127.0.0.1:0",
160 TLS: &options.TLS{
161 Key: &ipv4KeyDataSource,
162 Cert: &ipv4CertDataSource,
163 },
164 },
165 expectedErr: nil,
166 expectHTTPListener: true,
167 expectTLSListener: true,
168 }),
169 Entry("with a \"-\" for the bind address", &newServerTableInput{
170 opts: Opts{
171 Handler: handler,
172 BindAddress: "-",
173 },
174 expectedErr: nil,
175 expectHTTPListener: false,
176 expectTLSListener: false,
177 }),
178 Entry("with a \"-\" for the secure bind address", &newServerTableInput{
179 opts: Opts{
180 Handler: handler,
181 SecureBindAddress: "-",
182 },
183 expectedErr: nil,
184 expectHTTPListener: false,
185 expectTLSListener: false,
186 }),
187 Entry("with an ipv4 invalid bind address scheme", &newServerTableInput{
188 opts: Opts{
189 Handler: handler,
190 BindAddress: "invalid://127.0.0.1:0",
191 },
192 expectedErr: errors.New("error setting up listener: listen (invalid, 127.0.0.1:0) failed: listen invalid: unknown network invalid"),
193 expectHTTPListener: false,
194 expectTLSListener: false,
195 }),
196 Entry("with an ipv4 invalid secure bind address scheme", &newServerTableInput{
197 opts: Opts{
198 Handler: handler,
199 SecureBindAddress: "invalid://127.0.0.1:0",
200 TLS: &options.TLS{
201 Key: &ipv4KeyDataSource,
202 Cert: &ipv4CertDataSource,
203 },
204 },
205 expectedErr: nil,
206 expectHTTPListener: false,
207 expectTLSListener: true,
208 }),
209 Entry("with an ipv4 invalid bind address port", &newServerTableInput{
210 opts: Opts{
211 Handler: handler,
212 BindAddress: "127.0.0.1:a",
213 },
214 expectedErr: errors.New("error setting up listener: listen (tcp, 127.0.0.1:a) failed: listen tcp: "),
215 expectHTTPListener: false,
216 expectTLSListener: false,
217 }),
218 Entry("with an ipv4 invalid secure bind address port", &newServerTableInput{
219 opts: Opts{
220 Handler: handler,
221 SecureBindAddress: "127.0.0.1:a",
222 TLS: &options.TLS{
223 Key: &ipv4KeyDataSource,
224 Cert: &ipv4CertDataSource,
225 },
226 },
227 expectedErr: errors.New("error setting up TLS listener: listen (127.0.0.1:a) failed: listen tcp: "),
228 expectHTTPListener: false,
229 expectTLSListener: false,
230 }),
231 Entry("with an ipv4 invalid TLS key", &newServerTableInput{
232 opts: Opts{
233 Handler: handler,
234 SecureBindAddress: "127.0.0.1:0",
235 TLS: &options.TLS{
236 Key: &options.SecretSource{
237 Value: []byte("invalid"),
238 },
239 Cert: &ipv4CertDataSource,
240 },
241 },
242 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
243 expectHTTPListener: false,
244 expectTLSListener: false,
245 }),
246 Entry("with an ipv4 invalid TLS cert", &newServerTableInput{
247 opts: Opts{
248 Handler: handler,
249 SecureBindAddress: "127.0.0.1:0",
250 TLS: &options.TLS{
251 Key: &ipv4KeyDataSource,
252 Cert: &options.SecretSource{
253 Value: []byte("invalid"),
254 },
255 },
256 },
257 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in certificate input"),
258 expectHTTPListener: false,
259 expectTLSListener: false,
260 }),
261 Entry("with an ipv4 address, with no TLS key", &newServerTableInput{
262 opts: Opts{
263 Handler: handler,
264 SecureBindAddress: "127.0.0.1:0",
265 TLS: &options.TLS{
266 Cert: &ipv4CertDataSource,
267 },
268 },
269 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
270 expectHTTPListener: false,
271 expectTLSListener: false,
272 }),
273 Entry("with an ipv4 address, with no TLS cert", &newServerTableInput{
274 opts: Opts{
275 Handler: handler,
276 SecureBindAddress: "127.0.0.1:0",
277 TLS: &options.TLS{
278 Key: &ipv4KeyDataSource,
279 },
280 },
281 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
282 expectHTTPListener: false,
283 expectTLSListener: false,
284 }),
285 Entry("when the ipv4 bind address is prefixed with the http scheme", &newServerTableInput{
286 opts: Opts{
287 Handler: handler,
288 BindAddress: "http://127.0.0.1:0",
289 },
290 expectedErr: nil,
291 expectHTTPListener: true,
292 expectTLSListener: false,
293 }),
294 Entry("when the ipv4 secure bind address is prefixed with the https scheme", &newServerTableInput{
295 opts: Opts{
296 Handler: handler,
297 SecureBindAddress: "https://127.0.0.1:0",
298 TLS: &options.TLS{
299 Key: &ipv4KeyDataSource,
300 Cert: &ipv4CertDataSource,
301 },
302 },
303 expectedErr: nil,
304 expectHTTPListener: false,
305 expectTLSListener: true,
306 }),
307 Entry("with an ipv4 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
308 opts: Opts{
309 Handler: handler,
310 SecureBindAddress: "127.0.0.1:0",
311 TLS: &options.TLS{
312 Key: &ipv4KeyDataSource,
313 Cert: &ipv4CertDataSource,
314 MinVersion: "TLS1.3",
315 },
316 },
317 expectedErr: nil,
318 expectHTTPListener: false,
319 expectTLSListener: true,
320 }),
321 Entry("with an ipv4 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
322 opts: Opts{
323 Handler: handler,
324 SecureBindAddress: "127.0.0.1:0",
325 TLS: &options.TLS{
326 Key: &ipv4KeyDataSource,
327 Cert: &ipv4CertDataSource,
328 MinVersion: "TLS1.42",
329 },
330 },
331 expectedErr: errors.New("error setting up TLS listener: unknown TLS MinVersion config provided"),
332 expectHTTPListener: false,
333 expectTLSListener: true,
334 }),
335 Entry("with an ipv4 valid https bind address, and valid TLS config with CipherSuites", &newServerTableInput{
336 opts: Opts{
337 Handler: handler,
338 SecureBindAddress: "127.0.0.1:0",
339 TLS: &options.TLS{
340 Key: &ipv4KeyDataSource,
341 Cert: &ipv4CertDataSource,
342 CipherSuites: []string{
343 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
344 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
345 },
346 },
347 },
348 expectedErr: nil,
349 expectHTTPListener: false,
350 expectTLSListener: true,
351 }),
352 Entry("with an ipv4 valid https bind address, and invalid TLS config with unknown CipherSuites", &newServerTableInput{
353 opts: Opts{
354 Handler: handler,
355 SecureBindAddress: "127.0.0.1:0",
356 TLS: &options.TLS{
357 Key: &ipv4KeyDataSource,
358 Cert: &ipv4CertDataSource,
359 CipherSuites: []string{
360 "TLS_RSA_WITH_RC4_64_SHA",
361 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
362 },
363 },
364 },
365 expectedErr: errors.New("error setting up TLS listener: could not parse cipher suites: unknown TLS cipher suite name specified \"TLS_RSA_WITH_RC4_64_SHA\""),
366 expectHTTPListener: false,
367 expectTLSListener: true,
368 }),
369 Entry("with valid fd IPv6 bind address", &newServerTableInput{
370 opts: Opts{
371 Handler: handler,
372 BindAddress: "fd:3",
373 },
374 expectedErr: nil,
375 expectHTTPListener: true,
376 expectTLSListener: false,
377 fdAddr: "[::1]:0",
378 ipv6: true,
379 }),
380 Entry("with a invalid fd IPv6 bind address", &newServerTableInput{
381 opts: Opts{
382 Handler: handler,
383 BindAddress: "fd:4",
384 },
385 expectedErr: fmt.Errorf("error setting up listener: listen (file, %d) failed: listen failed: fd outside of range of available file descriptors", 4),
386 expectHTTPListener: true,
387 expectTLSListener: false,
388 fdAddr: "[::1]:0",
389 }),
390 Entry("with an ipv6 valid http bind address", &newServerTableInput{
391 opts: Opts{
392 Handler: handler,
393 BindAddress: "[::1]:0",
394 },
395 expectedErr: nil,
396 expectHTTPListener: true,
397 expectTLSListener: false,
398 ipv6: true,
399 }),
400 Entry("with an ipv6 valid https bind address, with no TLS config", &newServerTableInput{
401 opts: Opts{
402 Handler: handler,
403 SecureBindAddress: "[::1]:0",
404 },
405 expectedErr: errors.New("error setting up TLS listener: no TLS config provided"),
406 expectHTTPListener: false,
407 expectTLSListener: false,
408 ipv6: true,
409 }),
410 Entry("with an ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
411 opts: Opts{
412 Handler: handler,
413 SecureBindAddress: "[::1]:0",
414 TLS: &options.TLS{
415 Key: &ipv6KeyDataSource,
416 Cert: &ipv6CertDataSource,
417 },
418 },
419 expectedErr: nil,
420 expectHTTPListener: false,
421 expectTLSListener: true,
422 ipv6: true,
423 }),
424 Entry("with a both a fd valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
425 opts: Opts{
426 Handler: handler,
427 BindAddress: "fd:3",
428 SecureBindAddress: "[::1]:0",
429 TLS: &options.TLS{
430 Key: &ipv6KeyDataSource,
431 Cert: &ipv6CertDataSource,
432 },
433 },
434 expectedErr: nil,
435 expectHTTPListener: true,
436 expectTLSListener: true,
437 fdAddr: "[::1]:0",
438 ipv6: true,
439 }),
440 Entry("with a both a ipv6 valid http and ipv6 valid https bind address, and valid TLS config", &newServerTableInput{
441 opts: Opts{
442 Handler: handler,
443 BindAddress: "[::1]:0",
444 SecureBindAddress: "[::1]:0",
445 TLS: &options.TLS{
446 Key: &ipv6KeyDataSource,
447 Cert: &ipv6CertDataSource,
448 },
449 },
450 expectedErr: nil,
451 expectHTTPListener: true,
452 expectTLSListener: true,
453 ipv6: true,
454 }),
455 Entry("with an ipv6 invalid bind address scheme", &newServerTableInput{
456 opts: Opts{
457 Handler: handler,
458 BindAddress: "invalid://[::1]:0",
459 },
460 expectedErr: errors.New("error setting up listener: listen (invalid, [::1]:0) failed: listen invalid: unknown network invalid"),
461 expectHTTPListener: false,
462 expectTLSListener: false,
463 ipv6: true,
464 }),
465 Entry("with an ipv6 invalid secure bind address scheme", &newServerTableInput{
466 opts: Opts{
467 Handler: handler,
468 SecureBindAddress: "invalid://[::1]:0",
469 TLS: &options.TLS{
470 Key: &ipv6KeyDataSource,
471 Cert: &ipv6CertDataSource,
472 },
473 },
474 expectedErr: nil,
475 expectHTTPListener: false,
476 expectTLSListener: true,
477 ipv6: true,
478 }),
479 Entry("with an ipv6 invalid bind address port", &newServerTableInput{
480 opts: Opts{
481 Handler: handler,
482 BindAddress: "[::1]:a",
483 },
484 expectedErr: errors.New("error setting up listener: listen (tcp, [::1]:a) failed: listen tcp: "),
485 expectHTTPListener: false,
486 expectTLSListener: false,
487 ipv6: true,
488 }),
489 Entry("with an ipv6 invalid secure bind address port", &newServerTableInput{
490 opts: Opts{
491 Handler: handler,
492 SecureBindAddress: "[::1]:a",
493 TLS: &options.TLS{
494 Key: &ipv6KeyDataSource,
495 Cert: &ipv6CertDataSource,
496 },
497 },
498 expectedErr: errors.New("error setting up TLS listener: listen ([::1]:a) failed: listen tcp: "),
499 expectHTTPListener: false,
500 expectTLSListener: false,
501 ipv6: true,
502 }),
503 Entry("with an ipv6 invalid TLS key", &newServerTableInput{
504 opts: Opts{
505 Handler: handler,
506 SecureBindAddress: "[::1]:0",
507 TLS: &options.TLS{
508 Key: &options.SecretSource{
509 Value: []byte("invalid"),
510 },
511 Cert: &ipv6CertDataSource,
512 },
513 },
514 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in key input"),
515 expectHTTPListener: false,
516 expectTLSListener: false,
517 ipv6: true,
518 }),
519 Entry("with an ipv6 invalid TLS cert", &newServerTableInput{
520 opts: Opts{
521 Handler: handler,
522 SecureBindAddress: "[::1]:0",
523 TLS: &options.TLS{
524 Key: &ipv6KeyDataSource,
525 Cert: &options.SecretSource{
526 Value: []byte("invalid"),
527 },
528 },
529 },
530 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not parse certificate data: tls: failed to find any PEM data in certificate input"),
531 expectHTTPListener: false,
532 expectTLSListener: false,
533 ipv6: true,
534 }),
535 Entry("with an ipv6 address, with no TLS key", &newServerTableInput{
536 opts: Opts{
537 Handler: handler,
538 SecureBindAddress: "[::1]:0",
539 TLS: &options.TLS{
540 Cert: &ipv6CertDataSource,
541 },
542 },
543 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load key data: no configuration provided"),
544 expectHTTPListener: false,
545 expectTLSListener: false,
546 ipv6: true,
547 }),
548 Entry("with an ipv6 address, with no TLS cert", &newServerTableInput{
549 opts: Opts{
550 Handler: handler,
551 SecureBindAddress: "[::1]:0",
552 TLS: &options.TLS{
553 Key: &ipv6KeyDataSource,
554 },
555 },
556 expectedErr: errors.New("error setting up TLS listener: could not load certificate: could not load cert data: no configuration provided"),
557 expectHTTPListener: false,
558 expectTLSListener: false,
559 ipv6: true,
560 }),
561 Entry("when the ipv6 bind address is prefixed with the http scheme", &newServerTableInput{
562 opts: Opts{
563 Handler: handler,
564 BindAddress: "http://[::1]:0",
565 },
566 expectedErr: nil,
567 expectHTTPListener: true,
568 expectTLSListener: false,
569 ipv6: true,
570 }),
571 Entry("when the ipv6 secure bind address is prefixed with the https scheme", &newServerTableInput{
572 opts: Opts{
573 Handler: handler,
574 SecureBindAddress: "https://[::1]:0",
575 TLS: &options.TLS{
576 Key: &ipv6KeyDataSource,
577 Cert: &ipv6CertDataSource,
578 },
579 },
580 expectedErr: nil,
581 expectHTTPListener: false,
582 expectTLSListener: true,
583 ipv6: true,
584 }),
585 Entry("with an ipv6 valid https bind address, and valid TLS config with MinVersion", &newServerTableInput{
586 opts: Opts{
587 Handler: handler,
588 SecureBindAddress: "[::1]:0",
589 TLS: &options.TLS{
590 Key: &ipv6KeyDataSource,
591 Cert: &ipv6CertDataSource,
592 MinVersion: "TLS1.3",
593 },
594 },
595 expectedErr: nil,
596 expectHTTPListener: false,
597 expectTLSListener: true,
598 ipv6: true,
599 }),
600 Entry("with an ipv6 valid https bind address, and invalid TLS config with unknown MinVersion", &newServerTableInput{
601 opts: Opts{
602 Handler: handler,
603 SecureBindAddress: "[::1]:0",
604 TLS: &options.TLS{
605 Key: &ipv6KeyDataSource,
606 Cert: &ipv6CertDataSource,
607 MinVersion: "TLS1.42",
608 },
609 },
610 expectedErr: errors.New("error setting up TLS listener: unknown TLS MinVersion config provided"),
611 expectHTTPListener: false,
612 expectTLSListener: true,
613 ipv6: true,
614 }),
615 Entry("with an ipv6 valid https bind address, and valid TLS config with CipherSuites", &newServerTableInput{
616 opts: Opts{
617 Handler: handler,
618 SecureBindAddress: "[::1]:0",
619 TLS: &options.TLS{
620 Key: &ipv4KeyDataSource,
621 Cert: &ipv4CertDataSource,
622 CipherSuites: []string{
623 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
624 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
625 },
626 },
627 },
628 expectedErr: nil,
629 expectHTTPListener: false,
630 expectTLSListener: true,
631 ipv6: true,
632 }),
633 Entry("with an ipv6 valid https bind address, and invalid TLS config with unknown CipherSuites", &newServerTableInput{
634 opts: Opts{
635 Handler: handler,
636 SecureBindAddress: "[::1]:0",
637 TLS: &options.TLS{
638 Key: &ipv4KeyDataSource,
639 Cert: &ipv4CertDataSource,
640 CipherSuites: []string{
641 "TLS_RSA_WITH_RC4_64_SHA",
642 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
643 },
644 },
645 },
646 expectedErr: errors.New("error setting up TLS listener: could not parse cipher suites: unknown TLS cipher suite name specified \"TLS_RSA_WITH_RC4_64_SHA\""),
647 expectHTTPListener: false,
648 expectTLSListener: true,
649 ipv6: true,
650 }),
651 )
652 })
654 Context("Start", func() {
655 var srv Server
656 var ctx context.Context
657 var cancel context.CancelFunc
659 BeforeEach(func() {
660 ctx, cancel = context.WithCancel(context.Background())
661 })
663 AfterEach(func() {
664 cancel()
665 Eventually(Goroutines).ShouldNot(HaveLeaked())
667 })
669 Context("with an fd ipv4 http server", func() {
670 var listenAddr string
672 BeforeEach(func() {
673 l, err := net.Listen("tcp", "127.0.0.1:0")
674 Expect(err).ToNot(HaveOccurred())
675 f, err := l.(*net.TCPListener).File()
676 Expect(err).ToNot(HaveOccurred())
678 srv, err = NewServer(Opts{
679 Handler: handler,
680 BindAddress: "fd:3",
681 fdFiles: []*os.File{f},
682 })
683 Expect(err).ToNot(HaveOccurred())
685 listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
686 })
688 It("Starts the server and serves the handler", func() {
689 go func() {
690 defer GinkgoRecover()
691 Expect(srv.Start(ctx)).To(Succeed())
692 }()
694 resp, err := httpGet(ctx, listenAddr)
695 Expect(err).ToNot(HaveOccurred())
696 Expect(resp.StatusCode).To(Equal(http.StatusOK))
698 body, err := io.ReadAll(resp.Body)
699 Expect(err).ToNot(HaveOccurred())
700 Expect(string(body)).To(Equal(hello))
701 })
703 It("Stops the server when the context is cancelled", func() {
704 go func() {
705 defer GinkgoRecover()
706 Expect(srv.Start(ctx)).To(Succeed())
707 }()
709 _, err := httpGet(ctx, listenAddr)
710 Expect(err).ToNot(HaveOccurred())
712 cancel()
714 Eventually(func() error {
715 _, err := httpGet(ctx, listenAddr)
716 return err
717 }).Should(HaveOccurred())
718 })
719 })
721 Context("with an ipv4 http server", func() {
722 var listenAddr string
724 BeforeEach(func() {
725 var err error
726 srv, err = NewServer(Opts{
727 Handler: handler,
728 BindAddress: "127.0.0.1:0",
729 })
730 Expect(err).ToNot(HaveOccurred())
732 s, ok := srv.(*server)
733 Expect(ok).To(BeTrue())
735 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
736 })
738 It("Starts the server and serves the handler", func() {
739 go func() {
740 defer GinkgoRecover()
741 Expect(srv.Start(ctx)).To(Succeed())
742 }()
744 resp, err := httpGet(ctx, listenAddr)
745 Expect(err).ToNot(HaveOccurred())
746 Expect(resp.StatusCode).To(Equal(http.StatusOK))
748 body, err := io.ReadAll(resp.Body)
749 Expect(err).ToNot(HaveOccurred())
750 Expect(string(body)).To(Equal(hello))
751 })
753 It("Stops the server when the context is cancelled", func() {
754 go func() {
755 defer GinkgoRecover()
756 Expect(srv.Start(ctx)).To(Succeed())
757 }()
759 _, err := httpGet(ctx, listenAddr)
760 Expect(err).ToNot(HaveOccurred())
762 cancel()
764 Eventually(func() error {
765 _, err := httpGet(ctx, listenAddr)
766 return err
767 }).Should(HaveOccurred())
768 })
769 })
771 Context("with an ipv4 https server", func() {
772 var secureListenAddr string
774 BeforeEach(func() {
775 var err error
776 srv, err = NewServer(Opts{
777 Handler: handler,
778 SecureBindAddress: "127.0.0.1:0",
779 TLS: &options.TLS{
780 Key: &ipv4KeyDataSource,
781 Cert: &ipv4CertDataSource,
782 },
783 })
784 Expect(err).ToNot(HaveOccurred())
786 s, ok := srv.(*server)
787 Expect(ok).To(BeTrue())
789 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
790 })
792 It("Starts the server and serves the handler", func() {
793 go func() {
794 defer GinkgoRecover()
795 Expect(srv.Start(ctx)).To(Succeed())
796 }()
798 resp, err := httpGet(ctx, secureListenAddr)
799 Expect(err).ToNot(HaveOccurred())
800 Expect(resp.StatusCode).To(Equal(http.StatusOK))
802 body, err := io.ReadAll(resp.Body)
803 Expect(err).ToNot(HaveOccurred())
804 Expect(string(body)).To(Equal(hello))
805 })
807 It("Stops the server when the context is cancelled", func() {
808 go func() {
809 defer GinkgoRecover()
810 Expect(srv.Start(ctx)).To(Succeed())
811 }()
813 _, err := httpGet(ctx, secureListenAddr)
814 Expect(err).ToNot(HaveOccurred())
816 cancel()
818 Eventually(func() error {
819 _, err := httpGet(ctx, secureListenAddr)
820 return err
821 }).Should(HaveOccurred())
822 })
824 It("Serves the certificate provided", func() {
825 go func() {
826 defer GinkgoRecover()
827 Expect(srv.Start(ctx)).To(Succeed())
828 }()
830 resp, err := httpGet(ctx, secureListenAddr)
831 Expect(err).ToNot(HaveOccurred())
832 Expect(resp.StatusCode).To(Equal(http.StatusOK))
834 Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
835 Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
836 Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv4CertData))
837 })
838 })
840 Context("with a fd ipv4 http and an ipv4 https server", func() {
841 var listenAddr, secureListenAddr string
843 BeforeEach(func() {
844 l, err := net.Listen("tcp", "127.0.0.1:0")
845 Expect(err).ToNot(HaveOccurred())
846 f, err := l.(*net.TCPListener).File()
847 Expect(err).ToNot(HaveOccurred())
849 srv, err = NewServer(Opts{
850 Handler: handler,
851 BindAddress: "fd:3",
852 fdFiles: []*os.File{f},
853 SecureBindAddress: "127.0.0.1:0",
854 TLS: &options.TLS{
855 Key: &ipv4KeyDataSource,
856 Cert: &ipv4CertDataSource,
857 },
858 })
859 Expect(err).ToNot(HaveOccurred())
861 s, ok := srv.(*server)
862 Expect(ok).To(BeTrue())
864 listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
865 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
866 })
868 It("Starts the server and serves the handler on http", func() {
869 go func() {
870 defer GinkgoRecover()
871 Expect(srv.Start(ctx)).To(Succeed())
872 }()
874 resp, err := httpGet(ctx, listenAddr)
875 Expect(err).ToNot(HaveOccurred())
876 Expect(resp.StatusCode).To(Equal(http.StatusOK))
878 body, err := io.ReadAll(resp.Body)
879 Expect(err).ToNot(HaveOccurred())
880 Expect(string(body)).To(Equal(hello))
881 })
883 It("Starts the server and serves the handler on https", func() {
884 go func() {
885 defer GinkgoRecover()
886 Expect(srv.Start(ctx)).To(Succeed())
887 }()
889 resp, err := httpGet(ctx, secureListenAddr)
890 Expect(err).ToNot(HaveOccurred())
891 Expect(resp.StatusCode).To(Equal(http.StatusOK))
893 body, err := io.ReadAll(resp.Body)
894 Expect(err).ToNot(HaveOccurred())
895 Expect(string(body)).To(Equal(hello))
896 })
898 It("Stops both servers when the context is cancelled", func() {
899 go func() {
900 defer GinkgoRecover()
901 Expect(srv.Start(ctx)).To(Succeed())
902 }()
904 _, err := httpGet(ctx, listenAddr)
905 Expect(err).ToNot(HaveOccurred())
906 _, err = httpGet(ctx, secureListenAddr)
907 Expect(err).ToNot(HaveOccurred())
909 cancel()
911 Eventually(func() error {
912 _, err := httpGet(ctx, listenAddr)
913 return err
914 }).Should(HaveOccurred())
915 Eventually(func() error {
916 _, err := httpGet(ctx, secureListenAddr)
917 return err
918 }).Should(HaveOccurred())
919 })
920 })
922 Context("with both an ipv4 http and an ipv4 https server", func() {
923 var listenAddr, secureListenAddr string
925 BeforeEach(func() {
926 var err error
927 srv, err = NewServer(Opts{
928 Handler: handler,
929 BindAddress: "127.0.0.1:0",
930 SecureBindAddress: "127.0.0.1:0",
931 TLS: &options.TLS{
932 Key: &ipv4KeyDataSource,
933 Cert: &ipv4CertDataSource,
934 },
935 })
936 Expect(err).ToNot(HaveOccurred())
938 s, ok := srv.(*server)
939 Expect(ok).To(BeTrue())
941 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
942 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
943 })
945 It("Starts the server and serves the handler on http", func() {
946 go func() {
947 defer GinkgoRecover()
948 Expect(srv.Start(ctx)).To(Succeed())
949 }()
951 resp, err := httpGet(ctx, listenAddr)
952 Expect(err).ToNot(HaveOccurred())
953 Expect(resp.StatusCode).To(Equal(http.StatusOK))
955 body, err := io.ReadAll(resp.Body)
956 Expect(err).ToNot(HaveOccurred())
957 Expect(string(body)).To(Equal(hello))
958 })
960 It("Starts the server and serves the handler on https", func() {
961 go func() {
962 defer GinkgoRecover()
963 Expect(srv.Start(ctx)).To(Succeed())
964 }()
966 resp, err := httpGet(ctx, secureListenAddr)
967 Expect(err).ToNot(HaveOccurred())
968 Expect(resp.StatusCode).To(Equal(http.StatusOK))
970 body, err := io.ReadAll(resp.Body)
971 Expect(err).ToNot(HaveOccurred())
972 Expect(string(body)).To(Equal(hello))
973 })
975 It("Stops both servers when the context is cancelled", func() {
976 go func() {
977 defer GinkgoRecover()
978 Expect(srv.Start(ctx)).To(Succeed())
979 }()
981 _, err := httpGet(ctx, listenAddr)
982 Expect(err).ToNot(HaveOccurred())
983 _, err = httpGet(ctx, secureListenAddr)
984 Expect(err).ToNot(HaveOccurred())
986 cancel()
988 Eventually(func() error {
989 _, err := httpGet(ctx, listenAddr)
990 return err
991 }).Should(HaveOccurred())
992 Eventually(func() error {
993 _, err := httpGet(ctx, secureListenAddr)
994 return err
995 }).Should(HaveOccurred())
996 })
997 })
999 Context("with an ipv6 http server", func() {
1000 var listenAddr string
1002 BeforeEach(func() {
1003 skipDevContainer()
1004 var err error
1005 srv, err = NewServer(Opts{
1006 Handler: handler,
1007 BindAddress: "[::1]:0",
1008 })
1009 Expect(err).ToNot(HaveOccurred())
1011 s, ok := srv.(*server)
1012 Expect(ok).To(BeTrue())
1014 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
1015 })
1017 It("Starts the server and serves the handler", func() {
1018 go func() {
1019 defer GinkgoRecover()
1020 Expect(srv.Start(ctx)).To(Succeed())
1021 }()
1023 resp, err := httpGet(ctx, listenAddr)
1024 Expect(err).ToNot(HaveOccurred())
1025 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1027 body, err := io.ReadAll(resp.Body)
1028 Expect(err).ToNot(HaveOccurred())
1029 Expect(string(body)).To(Equal(hello))
1030 })
1032 It("Stops the server when the context is cancelled", func() {
1033 go func() {
1034 defer GinkgoRecover()
1035 Expect(srv.Start(ctx)).To(Succeed())
1036 }()
1038 _, err := httpGet(ctx, listenAddr)
1039 Expect(err).ToNot(HaveOccurred())
1041 cancel()
1043 Eventually(func() error {
1044 _, err := httpGet(ctx, listenAddr)
1045 return err
1046 }).Should(HaveOccurred())
1047 })
1048 })
1050 Context("with an ipv6 https server", func() {
1051 var secureListenAddr string
1053 BeforeEach(func() {
1054 skipDevContainer()
1055 var err error
1056 srv, err = NewServer(Opts{
1057 Handler: handler,
1058 SecureBindAddress: "[::1]:0",
1059 TLS: &options.TLS{
1060 Key: &ipv6KeyDataSource,
1061 Cert: &ipv6CertDataSource,
1062 },
1063 })
1064 Expect(err).ToNot(HaveOccurred())
1066 s, ok := srv.(*server)
1067 Expect(ok).To(BeTrue())
1069 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
1070 })
1072 It("Starts the server and serves the handler", func() {
1073 go func() {
1074 defer GinkgoRecover()
1075 Expect(srv.Start(ctx)).To(Succeed())
1076 }()
1078 resp, err := httpGet(ctx, secureListenAddr)
1079 Expect(err).ToNot(HaveOccurred())
1080 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1082 body, err := io.ReadAll(resp.Body)
1083 Expect(err).ToNot(HaveOccurred())
1084 Expect(string(body)).To(Equal(hello))
1085 })
1087 It("Stops the server when the context is cancelled", func() {
1088 go func() {
1089 defer GinkgoRecover()
1090 Expect(srv.Start(ctx)).To(Succeed())
1091 }()
1093 _, err := httpGet(ctx, secureListenAddr)
1094 Expect(err).ToNot(HaveOccurred())
1096 cancel()
1098 Eventually(func() error {
1099 _, err := httpGet(ctx, secureListenAddr)
1100 return err
1101 }).Should(HaveOccurred())
1102 })
1104 It("Serves the certificate provided", func() {
1105 go func() {
1106 defer GinkgoRecover()
1107 Expect(srv.Start(ctx)).To(Succeed())
1108 }()
1110 resp, err := httpGet(ctx, secureListenAddr)
1111 Expect(err).ToNot(HaveOccurred())
1112 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1114 Expect(resp.TLS.VerifiedChains).Should(HaveLen(1))
1115 Expect(resp.TLS.VerifiedChains[0]).Should(HaveLen(1))
1116 Expect(resp.TLS.VerifiedChains[0][0].Raw).Should(Equal(ipv6CertData))
1117 })
1118 })
1120 Context("with an fd ipv6 http and an ipv6 https server", func() {
1121 var listenAddr, secureListenAddr string
1123 BeforeEach(func() {
1124 skipDevContainer()
1125 l, err := net.Listen("tcp", "[::1]:0")
1126 Expect(err).ToNot(HaveOccurred())
1127 f, err := l.(*net.TCPListener).File()
1128 Expect(err).ToNot(HaveOccurred())
1130 srv, err = NewServer(Opts{
1131 Handler: handler,
1132 BindAddress: "fd:3",
1133 fdFiles: []*os.File{f},
1134 SecureBindAddress: "[::1]:0",
1135 TLS: &options.TLS{
1136 Key: &ipv6KeyDataSource,
1137 Cert: &ipv6CertDataSource,
1138 },
1139 })
1140 Expect(err).ToNot(HaveOccurred())
1142 s, ok := srv.(*server)
1143 Expect(ok).To(BeTrue())
1145 listenAddr = fmt.Sprintf("http://%s/", l.Addr().String())
1146 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
1147 })
1149 It("Starts the server and serves the handler on http", func() {
1150 go func() {
1151 defer GinkgoRecover()
1152 Expect(srv.Start(ctx)).To(Succeed())
1153 }()
1155 resp, err := httpGet(ctx, listenAddr)
1156 Expect(err).ToNot(HaveOccurred())
1157 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1159 body, err := io.ReadAll(resp.Body)
1160 Expect(err).ToNot(HaveOccurred())
1161 Expect(string(body)).To(Equal(hello))
1162 })
1164 It("Starts the server and serves the handler on https", func() {
1165 go func() {
1166 defer GinkgoRecover()
1167 Expect(srv.Start(ctx)).To(Succeed())
1168 }()
1170 resp, err := httpGet(ctx, secureListenAddr)
1171 Expect(err).ToNot(HaveOccurred())
1172 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1174 body, err := io.ReadAll(resp.Body)
1175 Expect(err).ToNot(HaveOccurred())
1176 Expect(string(body)).To(Equal(hello))
1177 })
1179 It("Stops both servers when the context is cancelled", func() {
1180 go func() {
1181 defer GinkgoRecover()
1182 Expect(srv.Start(ctx)).To(Succeed())
1183 }()
1185 _, err := httpGet(ctx, listenAddr)
1186 Expect(err).ToNot(HaveOccurred())
1187 _, err = httpGet(ctx, secureListenAddr)
1188 Expect(err).ToNot(HaveOccurred())
1190 cancel()
1192 Eventually(func() error {
1193 _, err := httpGet(ctx, listenAddr)
1194 return err
1195 }).Should(HaveOccurred())
1196 Eventually(func() error {
1197 _, err := httpGet(ctx, secureListenAddr)
1198 return err
1199 }).Should(HaveOccurred())
1200 })
1201 })
1203 Context("with both an ipv6 http and an ipv6 https server", func() {
1204 var listenAddr, secureListenAddr string
1206 BeforeEach(func() {
1207 skipDevContainer()
1208 var err error
1209 srv, err = NewServer(Opts{
1210 Handler: handler,
1211 BindAddress: "[::1]:0",
1212 SecureBindAddress: "[::1]:0",
1213 TLS: &options.TLS{
1214 Key: &ipv6KeyDataSource,
1215 Cert: &ipv6CertDataSource,
1216 },
1217 })
1218 Expect(err).ToNot(HaveOccurred())
1220 s, ok := srv.(*server)
1221 Expect(ok).To(BeTrue())
1223 listenAddr = fmt.Sprintf("http://%s/", s.listener.Addr().String())
1224 secureListenAddr = fmt.Sprintf("https://%s/", s.tlsListener.Addr().String())
1225 })
1227 It("Starts the server and serves the handler on http", func() {
1228 go func() {
1229 defer GinkgoRecover()
1230 Expect(srv.Start(ctx)).To(Succeed())
1231 }()
1233 resp, err := httpGet(ctx, listenAddr)
1234 Expect(err).ToNot(HaveOccurred())
1235 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1237 body, err := io.ReadAll(resp.Body)
1238 Expect(err).ToNot(HaveOccurred())
1239 Expect(string(body)).To(Equal(hello))
1240 })
1242 It("Starts the server and serves the handler on https", func() {
1243 go func() {
1244 defer GinkgoRecover()
1245 Expect(srv.Start(ctx)).To(Succeed())
1246 }()
1248 resp, err := httpGet(ctx, secureListenAddr)
1249 Expect(err).ToNot(HaveOccurred())
1250 Expect(resp.StatusCode).To(Equal(http.StatusOK))
1252 body, err := io.ReadAll(resp.Body)
1253 Expect(err).ToNot(HaveOccurred())
1254 Expect(string(body)).To(Equal(hello))
1255 })
1257 It("Stops both servers when the context is cancelled", func() {
1258 go func() {
1259 defer GinkgoRecover()
1260 Expect(srv.Start(ctx)).To(Succeed())
1261 }()
1263 _, err := httpGet(ctx, listenAddr)
1264 Expect(err).ToNot(HaveOccurred())
1265 _, err = httpGet(ctx, secureListenAddr)
1266 Expect(err).ToNot(HaveOccurred())
1268 cancel()
1270 Eventually(func() error {
1271 _, err := httpGet(ctx, listenAddr)
1272 return err
1273 }).Should(HaveOccurred())
1274 Eventually(func() error {
1275 _, err := httpGet(ctx, secureListenAddr)
1276 return err
1277 }).Should(HaveOccurred())
1278 })
1279 })
1280 })
1282 Context("getNetworkScheme", func() {
1283 DescribeTable("should return the scheme", func(in, expected string) {
1284 Expect(getNetworkScheme(in)).To(Equal(expected))
1285 },
1286 Entry("ipv4 address with no scheme", "127.0.0.1:0", "tcp"),
1287 Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "tcp"),
1288 Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "tcp"),
1289 Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "unix"),
1290 Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "random"),
1291 Entry("ipv6 address with no scheme", "[::1]:0", "tcp"),
1292 Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "tcp"),
1293 Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "tcp"),
1294 Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "unix"),
1295 Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "random"),
1297 })
1299 Context("getListenAddress", func() {
1300 DescribeTable("should remove the scheme", func(in, expected string) {
1301 Expect(getListenAddress(in)).To(Equal(expected))
1302 },
1303 Entry("ipv4 address with no scheme", "127.0.0.1:0", "127.0.0.1:0"),
1304 Entry("ipv4 address with a tcp scheme", "tcp://127.0.0.1:0", "127.0.0.1:0"),
1305 Entry("ipv4 address with a http scheme", "http://192.168.0.1:1", "192.168.0.1:1"),
1306 Entry("ipv4 address with a unix scheme", "unix://172.168.16.2:2", "172.168.16.2:2"),
1307 Entry("ipv4 address with a random scheme", "random://10.10.10.10:10", "10.10.10.10:10"),
1308 Entry("ipv6 address with no scheme", "[::1]:0", "[::1]:0"),
1309 Entry("ipv6 address with a tcp scheme", "tcp://[::1]:0", "[::1]:0"),
1310 Entry("ipv6 address with a http scheme", "http://[::ffff:c0a8:1]:1", "[::ffff:c0a8:1]:1"),
1311 Entry("ipv6 address with a unix scheme", "unix://[::ffff:aca8:1002]:2", "[::ffff:aca8:1002]:2"),
1312 Entry("ipv6 address with a random scheme", "random://[::ffff:a0a:a0a]:10", "[::ffff:a0a:a0a]:10"),
1314 })
1317func skipDevContainer() {
1318 if os.Getenv("DEVCONTAINER") != "" {
1319 Skip("Skipping testing in DevContainer environment")