mirror of
https://github.com/traefik/traefik
synced 2026-02-03 12:20:33 +00:00
Add support for session-cookie-expires nginx annotation
This commit is contained in:
@@ -288,6 +288,7 @@ The following annotations are organized by category for easier navigation.
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-domain" href="#opt-nginx-ingress-kubernetes-iosession-cookie-domain" title="#opt-nginx-ingress-kubernetes-iosession-cookie-domain">`nginx.ingress.kubernetes.io/session-cookie-domain`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-samesite" href="#opt-nginx-ingress-kubernetes-iosession-cookie-samesite" title="#opt-nginx-ingress-kubernetes-iosession-cookie-samesite">`nginx.ingress.kubernetes.io/session-cookie-samesite`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-max-age" href="#opt-nginx-ingress-kubernetes-iosession-cookie-max-age" title="#opt-nginx-ingress-kubernetes-iosession-cookie-max-age">`nginx.ingress.kubernetes.io/session-cookie-max-age`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-expires" href="#opt-nginx-ingress-kubernetes-iosession-cookie-expires" title="#opt-nginx-ingress-kubernetes-iosession-cookie-expires">`nginx.ingress.kubernetes.io/session-cookie-expires`</a> | |
|
||||
|
||||
### Load Balancing & Backend
|
||||
|
||||
@@ -416,7 +417,6 @@ The following annotations are organized by category for easier navigation.
|
||||
| <a id="opt-nginx-ingress-kubernetes-ioserver-alias" href="#opt-nginx-ingress-kubernetes-ioserver-alias" title="#opt-nginx-ingress-kubernetes-ioserver-alias">`nginx.ingress.kubernetes.io/server-alias`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-ioserver-snippet" href="#opt-nginx-ingress-kubernetes-ioserver-snippet" title="#opt-nginx-ingress-kubernetes-ioserver-snippet">`nginx.ingress.kubernetes.io/server-snippet`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-conditional-samesite-none" href="#opt-nginx-ingress-kubernetes-iosession-cookie-conditional-samesite-none" title="#opt-nginx-ingress-kubernetes-iosession-cookie-conditional-samesite-none">`nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-expires" href="#opt-nginx-ingress-kubernetes-iosession-cookie-expires" title="#opt-nginx-ingress-kubernetes-iosession-cookie-expires">`nginx.ingress.kubernetes.io/session-cookie-expires`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iosession-cookie-change-on-failure" href="#opt-nginx-ingress-kubernetes-iosession-cookie-change-on-failure" title="#opt-nginx-ingress-kubernetes-iosession-cookie-change-on-failure">`nginx.ingress.kubernetes.io/session-cookie-change-on-failure`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iossl-ciphers" href="#opt-nginx-ingress-kubernetes-iossl-ciphers" title="#opt-nginx-ingress-kubernetes-iossl-ciphers">`nginx.ingress.kubernetes.io/ssl-ciphers`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iossl-prefer-server-ciphers" href="#opt-nginx-ingress-kubernetes-iossl-prefer-server-ciphers" title="#opt-nginx-ingress-kubernetes-iossl-prefer-server-ciphers">`nginx.ingress.kubernetes.io/ssl-prefer-server-ciphers`</a> | |
|
||||
|
||||
@@ -298,6 +298,10 @@ type Cookie struct {
|
||||
// Domain defines the host to which the cookie will be sent.
|
||||
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#domaindomain-value
|
||||
Domain string `json:"domain,omitempty" toml:"domain,omitempty" yaml:"domain,omitempty"`
|
||||
|
||||
// Expires defines the number of seconds to add to the current time to calculate the expiration date of the cookie.
|
||||
// This option is exposed only for the Ingress NGINX provider.
|
||||
Expires int `json:"-" toml:"-" yaml:"-" label:"-" file:"-" kv:"-" export:"true"`
|
||||
}
|
||||
|
||||
// SetDefaults set the default values for a Cookie.
|
||||
|
||||
@@ -33,6 +33,7 @@ type ingressConfig struct {
|
||||
SessionCookieDomain *string `annotation:"nginx.ingress.kubernetes.io/session-cookie-domain"`
|
||||
SessionCookieSameSite *string `annotation:"nginx.ingress.kubernetes.io/session-cookie-samesite"`
|
||||
SessionCookieMaxAge *int `annotation:"nginx.ingress.kubernetes.io/session-cookie-max-age"`
|
||||
SessionCookieExpires *int `annotation:"nginx.ingress.kubernetes.io/session-cookie-expires"`
|
||||
|
||||
ServiceUpstream *bool `annotation:"nginx.ingress.kubernetes.io/service-upstream"`
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ metadata:
|
||||
nginx.ingress.kubernetes.io/session-cookie-domain: "foo.localhost"
|
||||
nginx.ingress.kubernetes.io/session-cookie-samesite: "None"
|
||||
nginx.ingress.kubernetes.io/session-cookie-max-age: "42"
|
||||
nginx.ingress.kubernetes.io/session-cookie-expires: "42"
|
||||
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
|
||||
@@ -555,6 +555,7 @@ func (p *Provider) buildService(namespace string, backend netv1.IngressBackend,
|
||||
HTTPOnly: true, // Default value in Nginx.
|
||||
SameSite: strings.ToLower(ptr.Deref(cfg.SessionCookieSameSite, "")),
|
||||
MaxAge: ptr.Deref(cfg.SessionCookieMaxAge, 0),
|
||||
Expires: ptr.Deref(cfg.SessionCookieExpires, 0),
|
||||
Path: ptr.To(ptr.Deref(cfg.SessionCookiePath, "/")),
|
||||
Domain: ptr.Deref(cfg.SessionCookieDomain, ""),
|
||||
},
|
||||
|
||||
@@ -492,6 +492,7 @@ func TestLoadIngresses(t *testing.T) {
|
||||
Domain: "foo.localhost",
|
||||
HTTPOnly: true,
|
||||
MaxAge: 42,
|
||||
Expires: 42,
|
||||
Path: ptr.To("/foobar"),
|
||||
SameSite: "none",
|
||||
Secure: true,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
)
|
||||
@@ -27,6 +28,7 @@ type stickyCookie struct {
|
||||
httpOnly bool
|
||||
sameSite http.SameSite
|
||||
maxAge int
|
||||
expires time.Time
|
||||
path string
|
||||
domain string
|
||||
}
|
||||
@@ -59,6 +61,9 @@ func NewSticky(cookieConfig dynamic.Cookie) *Sticky {
|
||||
if cookieConfig.Path != nil {
|
||||
cookie.path = *cookieConfig.Path
|
||||
}
|
||||
if cookieConfig.Expires > 0 {
|
||||
cookie.expires = time.Now().Add(time.Duration(cookieConfig.Expires) * time.Second)
|
||||
}
|
||||
|
||||
return &Sticky{
|
||||
cookie: cookie,
|
||||
@@ -137,6 +142,7 @@ func (s *Sticky) WriteStickyCookie(rw http.ResponseWriter, name string) error {
|
||||
Secure: s.cookie.secure,
|
||||
SameSite: s.cookie.sameSite,
|
||||
MaxAge: s.cookie.maxAge,
|
||||
Expires: s.cookie.expires,
|
||||
}
|
||||
http.SetCookie(rw, cookie)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -103,15 +104,17 @@ func TestSticky_StickyHandler(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSticky_WriteStickyCookie(t *testing.T) {
|
||||
sticky := NewSticky(dynamic.Cookie{
|
||||
cookieConfig := dynamic.Cookie{
|
||||
Name: "test",
|
||||
Secure: true,
|
||||
HTTPOnly: true,
|
||||
SameSite: "none",
|
||||
MaxAge: 42,
|
||||
Expires: 10,
|
||||
Path: pointer("/foo"),
|
||||
Domain: "foo.com",
|
||||
})
|
||||
}
|
||||
sticky := NewSticky(cookieConfig)
|
||||
|
||||
// Should return an error if the handler does not exist.
|
||||
res := httptest.NewRecorder()
|
||||
@@ -133,6 +136,7 @@ func TestSticky_WriteStickyCookie(t *testing.T) {
|
||||
assert.True(t, cookie.HttpOnly)
|
||||
assert.Equal(t, http.SameSiteNoneMode, cookie.SameSite)
|
||||
assert.Equal(t, 42, cookie.MaxAge)
|
||||
assert.WithinDuration(t, time.Now(), cookie.Expires, time.Duration(cookieConfig.Expires)*time.Second)
|
||||
assert.Equal(t, "/foo", cookie.Path)
|
||||
assert.Equal(t, "foo.com", cookie.Domain)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user