@marcel91200 / caddy Mirror · read-only / commits / da6a569e
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 12, 17:00 UTC

reverseproxy: cookie should be Secure and SameSite=None when TLS (#6115)

* reverseproxy: cookie should be Secure and SameSite=None when TLS * Update modules/caddyhttp/reverseproxy/selectionpolicies_test.go Co-authored-by: Mohammed Al Sahaf <mohammed@caffeinatedwonders.com> --------- Co-authored-by: Mohammed Al Sahaf <mohammed@caffeinatedwonders.com>

Sam Ottenhoff committed Feb 23, 2024 at 14:45 UTC da6a569e859f4dfbbebfd084060e15d940de8861
2 files changed +66 -2
modules/caddyhttp/reverseproxy/selectionpolicies.go
+12 -2
@@ -655,12 +655,22 @@ func (s CookieHashSelection) Select(pool UpstreamPool, req *http.Request, w http
655 if err != nil {
656 return upstream
657 }
658 - http.SetCookie(w, &http.Cookie{
658 + cookie := &http.Cookie{
659 Name: s.Name,
660 Value: sha,
661 Path: "/",
662 Secure: false,
663 - })
663 + }
664 + isProxyHttps := false
665 + if trusted, ok := caddyhttp.GetVar(req.Context(), caddyhttp.TrustedProxyVarKey).(bool); ok && trusted {
666 + xfp, xfpOk, _ := lastHeaderValue(req.Header, "X-Forwarded-Proto")
667 + isProxyHttps = xfpOk && xfp == "https"
668 + }
669 + if req.TLS != nil || isProxyHttps {
670 + cookie.Secure = true
671 + cookie.SameSite = http.SameSiteNoneMode
672 + }
673 + http.SetCookie(w, cookie)
674 return upstream
675 }
676
modules/caddyhttp/reverseproxy/selectionpolicies_test.go
+54
@@ -658,6 +658,9 @@ func TestCookieHashPolicy(t *testing.T) {
658 if cookieServer1.Name != "lb" {
659 t.Error("cookieHashPolicy should set a cookie with name lb")
660 }
661 + if cookieServer1.Secure {
662 + t.Error("cookieHashPolicy should set cookie Secure attribute to false when request is not secure")
663 + }
664 if h != pool[0] {
665 t.Error("Expected cookieHashPolicy host to be the first only available host.")
666 }
@@ -687,6 +690,57 @@ func TestCookieHashPolicy(t *testing.T) {
690 }
691 }
692
693 +func TestCookieHashPolicyWithSecureRequest(t *testing.T) {
694 + ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
695 + defer cancel()
696 + cookieHashPolicy := CookieHashSelection{}
697 + if err := cookieHashPolicy.Provision(ctx); err != nil {
698 + t.Errorf("Provision error: %v", err)
699 + t.FailNow()
700 + }
701 +
702 + pool := testPool()
703 + pool[0].Dial = "localhost:8080"
704 + pool[1].Dial = "localhost:8081"
705 + pool[2].Dial = "localhost:8082"
706 + pool[0].setHealthy(true)
707 + pool[1].setHealthy(false)
708 + pool[2].setHealthy(false)
709 +
710 + // Create a test server that serves HTTPS requests
711 + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
712 + h := cookieHashPolicy.Select(pool, r, w)
713 + if h != pool[0] {
714 + t.Error("Expected cookieHashPolicy host to be the first only available host.")
715 + }
716 + }))
717 + defer ts.Close()
718 +
719 + // Make a new HTTPS request to the test server
720 + client := ts.Client()
721 + request, err := http.NewRequest(http.MethodGet, ts.URL+"/test", nil)
722 + if err != nil {
723 + t.Fatal(err)
724 + }
725 + response, err := client.Do(request)
726 + if err != nil {
727 + t.Fatal(err)
728 + }
729 +
730 + // Check if the cookie set is Secure and has SameSiteNone mode
731 + cookies := response.Cookies()
732 + if len(cookies) == 0 {
733 + t.Fatal("Expected a cookie to be set")
734 + }
735 + cookie := cookies[0]
736 + if !cookie.Secure {
737 + t.Error("Expected cookie Secure attribute to be true when request is secure")
738 + }
739 + if cookie.SameSite != http.SameSiteNoneMode {
740 + t.Error("Expected cookie SameSite attribute to be None when request is secure")
741 + }
742 +}
743 +
744 func TestCookieHashPolicyWithFirstFallback(t *testing.T) {
745 ctx, cancel := caddy.NewContext(caddy.Context{Context: context.Background()})
746 defer cancel()