Skip to content

Commit d062f7d

Browse files
committed
backend: allow OIDC cookies when in-cluster is false via flag
1 parent d7d68c3 commit d062f7d

File tree

9 files changed

+50
-6
lines changed

9 files changed

+50
-6
lines changed

backend/cmd/headlamp.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,8 +1284,8 @@ func (c *HeadlampConfig) helmRouteReleaseHandler(
12841284
// Create a copy of the context to avoid modifying the cached context
12851285
context = context.Copy()
12861286

1287-
// If headlamp is running in cluster, use the token from the cookie for oidc auth
1288-
if c.UseInCluster && context.OidcConf != nil {
1287+
// If running in cluster or explicitly enabled via flag, use the token from the cookie for oidc auth
1288+
if (c.UseInCluster || c.OidcUseCookie) && context.OidcConf != nil {
12891289
setTokenFromCookie(r, clusterName)
12901290
}
12911291

backend/cmd/headlamp_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,3 +1972,28 @@ func TestHandleClusterServiceProxy(t *testing.T) {
19721972
assert.Equal(t, "OK", rr.Body.String())
19731973
}
19741974
}
1975+
1976+
// TestOidcUseCookieLogic verifies that the mechanism for promoting an OIDC token
1977+
// from a cookie to the Authorization header works as expected.
1978+
func TestOidcUseCookieLogic(t *testing.T) {
1979+
clusterName := "test-cluster-oidc"
1980+
testToken := "fake-token-for-testing"
1981+
cookieName := "headlamp-auth-" + clusterName + ".0"
1982+
1983+
req, err := http.NewRequestWithContext(context.Background(), "GET", "/api/v1/clusters/"+clusterName, nil)
1984+
assert.NoError(t, err)
1985+
1986+
req.AddCookie(&http.Cookie{
1987+
Name: cookieName,
1988+
Value: testToken,
1989+
})
1990+
1991+
setTokenFromCookie(req, clusterName)
1992+
1993+
got := req.Header.Get("Authorization")
1994+
want := "Bearer " + testToken
1995+
1996+
if got != want {
1997+
t.Errorf("got %q, want %q", got, want)
1998+
}
1999+
}

backend/cmd/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ func buildHeadlampCFG(conf *config.Config, kubeConfigStore kubeconfig.ContextSto
100100
ProxyURLs: strings.Split(conf.ProxyURLs, ","),
101101
TLSCertPath: conf.TLSCertPath,
102102
TLSKeyPath: conf.TLSKeyPath,
103+
OidcUseCookie: conf.OidcUseCookie,
103104
}
104105
}
105106

backend/pkg/config/config.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type Config struct {
6363
OidcValidatorIdpIssuerURL string `koanf:"oidc-validator-idp-issuer-url"`
6464
OidcScopes string `koanf:"oidc-scopes"`
6565
OidcUseAccessToken bool `koanf:"oidc-use-access-token"`
66+
OidcUseCookie bool `koanf:"oidc-use-cookie"`
6667
OidcSkipTLSVerify bool `koanf:"oidc-skip-tls-verify"`
6768
OidcCAFile string `koanf:"oidc-ca-file"`
6869
MeUsernamePath string `koanf:"me-username-path"`
@@ -86,10 +87,11 @@ type Config struct {
8687
}
8788

8889
func (c *Config) Validate() error {
89-
if !c.InCluster && (c.OidcClientID != "" || c.OidcClientSecret != "" || c.OidcIdpIssuerURL != "" ||
90+
if !c.InCluster && !c.OidcUseCookie && (c.OidcClientID != "" || c.OidcClientSecret != "" || c.OidcIdpIssuerURL != "" ||
9091
c.OidcValidatorClientID != "" || c.OidcValidatorIdpIssuerURL != "") {
91-
return errors.New(`oidc-client-id, oidc-client-secret, oidc-idp-issuer-url, oidc-validator-client-id,
92-
oidc-validator-idp-issuer-url, flags are only meant to be used in inCluster mode`)
92+
return errors.New("oidc-client-id, oidc-client-secret, oidc-idp-issuer-url, " +
93+
"oidc-validator-client-id, oidc-validator-idp-issuer-url, flags are only " +
94+
"meant to be used in inCluster mode or with --oidc-use-cookie")
9395
}
9496

9597
// OIDC TLS verification warning.
@@ -447,6 +449,7 @@ func addOIDCFlags(f *flag.FlagSet) {
447449
f.Bool("oidc-skip-tls-verify", false, "Skip TLS verification for OIDC")
448450
f.String("oidc-ca-file", "", "CA file for OIDC")
449451
f.Bool("oidc-use-access-token", false, "Setup oidc to pass through the access_token instead of the default id_token")
452+
f.Bool("oidc-use-cookie", false, "Enable OIDC cookie usage even when not running in-cluster")
450453
f.Bool("oidc-use-pkce", false, "Use PKCE (Proof Key for Code Exchange) for enhanced security in OIDC flow")
451454
f.String("me-username-path", DefaultMeUsernamePath,
452455
"Comma separated JMESPath expressions used to read username from the JWT payload")

backend/pkg/config/config_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ func TestParseBasic(t *testing.T) {
5555
assert.Equal(t, config.DefaultMeUsernamePath, conf.MeUsernamePath)
5656
},
5757
},
58+
{
59+
name: "oidc_use_cookie",
60+
args: []string{"go run ./cmd", "--oidc-use-cookie", "--oidc-client-id=my-id"},
61+
verify: func(t *testing.T, conf *config.Config) {
62+
assert.Equal(t, true, conf.OidcUseCookie)
63+
assert.Equal(t, "my-id", conf.OidcClientID)
64+
},
65+
},
5866
}
5967

6068
for _, tt := range tests {
@@ -173,7 +181,7 @@ func TestParseErrors(t *testing.T) {
173181
{
174182
name: "oidc_settings_without_incluster",
175183
args: []string{"go run ./cmd", "-oidc-client-id=noClient"},
176-
errorContains: "are only meant to be used in inCluster mode",
184+
errorContains: "flags are only meant to be used in inCluster mode or with --oidc-use-cookie",
177185
},
178186
{
179187
name: "invalid_base_url",

backend/pkg/headlampconfig/headlampConfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,5 @@ type HeadlampCFG struct {
6262
ProxyURLs []string
6363
TLSCertPath string
6464
TLSKeyPath string
65+
OidcUseCookie bool
6566
}

charts/headlamp/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ $ helm install my-headlamp headlamp/headlamp \
8686
| config.oidc.issuerURL | string | `""` | OIDC issuer URL |
8787
| config.oidc.scopes | string | `""` | OIDC scopes to be used |
8888
| config.oidc.usePKCE | bool | `false` | Use PKCE (Proof Key for Code Exchange) for enhanced security in OIDC flow |
89+
| config.oidc.useCookie | bool | `false` | Enable using OIDC cookie for authentication outside of cluster |
8990
| config.oidc.secret.create | bool | `true` | Create OIDC secret using provided values |
9091
| config.oidc.secret.name | string | `"oidc"` | Name of the OIDC secret |
9192
| config.oidc.externalSecret.enabled | bool | `false` | Enable using external secret for OIDC |

charts/headlamp/templates/deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ spec:
242242
{{- if .Values.config.watchPlugins }}
243243
- "-watch-plugins-changes"
244244
{{- end }}
245+
{{- if .Values.config.oidc.useCookie }}
246+
- "-oidc-use-cookie"
247+
{{- end }}
245248
{{- with .Values.config.pluginsDir}}
246249
- "-plugins-dir={{ . }}"
247250
{{- end }}

charts/headlamp/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ config:
8484
useAccessToken: false
8585
# -- Use PKCE (Proof Key for Code Exchange) for enhanced security in OIDC flow
8686
usePKCE: false
87+
# -- Enable using OIDC cookie for authentication outside of cluster
88+
useCookie: false
8789

8890
# Option 3:
8991
# @param config.oidc - External OIDC secret configuration

0 commit comments

Comments
 (0)