Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions backend/cmd/headlamp.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ func createHeadlampHandler(config *HeadlampConfig) http.Handler {
logger.Log(logger.LevelInfo, nil, nil, "me Groups Paths: "+config.MeGroupsPaths)
logger.Log(logger.LevelInfo, nil, nil, "me User Info URL: "+config.MeUserInfoURL)
logger.Log(logger.LevelInfo, nil, nil, "Base URL: "+config.BaseURL)
logger.Log(logger.LevelInfo, nil, nil, "Session TTL: "+fmt.Sprint(config.SessionTTL))
logger.Log(logger.LevelInfo, nil, nil, "Use In Cluster: "+fmt.Sprint(config.UseInCluster))
logger.Log(logger.LevelInfo, nil, nil, "Watch Plugins Changes: "+fmt.Sprint(config.WatchPluginsChanges))

Expand Down Expand Up @@ -859,7 +860,7 @@ func createHeadlampHandler(config *HeadlampConfig) http.Handler {
}

// Set auth cookie
auth.SetTokenCookie(w, r, oauthConfig.Cluster, rawUserToken, config.BaseURL)
auth.SetTokenCookie(w, r, oauthConfig.Cluster, rawUserToken, config.BaseURL, config.SessionTTL)

redirectURL += fmt.Sprintf("auth?cluster=%1s", oauthConfig.Cluster)

Expand Down Expand Up @@ -942,7 +943,7 @@ func (c *HeadlampConfig) refreshAndSetToken(oidcAuthConfig *kubeconfig.OidcConfi
}

// Set refreshed token in cookie
auth.SetTokenCookie(w, r, cluster, newTokenString, c.BaseURL)
auth.SetTokenCookie(w, r, cluster, newTokenString, c.BaseURL, c.SessionTTL)

c.TelemetryHandler.RecordEvent(span, "Token refreshed successfully")
}
Expand Down Expand Up @@ -2534,7 +2535,7 @@ func (c *HeadlampConfig) handleSetToken(w http.ResponseWriter, r *http.Request)
if req.Token == "" {
auth.ClearTokenCookie(w, r, cluster, c.BaseURL)
} else {
auth.SetTokenCookie(w, r, cluster, req.Token, c.BaseURL)
auth.SetTokenCookie(w, r, cluster, req.Token, c.BaseURL, c.SessionTTL)
}

w.WriteHeader(http.StatusOK)
Expand Down
1 change: 1 addition & 0 deletions backend/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func buildHeadlampCFG(conf *config.Config, kubeConfigStore kubeconfig.ContextSto
ProxyURLs: strings.Split(conf.ProxyURLs, ","),
TLSCertPath: conf.TLSCertPath,
TLSKeyPath: conf.TLSKeyPath,
SessionTTL: conf.SessionTTL,
}
}

Expand Down
4 changes: 2 additions & 2 deletions backend/pkg/auth/cookies.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func IsSecureContext(r *http.Request) bool {
}

// SetTokenCookie sets an authentication cookie for a specific cluster.
func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token, baseURL string) {
func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token, baseURL string, sessionTTL int) {
// Validate inputs
if cluster == "" || token == "" {
return
Expand All @@ -101,7 +101,7 @@ func SetTokenCookie(w http.ResponseWriter, r *http.Request, cluster, token, base
Secure: secure,
SameSite: http.SameSiteStrictMode,
Path: GetCookiePath(baseURL, cluster),
MaxAge: 86400, // 24 hours
MaxAge: sessionTTL,
}

http.SetCookie(w, cookie)
Expand Down
9 changes: 7 additions & 2 deletions backend/pkg/auth/cookies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ func TestSetAndGetAuthCookie(t *testing.T) {
w := httptest.NewRecorder()

// Test setting a cookie
auth.SetTokenCookie(w, req, "test-cluster", "test-token", "")
testTTL := 100
auth.SetTokenCookie(w, req, "test-cluster", "test-token", "", testTTL)

// Check if cookie was set
cookies := w.Result().Cookies()
Expand All @@ -191,6 +192,10 @@ func TestSetAndGetAuthCookie(t *testing.T) {
t.Error("Expected SameSite to be SameSiteStrictMode")
}

if cookie.MaxAge != testTTL {
t.Errorf("Expected MaxAge to be %d, got %d", testTTL, cookie.MaxAge)
}

// Test getting the cookie
req.AddCookie(cookie)

Expand All @@ -213,7 +218,7 @@ func TestGetAuthCookieChunked(t *testing.T) {
longToken := strings.Repeat("a", 5000)

// Test setting a cookie
auth.SetTokenCookie(w, req, "test-cluster", longToken, "")
auth.SetTokenCookie(w, req, "test-cluster", longToken, "", 86400)

// Check if cookie was set
cookies := w.Result().Cookies()
Expand Down
18 changes: 16 additions & 2 deletions backend/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import (
)

const (
defaultPort = 4466
osWindows = "windows"
defaultPort = 4466
defaultSessionTTL = 86400 // 24 hours in seconds
osWindows = "windows"
)

const (
Expand Down Expand Up @@ -54,6 +55,7 @@ type Config struct {
PluginsDir string `koanf:"plugins-dir"`
UserPluginsDir string `koanf:"user-plugins-dir"`
BaseURL string `koanf:"base-url"`
SessionTTL int `koanf:"session-ttl"`
ProxyURLs string `koanf:"proxy-urls"`
OidcClientID string `koanf:"oidc-client-id"`
OidcValidatorClientID string `koanf:"oidc-validator-client-id"`
Expand Down Expand Up @@ -115,6 +117,16 @@ func (c *Config) Validate() error {
return errors.New("base-url needs to start with a '/' or be empty")
}

if c.SessionTTL <= 0 {
return errors.New("session-ttl cannot be negative or equal to zero")
}

const oneYearInSeconds = 31536000

if c.SessionTTL > oneYearInSeconds {
return errors.New("session-ttl cannot be greater than 1 year")
}

if c.TracingEnabled != nil && *c.TracingEnabled {
if c.ServiceName == "" {
return errors.New("service-name is required when tracing is enabled")
Expand Down Expand Up @@ -430,6 +442,8 @@ func addGeneralFlags(f *flag.FlagSet) {
f.String("plugins-dir", defaultPluginDir(), "Specify the plugins directory to build the backend with")
f.String("user-plugins-dir", defaultUserPluginDir(), "Specify the user-installed plugins directory")
f.String("base-url", "", "Base URL path. eg. /headlamp")
f.Int("session-ttl", defaultSessionTTL, "The time in seconds for the session to be valid"+
"(Default: 86400/24h, Min: 1 , Max: 31536000/1yr )")
f.String("listen-addr", "", "Address to listen on; default is empty, which means listening to any address")
f.Uint("port", defaultPort, "Port to listen from")
f.String("proxy-urls", "", "Allow proxy requests to specified URLs")
Expand Down
1 change: 1 addition & 0 deletions backend/pkg/headlampconfig/headlampConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,5 @@ type HeadlampCFG struct {
ProxyURLs []string
TLSCertPath string
TLSKeyPath string
SessionTTL int
}
1 change: 1 addition & 0 deletions charts/headlamp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ $ helm install my-headlamp headlamp/headlamp \
|--------------------|--------|-----------------------|---------------------------------------------------------------------------|
| config.inCluster | bool | `true` | Run Headlamp in-cluster |
| config.baseURL | string | `""` | Base URL path for Headlamp UI |
| config.sessionTTL | int | `86400` | The time in seconds for the internal session to remain valid (Default: 86400/24h, Min: 1 , Max: 31536000/1yr) |
| config.pluginsDir | string | `"/headlamp/plugins"` | Directory to load Headlamp plugins from |
| config.enableHelm | bool | `false` | Enable Helm operations like install, upgrade and uninstall of Helm charts |
| config.extraArgs | array | `[]` | Additional arguments for Headlamp server |
Expand Down
3 changes: 3 additions & 0 deletions charts/headlamp/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,9 @@ spec:
{{- with .Values.config.pluginsDir}}
- "-plugins-dir={{ . }}"
{{- end }}
{{- if hasKey .Values.config "sessionTTL" }}
- "-session-ttl={{ .Values.config.sessionTTL }}"
{{- end }}
{{- if not $oidc.externalSecret.enabled}}
# Check if externalSecret is disabled
{{- if or (ne $oidc.clientID "") (ne $clientID "") }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
1 change: 1 addition & 0 deletions charts/headlamp/tests/expected_templates/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
1 change: 1 addition & 0 deletions charts/headlamp/tests/expected_templates/extra-args.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
- -insecure-ssl
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
- "-me-user-info-url=$(ME_USER_INFO_URL)"
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
- "-me-user-info-url=$(ME_USER_INFO_URL)"
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
- "-oidc-client-secret=$(OIDC_CLIENT_SECRET)"
- "-oidc-idp-issuer-url=$(OIDC_ISSUER_URL)"
Expand Down
1 change: 1 addition & 0 deletions charts/headlamp/tests/expected_templates/oidc-pkce.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
# Check if clientID is non empty either from env or oidc.config
- "-oidc-client-id=$(OIDC_CLIENT_ID)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
1 change: 1 addition & 0 deletions charts/headlamp/tests/expected_templates/tls-added.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
- "-tls-cert-path=/headlamp-cert/headlamp-ca.crt"
- "-tls-key-path=/headlamp-cert/headlamp-tls.key"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ spec:
- "-in-cluster"
- "-in-cluster-context-name=main"
- "-plugins-dir=/headlamp/plugins"
- "-session-ttl=86400"
# Check if externalSecret is disabled
ports:
- name: http
Expand Down
7 changes: 7 additions & 0 deletions charts/headlamp/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,13 @@
"type": "string",
"description": "Base URL of the application"
},
"sessionTTL": {
"type": "integer",
"description": "The time in seconds for the session to be valid",
"default": 86400,
"minimum": 1,
"maximum": 31536000
},
"oidc": {
"type": "object",
"description": "OIDC configuration",
Expand Down
2 changes: 2 additions & 0 deletions charts/headlamp/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ config:
inClusterContextName: "main"
# -- base url path at which headlamp should run
baseURL: ""
# -- session token TTL in seconds (default is 24 hours)
sessionTTL: 86400
oidc:
# Option 1:
# @param config.oidc.secret - OIDC secret configuration
Expand Down
Loading