From 175ae56a11a8ef884033ea07a33c0a055f32f0ef Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Tue, 30 Jul 2024 01:18:09 +0100 Subject: [PATCH 1/8] Support Logout Endpoint for OIDC and allow customisable Post-logout Redirect URI Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- config/crd/bases/k8s.nginx.org_policies.yaml | 4 + deploy/crds.yaml | 4 + docs/content/configuration/policy-resource.md | 6 +- examples/custom-resources/oidc/README.md | 5 + .../custom-resources/oidc/keycloak_setup.md | 13 +- .../custom-resources/oidc/nginx-config.yaml | 1 - examples/custom-resources/oidc/oidc.yaml | 3 + internal/configs/version2/http.go | 2 + .../version2/nginx-plus.virtualserver.tmpl | 5 +- internal/configs/virtualserver.go | 6 + internal/configs/virtualserver_test.go | 18 + pkg/apis/configuration/v1/types.go | 2 + pkg/apis/configuration/validation/policy.go | 10 + .../configuration/validation/policy_test.go | 482 ++++++++++++------ 14 files changed, 383 insertions(+), 178 deletions(-) diff --git a/config/crd/bases/k8s.nginx.org_policies.yaml b/config/crd/bases/k8s.nginx.org_policies.yaml index ad4f26276..b2a8e1c3f 100644 --- a/config/crd/bases/k8s.nginx.org_policies.yaml +++ b/config/crd/bases/k8s.nginx.org_policies.yaml @@ -161,6 +161,10 @@ spec: type: string jwksURI: type: string + logoutEndpoint: + type: string + logoutRedirect: + type: string redirectURI: type: string scope: diff --git a/deploy/crds.yaml b/deploy/crds.yaml index 7b49247e1..0eb945ac1 100644 --- a/deploy/crds.yaml +++ b/deploy/crds.yaml @@ -363,6 +363,10 @@ spec: type: string jwksURI: type: string + logoutEndpoint: + type: string + logoutRedirect: + type: string redirectURI: type: string scope: diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md index 55b91fa8a..cd9cc706a 100644 --- a/docs/content/configuration/policy-resource.md +++ b/docs/content/configuration/policy-resource.md @@ -583,6 +583,8 @@ spec: authEndpoint: https://idp.example.com/openid-connect/auth tokenEndpoint: https://idp.example.com/openid-connect/token jwksURI: https://idp.example.com/openid-connect/certs + logoutEndpoint: https://idp.example.com/openid-connect/logout + logoutRedirect: / accessTokenEnable: true ``` @@ -607,7 +609,7 @@ The configuration in the example doesn't enable TLS and the synchronization betw #### Limitations -The OIDC policy defines a few internal locations that can't be customized: `/_jwks_uri`, `/_token`, `/_refresh`, `/_id_token_validation`, `/logout`, `/_logout`. In addition, as explained below `/_codexch` is the default value for redirect URI, but can be customized. Specifying one of these locations as a route in the VirtualServer or VirtualServerRoute will result in a collision and NGINX Plus will fail to reload. +The OIDC policy defines a few internal locations that can't be customized: `/_jwks_uri`, `/_token`, `/_refresh`, `/_id_token_validation`, `/logout`. In addition, as explained below, `/_codexch` is the default value for redirect URI, and `/_logout` is the default value for logout endpoint, both of which can be customized. Specifying one of these locations as a route in the VirtualServer or VirtualServerRoute will result in a collision and NGINX Plus will fail to reload. {{% table %}} |Field | Description | Type | Required | @@ -617,9 +619,11 @@ The OIDC policy defines a few internal locations that can't be customized: `/_jw |``authEndpoint`` | URL for the authorization endpoint provided by your OpenID Connect provider. | ``string`` | Yes | |``authExtraArgs`` | A list of extra URL arguments to pass to the authorization endpoint provided by your OpenID Connect provider. Arguments must be URL encoded, multiple arguments may be included in the list, for example ``[ arg1=value1, arg2=value2 ]`` | ``string[]`` | No | |``tokenEndpoint`` | URL for the token endpoint provided by your OpenID Connect provider. | ``string`` | Yes | +|``logoutEndpoint`` | URL for the logout endpoint provided by your OpenID Connect provider. | ``string`` | No | |``jwksURI`` | URL for the JSON Web Key Set (JWK) document provided by your OpenID Connect provider. | ``string`` | Yes | |``scope`` | List of OpenID Connect scopes. The scope ``openid`` always needs to be present and others can be added concatenating them with a ``+`` sign, for example ``openid+profile+email``, ``openid+email+userDefinedScope``. The default is ``openid``. | ``string`` | No | |``redirectURI`` | Allows overriding the default redirect URI. The default is ``/_codexch``. | ``string`` | No | +|``logoutRedirect`` | URL to redirect to after logout. The default is ``/_logout``. | ``string`` | No | |``zoneSyncLeeway`` | Specifies the maximum timeout in milliseconds for synchronizing ID/access tokens and shared values between Ingress Controller pods. The default is ``200``. | ``int`` | No | |``accessTokenEnable`` | Option of whether Bearer token is used to authorize NGINX to access protected backend. | ``boolean`` | No | {{% /table %}} diff --git a/examples/custom-resources/oidc/README.md b/examples/custom-resources/oidc/README.md index 5da22137f..62b066903 100644 --- a/examples/custom-resources/oidc/README.md +++ b/examples/custom-resources/oidc/README.md @@ -146,3 +146,8 @@ Note that the VirtualServer references the policy `oidc-policy` created in Step ![keycloak](./keycloak.png) 1. Once logged in, you will be redirected to the web application and get a response from it. Notice the field `User ID` in the response, this will match the ID for your user in Keycloak. ![webapp](./webapp.png) + +## Step 10 - Log Out + +1. To log out, navigate to `https://webapp.example.com/logout`. Your session will be terminated and you will be + redirected to the default post logout URI `https://webapp.example.com/_logout`. \ No newline at end of file diff --git a/examples/custom-resources/oidc/keycloak_setup.md b/examples/custom-resources/oidc/keycloak_setup.md index 9863e32c6..570778e36 100644 --- a/examples/custom-resources/oidc/keycloak_setup.md +++ b/examples/custom-resources/oidc/keycloak_setup.md @@ -7,7 +7,9 @@ This guide will help you configure KeyCloak using Keycloak's API: **Notes**: -- This guide has been tested with keycloak 19.0.2 and later. If you modify `keycloak.yaml` to use an older version, Keycloak may not start correctly or the commands in this guide may not work as expected. The Keycloak OpenID endpoints `oidc.yaml` might also be different in older versions of Keycloak. +- This guide has been tested with keycloak 19.0.2 and later. If you modify `keycloak.yaml` to use an older version, + Keycloak may not start correctly or the commands in this guide may not work as expected. The Keycloak OpenID + endpoints `oidc.yaml` might also be different in older versions of Keycloak. - if you changed the admin username and password for Keycloak in `keycloak.yaml`, modify the commands accordingly. - The instructions use [`jq`](https://stedolan.github.io/jq/). @@ -26,12 +28,13 @@ Steps: ``` Ensure the request was successful and the token is stored in the shell variable by running: + ```console echo $TOKEN ``` - ***Note***: The access token lifespan is very short. If it expires between commands, retrieve it again with the - command above. + ***Note***: The access token lifespan is very short. If it expires between commands, retrieve it again with the + command above. 1. Create the user `nginx-user`: @@ -42,10 +45,10 @@ Steps: 1. Create the client `nginx-plus` and retrieve the secret: ```console - SECRET=`curl -sS -k -X POST -d '{ "clientId": "nginx-plus", "redirectUris": ["https://webapp.example.com:443/_codexch"] }' -H "Content-Type:application/json" -H "Authorization: bearer ${TOKEN}" https://${KEYCLOAK_ADDRESS}/realms/master/clients-registrations/default | jq -r .secret` + SECRET=`curl -sS -k -X POST -d '{ "clientId": "nginx-plus", "redirectUris": ["https://webapp.example.com:443/_codexch"], "attributes": {"post.logout.redirect.uris": "https://webapp.example.com:443/*"}}' -H "Content-Type:application/json" -H "Authorization: bearer ${TOKEN}" https://${KEYCLOAK_ADDRESS}/realms/master/clients-registrations/default | jq -r .secret` ``` - If everything went well you should have the secret stored in $SECRET. To double check run: + If everything went well you should have the secret stored in $SECRET. To double check run: ```console echo $SECRET diff --git a/examples/custom-resources/oidc/nginx-config.yaml b/examples/custom-resources/oidc/nginx-config.yaml index da6b022e5..3298117ca 100644 --- a/examples/custom-resources/oidc/nginx-config.yaml +++ b/examples/custom-resources/oidc/nginx-config.yaml @@ -5,7 +5,6 @@ metadata: namespace: nginx-ingress data: stream-snippets: | - resolver valid=5s; server { listen 12345; listen [::]:12345; diff --git a/examples/custom-resources/oidc/oidc.yaml b/examples/custom-resources/oidc/oidc.yaml index d75027584..5f841fa8d 100644 --- a/examples/custom-resources/oidc/oidc.yaml +++ b/examples/custom-resources/oidc/oidc.yaml @@ -9,5 +9,8 @@ spec: authEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/auth tokenEndpoint: http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token jwksURI: http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs + logoutEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/logout scope: openid+profile+email accessTokenEnable: true + #redirectURI: # default: /_codexch + #logoutRedirect: # default: /_logout diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index 2ee188468..eb7fb6537 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -133,7 +133,9 @@ type OIDC struct { JwksURI string Scope string TokenEndpoint string + LogoutEndpoint string RedirectURI string + LogoutRedirect string ZoneSyncLeeway int AuthExtraArgs string AccessTokenEnable bool diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 7c6af65f5..fe2977ba6 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -90,19 +90,20 @@ server { include oidc/oidc.conf; set $oidc_pkce_enable 0; - set $oidc_logout_redirect "/_logout"; + set $oidc_logout_redirect "{{ $oidc.LogoutRedirect }}"; set $oidc_hmac_key "{{ $s.VSName }}"; set $zone_sync_leeway {{ $oidc.ZoneSyncLeeway }}; set $oidc_authz_endpoint "{{ $oidc.AuthEndpoint }}"; set $oidc_authz_extra_args "{{ $oidc.AuthExtraArgs }}"; set $oidc_token_endpoint "{{ $oidc.TokenEndpoint }}"; + set $oidc_end_session_endpoint "{{ $oidc.LogoutEndpoint }}"; set $oidc_jwt_keyfile "{{ $oidc.JwksURI }}"; set $oidc_scopes "{{ $oidc.Scope }}"; set $oidc_client "{{ $oidc.ClientID }}"; set $oidc_client_secret "{{ $oidc.ClientSecret }}"; set $redir_location "{{ $oidc.RedirectURI }}"; - {{- end }} +{{- end }} {{- with $ssl := $s.SSL }} {{- if $s.TLSPassthrough }} diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 32d561def..84fc7100b 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -1306,6 +1306,10 @@ func (p *policiesCfg) addOIDCConfig( if redirectURI == "" { redirectURI = "/_codexch" } + logoutRedirect := oidc.LogoutRedirect + if logoutRedirect == "" { + logoutRedirect = "/_logout" + } scope := oidc.Scope if scope == "" { scope = "openid" @@ -1320,10 +1324,12 @@ func (p *policiesCfg) addOIDCConfig( AuthExtraArgs: authExtraArgs, TokenEndpoint: oidc.TokenEndpoint, JwksURI: oidc.JWKSURI, + LogoutEndpoint: oidc.LogoutEndpoint, ClientID: oidc.ClientID, ClientSecret: string(clientSecret), Scope: scope, RedirectURI: redirectURI, + LogoutRedirect: logoutRedirect, ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200), AccessTokenEnable: oidc.AccessTokenEnable, } diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index f292d960a..36f5451d3 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -6864,6 +6864,8 @@ func TestGeneratePolicies(t *testing.T) { RedirectURI: "/redirect", ZoneSyncLeeway: createPointerFromInt(20), AccessTokenEnable: true, + LogoutEndpoint: "http://example.com/logout", + LogoutRedirect: "http://example.com/", }, }, }, @@ -8162,6 +8164,8 @@ func TestGeneratePoliciesFails(t *testing.T) { AuthEndpoint: "http://foo.com/bar", TokenEndpoint: "http://foo.com/bar", JWKSURI: "http://foo.com/bar", + LogoutEndpoint: "http://foo.com/bar", + LogoutRedirect: "http://foo.com/bar", AccessTokenEnable: true, }, }, @@ -8210,6 +8214,8 @@ func TestGeneratePoliciesFails(t *testing.T) { AuthEndpoint: "https://foo.com/auth", TokenEndpoint: "https://foo.com/token", JWKSURI: "https://foo.com/certs", + LogoutEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", AccessTokenEnable: true, }, }, @@ -8226,6 +8232,8 @@ func TestGeneratePoliciesFails(t *testing.T) { AuthEndpoint: "https://bar.com/auth", TokenEndpoint: "https://bar.com/token", JWKSURI: "https://bar.com/certs", + LogoutEndpoint: "https://bar.com/logout", + LogoutRedirect: "https://bar.com/", AccessTokenEnable: true, }, }, @@ -8254,6 +8262,8 @@ func TestGeneratePoliciesFails(t *testing.T) { RedirectURI: "/_codexch", Scope: "openid", ZoneSyncLeeway: 0, + LogoutEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", AccessTokenEnable: true, }, key: "default/oidc-policy-1", @@ -8277,6 +8287,8 @@ func TestGeneratePoliciesFails(t *testing.T) { ClientSecret: "super_secret_123", RedirectURI: "/_codexch", Scope: "openid", + LogoutEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", AccessTokenEnable: true, }, key: "default/oidc-policy-1", @@ -8306,6 +8318,8 @@ func TestGeneratePoliciesFails(t *testing.T) { AuthEndpoint: "https://foo.com/auth", TokenEndpoint: "https://foo.com/token", JWKSURI: "https://foo.com/certs", + LogoutEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", ClientID: "foo", AccessTokenEnable: true, }, @@ -8322,6 +8336,8 @@ func TestGeneratePoliciesFails(t *testing.T) { AuthEndpoint: "https://bar.com/auth", TokenEndpoint: "https://bar.com/token", JWKSURI: "https://bar.com/certs", + LogoutEndpoint: "https://bar.com/logout", + LogoutRedirect: "https://bar.com/", ClientID: "bar", AccessTokenEnable: true, }, @@ -8358,6 +8374,8 @@ func TestGeneratePoliciesFails(t *testing.T) { ClientSecret: "super_secret_123", RedirectURI: "/_codexch", Scope: "openid", + LogoutEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", ZoneSyncLeeway: 200, AccessTokenEnable: true, }, diff --git a/pkg/apis/configuration/v1/types.go b/pkg/apis/configuration/v1/types.go index 0ad315fad..2b789123b 100644 --- a/pkg/apis/configuration/v1/types.go +++ b/pkg/apis/configuration/v1/types.go @@ -655,6 +655,8 @@ type OIDC struct { ClientSecret string `json:"clientSecret"` Scope string `json:"scope"` RedirectURI string `json:"redirectURI"` + LogoutEndpoint string `json:"logoutEndpoint"` + LogoutRedirect string `json:"logoutRedirect"` ZoneSyncLeeway *int `json:"zoneSyncLeeway"` AuthExtraArgs []string `json:"authExtraArgs"` AccessTokenEnable bool `json:"accessTokenEnable"` diff --git a/pkg/apis/configuration/validation/policy.go b/pkg/apis/configuration/validation/policy.go index 5483cd462..fd27aa101 100644 --- a/pkg/apis/configuration/validation/policy.go +++ b/pkg/apis/configuration/validation/policy.go @@ -260,6 +260,10 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.ClientSecret == "" { return field.ErrorList{field.Required(fieldPath.Child("clientSecret"), "")} } + if oidc.LogoutEndpoint == "" && oidc.LogoutRedirect != "" { + msg := "logoutRedirect can only be set when logoutEndpoint is set" + return field.ErrorList{field.Forbidden(fieldPath.Child("logoutRedirect"), msg)} + } allErrs := field.ErrorList{} if oidc.Scope != "" { @@ -268,6 +272,12 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.RedirectURI != "" { allErrs = append(allErrs, validatePath(oidc.RedirectURI, fieldPath.Child("redirectURI"))...) } + if oidc.LogoutEndpoint != "" { + allErrs = append(allErrs, validateURL(oidc.LogoutEndpoint, fieldPath.Child("logoutEndpoint"))...) + } + if oidc.LogoutRedirect != "" { + allErrs = append(allErrs, validatePath(oidc.LogoutRedirect, fieldPath.Child("logoutRedirect"))...) + } if oidc.ZoneSyncLeeway != nil { allErrs = append(allErrs, validatePositiveIntOrZero(*oidc.ZoneSyncLeeway, fieldPath.Child("zoneSyncLeeway"))...) } diff --git a/pkg/apis/configuration/validation/policy_test.go b/pkg/apis/configuration/validation/policy_test.go index 6a66806b5..c34c1ffe6 100644 --- a/pkg/apis/configuration/validation/policy_test.go +++ b/pkg/apis/configuration/validation/policy_test.go @@ -291,6 +291,9 @@ func TestValidatePolicy_PassesOnValidInput(t *testing.T) { AuthExtraArgs: []string{"foo=bar"}, TokenEndpoint: "https://foo.bar/token", JWKSURI: "https://foo.bar/certs", + LogoutEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "random-string", ClientSecret: "random-secret", Scope: "openid", @@ -395,6 +398,9 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { AuthEndpoint: "https://foo.bar/auth", TokenEndpoint: "https://foo.bar/token", JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + LogoutEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", ClientID: "random-string", ClientSecret: "random-secret", Scope: "openid", @@ -413,6 +419,9 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { AuthEndpoint: "https://foo.bar/auth", TokenEndpoint: "https://foo.bar/token", JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + LogoutEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", ClientID: "random-string", ClientSecret: "random-secret", Scope: "openid", @@ -444,6 +453,9 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { AuthEndpoint: "https://foo.bar/auth", TokenEndpoint: "https://foo.bar/token", JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + LogoutEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", ClientID: "random-string", ClientSecret: "random-secret", Scope: "openid", @@ -460,13 +472,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", + AuthEndpoint: "https://foo.bar/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + LogoutEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", }, }, }, @@ -1234,6 +1249,8 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { AuthExtraArgs: []string{"foo=bar", "baz=zot"}, TokenEndpoint: "https://oauth2.googleapis.com/token", JWKSURI: "https://www.googleapis.com/oauth2/v3/certs", + LogoutEndpoint: "https://oauth2.googleapis.com/revoke", + LogoutRedirect: "/_logout", ClientID: "random-string", ClientSecret: "random-secret", Scope: "openid", @@ -1248,20 +1265,25 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "ff", ClientSecret: "ff", Scope: "openid+profile", - RedirectURI: "/_codexe", AccessTokenEnable: true, }, msg: "verify azure endpoint", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/auth/realms/master/protocol/openid-connect/auth", + AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/auth", AuthExtraArgs: []string{"kc_idp_hint=foo"}, - TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://keycloak.default.svc.cluster.local:8080/auth/realms/master/protocol/openid-connect/certs", + TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "bar", ClientSecret: "foo", Scope: "openid", @@ -1271,9 +1293,12 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "client", ClientSecret: "secret", Scope: "openid", @@ -1283,9 +1308,12 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "client", ClientSecret: "secret", Scope: "openid+offline_access", @@ -1293,6 +1321,47 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }, msg: "offline access scope", }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+", + AccessTokenEnable: true, + }, + msg: "no logout redirect", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+", + AccessTokenEnable: true, + }, + msg: "no logout endpoint or logout redirect", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+", + AccessTokenEnable: true, + }, + msg: "no logout endpoint redirect", + }, } for _, test := range tests { @@ -1303,6 +1372,233 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { } } +func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { + t.Parallel() + tests := []struct { + oidc *v1.OIDC + fieldPath string + msg string + }{ + { + oidc: &v1.OIDC{ + RedirectURI: "/foo", + }, + fieldPath: "oidc.authEndpoint", + msg: "missing required field auth", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "bogus", + AccessTokenEnable: true, + }, + fieldPath: "oidc.scope", + msg: "missing openid in scope", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+bogus\x7f", + AccessTokenEnable: true, + }, + fieldPath: "oidc.scope", + msg: "invalid unicode in scope", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.tokenEndpoint", + msg: "missing required field token", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.jwksURI", + msg: "missing required field jwk", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.clientID", + msg: "missing required field clientid", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.clientSecret", + msg: "missing required field client secret", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + // LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.logoutRedirect", + msg: "missing required field logout endpoint when logout redirect is set", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "ff", + ClientSecret: "-ff-", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.clientSecret", + msg: "invalid secret name", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://foo.\bar.com", + TokenEndpoint: "http://keycloak.default/", + JWKSURI: "http://keycloak.default/", + LogoutEndpoint: "http://keycloak.default/", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, + }, + fieldPath: "oidc.authEndpoint", + msg: "invalid URL", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "http://foo.bar", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, + }, + fieldPath: "oidc.logoutRedirect", + msg: "invalid logout redirect URL", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "$foo$bar", + ClientSecret: "secret", + Scope: "openid", + AccessTokenEnable: true, + }, + fieldPath: "oidc.clientID", + msg: "invalid chars in clientID", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "foobar", + ClientSecret: "secret", + Scope: "openid", + }, + fieldPath: "oidc.authExtraArgs", + msg: "invalid chars in authExtraArgs", + }, + { + oidc: &v1.OIDC{ + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "foobar", + ClientSecret: "secret", + Scope: "openid", + ZoneSyncLeeway: createPointerFromInt(-1), + AccessTokenEnable: true, + }, + fieldPath: "oidc.zoneSyncLeeway", + msg: "invalid zoneSyncLeeway value", + }, + } + + for _, test := range tests { + t.Run(test.msg, func(t *testing.T) { + t.Parallel() + allErrs := validateOIDC(test.oidc, field.NewPath("oidc")) + if len(allErrs) == 0 { + t.Errorf("validateOIDC() returned no errors for invalid input for the case of %v", test.msg) + } else if allErrs[0].Field != test.fieldPath { + t.Errorf("validateOIDC() returned error on wrong field for the case of %v, want %v, got %v", test.msg, test.fieldPath, allErrs[0].Field) + } + t.Log(allErrs) + }) + } +} + func TestValidateAPIKeyPolicy_PassOnValidInput(t *testing.T) { t.Parallel() tests := []struct { @@ -1433,158 +1729,6 @@ func TestValidateOIDCScope_PassesOnValidInput(t *testing.T) { } } -func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { - t.Parallel() - tests := []struct { - oidc *v1.OIDC - msg string - }{ - { - oidc: &v1.OIDC{ - RedirectURI: "/foo", - }, - msg: "missing required field auth", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", - ClientID: "client", - ClientSecret: "secret", - Scope: "bogus", - AccessTokenEnable: true, - }, - msg: "missing openid in scope", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+bogus\x7f", - AccessTokenEnable: true, - }, - msg: "invalid unicode in scope", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - msg: "missing required field token", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - msg: "missing required field jwk", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - msg: "missing required field clientid", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - ClientID: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - msg: "missing required field client secret", - }, - - { - oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - ClientID: "ff", - ClientSecret: "-ff-", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - msg: "invalid secret name", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://foo.\bar.com", - TokenEndpoint: "http://keycloak.default", - JWKSURI: "http://keycloak.default", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, - }, - msg: "invalid URL", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", - ClientID: "$foo$bar", - ClientSecret: "secret", - Scope: "openid", - AccessTokenEnable: true, - }, - msg: "invalid chars in clientID", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", - ClientID: "foobar", - ClientSecret: "secret", - Scope: "openid", - }, - msg: "invalid chars in authExtraArgs", - }, - { - oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/auth/realms/master/protocol/openid-connect/certs", - ClientID: "foobar", - ClientSecret: "secret", - Scope: "openid", - ZoneSyncLeeway: createPointerFromInt(-1), - AccessTokenEnable: true, - }, - msg: "invalid zoneSyncLeeway value", - }, - } - - for _, test := range tests { - allErrs := validateOIDC(test.oidc, field.NewPath("oidc")) - if len(allErrs) == 0 { - t.Errorf("validateOIDC() returned no errors for invalid input for the case of %v", test.msg) - } - } -} - func TestValidatePortNumber_ErrorsOnInvalidPort(t *testing.T) { t.Parallel() From d306d051b754de7abf82231f22239270a3b4dbdc Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:49:37 +0100 Subject: [PATCH 2/8] update example Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- examples/custom-resources/oidc/README.md | 35 +++++++----------- examples/custom-resources/oidc/logout.png | Bin 0 -> 397424 bytes .../custom-resources/oidc/nginx-config.yaml | 2 +- examples/custom-resources/oidc/oidc.yaml | 2 - 4 files changed, 14 insertions(+), 25 deletions(-) create mode 100644 examples/custom-resources/oidc/logout.png diff --git a/examples/custom-resources/oidc/README.md b/examples/custom-resources/oidc/README.md index 62b066903..84de386e5 100644 --- a/examples/custom-resources/oidc/README.md +++ b/examples/custom-resources/oidc/README.md @@ -84,15 +84,7 @@ To set up Keycloak: kubectl apply -f client-secret.yaml ``` -## Step 6 - Deploy the OIDC Policy - -Create a policy with the name `oidc-policy` that references the secret from the previous step: - -```console -kubectl apply -f oidc.yaml -``` - -## Step 7 - Configure NGINX Plus Zone Synchronization and Resolver +## Step 6 - Configure NGINX Plus Zone Synchronization and Resolver In this step we configure: @@ -110,23 +102,19 @@ Steps: kubectl apply -f nginx-ingress-headless.yaml ``` -1. Get the cluster IP of the KubeDNS service: +1. Apply the ConfigMap `nginx-config.yaml`, which contains a stream snippet that enables zone synchronization and the resolver using the kube-dns service. ```console - kubectl -n kube-system get svc kube-dns + kubectl apply -f nginx-config.yaml ``` - ```text - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - kube-dns ClusterIP 10.4.0.10 53/UDP,53/TCP 9d - ``` +## Step 7 - Deploy the OIDC Policy -1. Edit the ConfigMap `nginx-config.yaml`, replacing the `` with the IP obtained in the previous step. -1. Apply the ConfigMap: +Create a policy with the name `oidc-policy` that references the secret from the previous step: - ```console - kubectl apply -f nginx-config.yaml - ``` +```console +kubectl apply -f oidc.yaml +``` ## Step 8 - Configure Load Balancing @@ -149,5 +137,8 @@ in the response, this will match the ID for your user in Keycloak. ![webapp](./w ## Step 10 - Log Out -1. To log out, navigate to `https://webapp.example.com/logout`. Your session will be terminated and you will be - redirected to the default post logout URI `https://webapp.example.com/_logout`. \ No newline at end of file +1. To log out, navigate to `https://webapp.example.com/logout`. Your session will be terminated, and you will be + redirected to the default post logout URI `https://webapp.example.com/_logout`. +![logout](./logout.png) +1. To confirm that you have been logged out, navigate to `https://webapp.example.com`. You will be redirected to + Keycloak to log in again. \ No newline at end of file diff --git a/examples/custom-resources/oidc/logout.png b/examples/custom-resources/oidc/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..6425333bada45b6e694835887340c6afac019ad2 GIT binary patch literal 397424 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

A5Tut@@sVW7W7KVr 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

;__UJ+6ImP8k>7uQ9T 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

v>7}7zBXg?bel18HkfLlfrIbH2GAj?Aeemx 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¢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 -mhMHMw^_o6=zG{5{7{*ALG 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 A=l}o! literal 0 HcmV?d00001 diff --git a/examples/custom-resources/oidc/nginx-config.yaml b/examples/custom-resources/oidc/nginx-config.yaml index 3298117ca..6e9aa9b17 100644 --- a/examples/custom-resources/oidc/nginx-config.yaml +++ b/examples/custom-resources/oidc/nginx-config.yaml @@ -11,5 +11,5 @@ data: zone_sync; zone_sync_server nginx-ingress-headless.nginx-ingress.svc.cluster.local:12345 resolve; } - resolver-addresses: + resolver-addresses: kube-dns.kube-system.svc.cluster.local resolver-valid: 5s diff --git a/examples/custom-resources/oidc/oidc.yaml b/examples/custom-resources/oidc/oidc.yaml index 5f841fa8d..5869652bd 100644 --- a/examples/custom-resources/oidc/oidc.yaml +++ b/examples/custom-resources/oidc/oidc.yaml @@ -12,5 +12,3 @@ spec: logoutEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/logout scope: openid+profile+email accessTokenEnable: true - #redirectURI: # default: /_codexch - #logoutRedirect: # default: /_logout From 47609aac69649a188fdfb4b0186b09cc57cc5dc1 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 2 Aug 2024 12:51:15 +0100 Subject: [PATCH 3/8] fix indentation Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/version2/nginx-plus.virtualserver.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index fe2977ba6..491156f5b 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -103,7 +103,7 @@ server { set $oidc_client "{{ $oidc.ClientID }}"; set $oidc_client_secret "{{ $oidc.ClientSecret }}"; set $redir_location "{{ $oidc.RedirectURI }}"; -{{- end }} + {{- end }} {{- with $ssl := $s.SSL }} {{- if $s.TLSPassthrough }} From 321ccd7781a61a4d16bf2f98122d0d927ff19165 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:56:06 +0000 Subject: [PATCH 4/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- examples/custom-resources/oidc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/custom-resources/oidc/README.md b/examples/custom-resources/oidc/README.md index 84de386e5..6113c157a 100644 --- a/examples/custom-resources/oidc/README.md +++ b/examples/custom-resources/oidc/README.md @@ -141,4 +141,4 @@ in the response, this will match the ID for your user in Keycloak. ![webapp](./w redirected to the default post logout URI `https://webapp.example.com/_logout`. ![logout](./logout.png) 1. To confirm that you have been logged out, navigate to `https://webapp.example.com`. You will be redirected to - Keycloak to log in again. \ No newline at end of file + Keycloak to log in again. From 466b7fc9863adf60402ecf48a354bfcb725e737d Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:26:16 +0100 Subject: [PATCH 5/8] rename field Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- config/crd/bases/k8s.nginx.org_policies.yaml | 4 +- deploy/crds.yaml | 4 +- docs/content/configuration/policy-resource.md | 6 +- examples/custom-resources/oidc/oidc.yaml | 2 +- internal/configs/version2/http.go | 24 +- .../version2/nginx-plus.virtualserver.tmpl | 2 +- internal/configs/virtualserver.go | 24 +- internal/configs/virtualserver_test.go | 164 +++---- pkg/apis/configuration/v1/types.go | 24 +- pkg/apis/configuration/validation/policy.go | 8 +- .../configuration/validation/policy_test.go | 462 +++++++++--------- 11 files changed, 362 insertions(+), 362 deletions(-) diff --git a/config/crd/bases/k8s.nginx.org_policies.yaml b/config/crd/bases/k8s.nginx.org_policies.yaml index b2a8e1c3f..560fd0aa4 100644 --- a/config/crd/bases/k8s.nginx.org_policies.yaml +++ b/config/crd/bases/k8s.nginx.org_policies.yaml @@ -159,9 +159,9 @@ spec: type: string clientSecret: type: string - jwksURI: + endSessionEndpoint: type: string - logoutEndpoint: + jwksURI: type: string logoutRedirect: type: string diff --git a/deploy/crds.yaml b/deploy/crds.yaml index 0eb945ac1..ebf74d15f 100644 --- a/deploy/crds.yaml +++ b/deploy/crds.yaml @@ -361,9 +361,9 @@ spec: type: string clientSecret: type: string - jwksURI: + endSessionEndpoint: type: string - logoutEndpoint: + jwksURI: type: string logoutRedirect: type: string diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md index cd9cc706a..d3c4a8f03 100644 --- a/docs/content/configuration/policy-resource.md +++ b/docs/content/configuration/policy-resource.md @@ -583,7 +583,7 @@ spec: authEndpoint: https://idp.example.com/openid-connect/auth tokenEndpoint: https://idp.example.com/openid-connect/token jwksURI: https://idp.example.com/openid-connect/certs - logoutEndpoint: https://idp.example.com/openid-connect/logout + endSessionEndpoint: https://idp.example.com/openid-connect/logout logoutRedirect: / accessTokenEnable: true ``` @@ -619,11 +619,11 @@ The OIDC policy defines a few internal locations that can't be customized: `/_jw |``authEndpoint`` | URL for the authorization endpoint provided by your OpenID Connect provider. | ``string`` | Yes | |``authExtraArgs`` | A list of extra URL arguments to pass to the authorization endpoint provided by your OpenID Connect provider. Arguments must be URL encoded, multiple arguments may be included in the list, for example ``[ arg1=value1, arg2=value2 ]`` | ``string[]`` | No | |``tokenEndpoint`` | URL for the token endpoint provided by your OpenID Connect provider. | ``string`` | Yes | -|``logoutEndpoint`` | URL for the logout endpoint provided by your OpenID Connect provider. | ``string`` | No | +|``endSessionEndpoint`` | URL provided by your OpenID Connect provider to request the end user be logged out. | ``string`` | No | |``jwksURI`` | URL for the JSON Web Key Set (JWK) document provided by your OpenID Connect provider. | ``string`` | Yes | |``scope`` | List of OpenID Connect scopes. The scope ``openid`` always needs to be present and others can be added concatenating them with a ``+`` sign, for example ``openid+profile+email``, ``openid+email+userDefinedScope``. The default is ``openid``. | ``string`` | No | |``redirectURI`` | Allows overriding the default redirect URI. The default is ``/_codexch``. | ``string`` | No | -|``logoutRedirect`` | URL to redirect to after logout. The default is ``/_logout``. | ``string`` | No | +|``logoutRedirect`` | URL to redirect to after the logout has been performed. The default is ``/_logout``. | ``string`` | No | |``zoneSyncLeeway`` | Specifies the maximum timeout in milliseconds for synchronizing ID/access tokens and shared values between Ingress Controller pods. The default is ``200``. | ``int`` | No | |``accessTokenEnable`` | Option of whether Bearer token is used to authorize NGINX to access protected backend. | ``boolean`` | No | {{% /table %}} diff --git a/examples/custom-resources/oidc/oidc.yaml b/examples/custom-resources/oidc/oidc.yaml index 5869652bd..990924f3d 100644 --- a/examples/custom-resources/oidc/oidc.yaml +++ b/examples/custom-resources/oidc/oidc.yaml @@ -9,6 +9,6 @@ spec: authEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/auth tokenEndpoint: http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token jwksURI: http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs - logoutEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/logout + endSessionEndpoint: https://keycloak.example.com/realms/master/protocol/openid-connect/logout scope: openid+profile+email accessTokenEnable: true diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index eb7fb6537..3662ec022 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -127,18 +127,18 @@ type EgressMTLS struct { // OIDC holds OIDC configuration data. type OIDC struct { - AuthEndpoint string - ClientID string - ClientSecret string - JwksURI string - Scope string - TokenEndpoint string - LogoutEndpoint string - RedirectURI string - LogoutRedirect string - ZoneSyncLeeway int - AuthExtraArgs string - AccessTokenEnable bool + AuthEndpoint string + ClientID string + ClientSecret string + JwksURI string + Scope string + TokenEndpoint string + EndSessionEndpoint string + RedirectURI string + LogoutRedirect string + ZoneSyncLeeway int + AuthExtraArgs string + AccessTokenEnable bool } // APIKey holds API key configuration. diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index 491156f5b..a7534774a 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -97,7 +97,7 @@ server { set $oidc_authz_endpoint "{{ $oidc.AuthEndpoint }}"; set $oidc_authz_extra_args "{{ $oidc.AuthExtraArgs }}"; set $oidc_token_endpoint "{{ $oidc.TokenEndpoint }}"; - set $oidc_end_session_endpoint "{{ $oidc.LogoutEndpoint }}"; + set $oidc_end_session_endpoint "{{ $oidc.EndSessionEndpoint }}"; set $oidc_jwt_keyfile "{{ $oidc.JwksURI }}"; set $oidc_scopes "{{ $oidc.Scope }}"; set $oidc_client "{{ $oidc.ClientID }}"; diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 84fc7100b..1a45a0864 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -1320,18 +1320,18 @@ func (p *policiesCfg) addOIDCConfig( } oidcPolCfg.oidc = &version2.OIDC{ - AuthEndpoint: oidc.AuthEndpoint, - AuthExtraArgs: authExtraArgs, - TokenEndpoint: oidc.TokenEndpoint, - JwksURI: oidc.JWKSURI, - LogoutEndpoint: oidc.LogoutEndpoint, - ClientID: oidc.ClientID, - ClientSecret: string(clientSecret), - Scope: scope, - RedirectURI: redirectURI, - LogoutRedirect: logoutRedirect, - ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200), - AccessTokenEnable: oidc.AccessTokenEnable, + AuthEndpoint: oidc.AuthEndpoint, + AuthExtraArgs: authExtraArgs, + TokenEndpoint: oidc.TokenEndpoint, + JwksURI: oidc.JWKSURI, + EndSessionEndpoint: oidc.EndSessionEndpoint, + ClientID: oidc.ClientID, + ClientSecret: string(clientSecret), + Scope: scope, + RedirectURI: redirectURI, + LogoutRedirect: logoutRedirect, + ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200), + AccessTokenEnable: oidc.AccessTokenEnable, } oidcPolCfg.key = polKey } diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index 36f5451d3..f8e913e28 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -6855,17 +6855,17 @@ func TestGeneratePolicies(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - AuthEndpoint: "http://example.com/auth", - TokenEndpoint: "http://example.com/token", - JWKSURI: "http://example.com/jwks", - ClientID: "client-id", - ClientSecret: "oidc-secret", - Scope: "scope", - RedirectURI: "/redirect", - ZoneSyncLeeway: createPointerFromInt(20), - AccessTokenEnable: true, - LogoutEndpoint: "http://example.com/logout", - LogoutRedirect: "http://example.com/", + AuthEndpoint: "http://example.com/auth", + TokenEndpoint: "http://example.com/token", + JWKSURI: "http://example.com/jwks", + ClientID: "client-id", + ClientSecret: "oidc-secret", + Scope: "scope", + RedirectURI: "/redirect", + ZoneSyncLeeway: createPointerFromInt(20), + AccessTokenEnable: true, + EndSessionEndpoint: "http://example.com/logout", + LogoutRedirect: "http://example.com/", }, }, }, @@ -8160,13 +8160,13 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "http://foo.com/bar", - TokenEndpoint: "http://foo.com/bar", - JWKSURI: "http://foo.com/bar", - LogoutEndpoint: "http://foo.com/bar", - LogoutRedirect: "http://foo.com/bar", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "http://foo.com/bar", + TokenEndpoint: "http://foo.com/bar", + JWKSURI: "http://foo.com/bar", + EndSessionEndpoint: "http://foo.com/bar", + LogoutRedirect: "http://foo.com/bar", + AccessTokenEnable: true, }, }, }, @@ -8209,14 +8209,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientID: "foo", - ClientSecret: "oidc-secret", - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JWKSURI: "https://foo.com/certs", - LogoutEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + ClientID: "foo", + ClientSecret: "oidc-secret", + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JWKSURI: "https://foo.com/certs", + EndSessionEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", + AccessTokenEnable: true, }, }, }, @@ -8227,14 +8227,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientID: "foo", - ClientSecret: "oidc-secret", - AuthEndpoint: "https://bar.com/auth", - TokenEndpoint: "https://bar.com/token", - JWKSURI: "https://bar.com/certs", - LogoutEndpoint: "https://bar.com/logout", - LogoutRedirect: "https://bar.com/", - AccessTokenEnable: true, + ClientID: "foo", + ClientSecret: "oidc-secret", + AuthEndpoint: "https://bar.com/auth", + TokenEndpoint: "https://bar.com/token", + JWKSURI: "https://bar.com/certs", + EndSessionEndpoint: "https://bar.com/logout", + LogoutRedirect: "https://bar.com/", + AccessTokenEnable: true, }, }, }, @@ -8254,17 +8254,17 @@ func TestGeneratePoliciesFails(t *testing.T) { context: "route", oidcPolCfg: &oidcPolicyCfg{ oidc: &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - ZoneSyncLeeway: 0, - LogoutEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + ZoneSyncLeeway: 0, + EndSessionEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", + AccessTokenEnable: true, }, key: "default/oidc-policy-1", }, @@ -8280,16 +8280,16 @@ func TestGeneratePoliciesFails(t *testing.T) { }, expectedOidc: &oidcPolicyCfg{ oidc: &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - LogoutEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + EndSessionEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", + AccessTokenEnable: true, }, key: "default/oidc-policy-1", }, @@ -8314,14 +8314,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JWKSURI: "https://foo.com/certs", - LogoutEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - ClientID: "foo", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JWKSURI: "https://foo.com/certs", + EndSessionEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", + ClientID: "foo", + AccessTokenEnable: true, }, }, }, @@ -8332,14 +8332,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "https://bar.com/auth", - TokenEndpoint: "https://bar.com/token", - JWKSURI: "https://bar.com/certs", - LogoutEndpoint: "https://bar.com/logout", - LogoutRedirect: "https://bar.com/", - ClientID: "bar", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "https://bar.com/auth", + TokenEndpoint: "https://bar.com/token", + JWKSURI: "https://bar.com/certs", + EndSessionEndpoint: "https://bar.com/logout", + LogoutRedirect: "https://bar.com/", + ClientID: "bar", + AccessTokenEnable: true, }, }, }, @@ -8367,17 +8367,17 @@ func TestGeneratePoliciesFails(t *testing.T) { }, expectedOidc: &oidcPolicyCfg{ &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - LogoutEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - ZoneSyncLeeway: 200, - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + EndSessionEndpoint: "https://foo.com/logout", + LogoutRedirect: "https://foo.com/", + ZoneSyncLeeway: 200, + AccessTokenEnable: true, }, "default/oidc-policy", }, diff --git a/pkg/apis/configuration/v1/types.go b/pkg/apis/configuration/v1/types.go index 2b789123b..46c231053 100644 --- a/pkg/apis/configuration/v1/types.go +++ b/pkg/apis/configuration/v1/types.go @@ -648,18 +648,18 @@ type EgressMTLS struct { // OIDC defines an Open ID Connect policy. type OIDC struct { - AuthEndpoint string `json:"authEndpoint"` - TokenEndpoint string `json:"tokenEndpoint"` - JWKSURI string `json:"jwksURI"` - ClientID string `json:"clientID"` - ClientSecret string `json:"clientSecret"` - Scope string `json:"scope"` - RedirectURI string `json:"redirectURI"` - LogoutEndpoint string `json:"logoutEndpoint"` - LogoutRedirect string `json:"logoutRedirect"` - ZoneSyncLeeway *int `json:"zoneSyncLeeway"` - AuthExtraArgs []string `json:"authExtraArgs"` - AccessTokenEnable bool `json:"accessTokenEnable"` + AuthEndpoint string `json:"authEndpoint"` + TokenEndpoint string `json:"tokenEndpoint"` + JWKSURI string `json:"jwksURI"` + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + Scope string `json:"scope"` + RedirectURI string `json:"redirectURI"` + EndSessionEndpoint string `json:"endSessionEndpoint"` + LogoutRedirect string `json:"logoutRedirect"` + ZoneSyncLeeway *int `json:"zoneSyncLeeway"` + AuthExtraArgs []string `json:"authExtraArgs"` + AccessTokenEnable bool `json:"accessTokenEnable"` } // WAF defines an WAF policy. diff --git a/pkg/apis/configuration/validation/policy.go b/pkg/apis/configuration/validation/policy.go index fd27aa101..0f01ee840 100644 --- a/pkg/apis/configuration/validation/policy.go +++ b/pkg/apis/configuration/validation/policy.go @@ -260,8 +260,8 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.ClientSecret == "" { return field.ErrorList{field.Required(fieldPath.Child("clientSecret"), "")} } - if oidc.LogoutEndpoint == "" && oidc.LogoutRedirect != "" { - msg := "logoutRedirect can only be set when logoutEndpoint is set" + if oidc.EndSessionEndpoint == "" && oidc.LogoutRedirect != "" { + msg := "logoutRedirect can only be set when endSessionEndpoint is set" return field.ErrorList{field.Forbidden(fieldPath.Child("logoutRedirect"), msg)} } @@ -272,8 +272,8 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.RedirectURI != "" { allErrs = append(allErrs, validatePath(oidc.RedirectURI, fieldPath.Child("redirectURI"))...) } - if oidc.LogoutEndpoint != "" { - allErrs = append(allErrs, validateURL(oidc.LogoutEndpoint, fieldPath.Child("logoutEndpoint"))...) + if oidc.EndSessionEndpoint != "" { + allErrs = append(allErrs, validateURL(oidc.EndSessionEndpoint, fieldPath.Child("endSessionEndpoint"))...) } if oidc.LogoutRedirect != "" { allErrs = append(allErrs, validatePath(oidc.LogoutRedirect, fieldPath.Child("logoutRedirect"))...) diff --git a/pkg/apis/configuration/validation/policy_test.go b/pkg/apis/configuration/validation/policy_test.go index c34c1ffe6..b844c811b 100644 --- a/pkg/apis/configuration/validation/policy_test.go +++ b/pkg/apis/configuration/validation/policy_test.go @@ -287,18 +287,18 @@ func TestValidatePolicy_PassesOnValidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - AuthExtraArgs: []string{"foo=bar"}, - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - LogoutEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - ZoneSyncLeeway: createPointerFromInt(10), - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + AuthExtraArgs: []string{"foo=bar"}, + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + EndSessionEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + ZoneSyncLeeway: createPointerFromInt(10), + AccessTokenEnable: true, }, }, }, @@ -395,16 +395,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - LogoutEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + AccessTokenEnable: true, }, }, }, @@ -416,16 +416,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - LogoutEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + AccessTokenEnable: true, }, }, }, @@ -450,17 +450,17 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - LogoutEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - ZoneSyncLeeway: createPointerFromInt(-1), - AccessTokenEnable: false, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + ZoneSyncLeeway: createPointerFromInt(-1), + AccessTokenEnable: false, }, }, }, @@ -472,16 +472,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - LogoutEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", + AuthEndpoint: "https://foo.bar/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", }, }, }, @@ -1245,93 +1245,93 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }{ { oidc: &v1.OIDC{ - AuthEndpoint: "https://accounts.google.com/o/oauth2/v2/auth", - AuthExtraArgs: []string{"foo=bar", "baz=zot"}, - TokenEndpoint: "https://oauth2.googleapis.com/token", - JWKSURI: "https://www.googleapis.com/oauth2/v3/certs", - LogoutEndpoint: "https://oauth2.googleapis.com/revoke", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - RedirectURI: "/foo", - ZoneSyncLeeway: createPointerFromInt(20), - AccessTokenEnable: true, + AuthEndpoint: "https://accounts.google.com/o/oauth2/v2/auth", + AuthExtraArgs: []string{"foo=bar", "baz=zot"}, + TokenEndpoint: "https://oauth2.googleapis.com/token", + JWKSURI: "https://www.googleapis.com/oauth2/v3/certs", + EndSessionEndpoint: "https://oauth2.googleapis.com/revoke", + LogoutRedirect: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + RedirectURI: "/foo", + ZoneSyncLeeway: createPointerFromInt(20), + AccessTokenEnable: true, }, msg: "verify full oidc", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, msg: "verify azure endpoint", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/auth", - AuthExtraArgs: []string{"kc_idp_hint=foo"}, - TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/auth", + AuthExtraArgs: []string{"kc_idp_hint=foo"}, + TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, }, msg: "domain with port number", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid", + AccessTokenEnable: true, }, msg: "ip address", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+offline_access", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+offline_access", + AccessTokenEnable: true, }, msg: "offline access scope", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+", + AccessTokenEnable: true, }, msg: "no logout redirect", }, @@ -1350,15 +1350,15 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+", + AccessTokenEnable: true, }, msg: "no logout endpoint redirect", }, @@ -1388,86 +1388,86 @@ func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - ClientID: "client", - ClientSecret: "secret", - Scope: "bogus", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "bogus", + AccessTokenEnable: true, }, fieldPath: "oidc.scope", msg: "missing openid in scope", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+bogus\x7f", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+bogus\x7f", + AccessTokenEnable: true, }, fieldPath: "oidc.scope", msg: "invalid unicode in scope", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.tokenEndpoint", msg: "missing required field token", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.jwksURI", msg: "missing required field jwk", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientID", msg: "missing required field clientid", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + ClientID: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientSecret", msg: "missing required field client secret", @@ -1477,7 +1477,7 @@ func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - // LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + // EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", LogoutRedirect: "/_logout", ClientID: "ff", ClientSecret: "ff", @@ -1489,92 +1489,92 @@ func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - LogoutEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "ff", - ClientSecret: "-ff-", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "ff", + ClientSecret: "-ff-", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientSecret", msg: "invalid secret name", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://foo.\bar.com", - TokenEndpoint: "http://keycloak.default/", - JWKSURI: "http://keycloak.default/", - LogoutEndpoint: "http://keycloak.default/", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://foo.\bar.com", + TokenEndpoint: "http://keycloak.default/", + JWKSURI: "http://keycloak.default/", + EndSessionEndpoint: "http://keycloak.default/", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, }, fieldPath: "oidc.authEndpoint", msg: "invalid URL", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "http://foo.bar", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "http://foo.bar", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, }, fieldPath: "oidc.logoutRedirect", msg: "invalid logout redirect URL", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "$foo$bar", - ClientSecret: "secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "$foo$bar", + ClientSecret: "secret", + Scope: "openid", + AccessTokenEnable: true, }, fieldPath: "oidc.clientID", msg: "invalid chars in clientID", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "foobar", - ClientSecret: "secret", - Scope: "openid", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", + ClientID: "foobar", + ClientSecret: "secret", + Scope: "openid", }, fieldPath: "oidc.authExtraArgs", msg: "invalid chars in authExtraArgs", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - LogoutEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", ClientID: "foobar", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + LogoutRedirect: "/_logout", + RedirectURI: "/_codexch", ClientID: "foobar", ClientSecret: "secret", Scope: "openid", ZoneSyncLeeway: createPointerFromInt(-1), From 493c49b8149e91218b4c0a4a0e2aba564040a9c9 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:49:26 +0100 Subject: [PATCH 6/8] rename logout redirect Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- config/crd/bases/k8s.nginx.org_policies.yaml | 2 +- deploy/crds.yaml | 2 +- docs/content/configuration/policy-resource.md | 4 +- internal/configs/version2/http.go | 24 +- .../version2/nginx-plus.virtualserver.tmpl | 2 +- internal/configs/virtualserver.go | 30 +- internal/configs/virtualserver_test.go | 164 +++---- pkg/apis/configuration/v1/types.go | 24 +- pkg/apis/configuration/validation/policy.go | 10 +- .../configuration/validation/policy_test.go | 455 +++++++++--------- 10 files changed, 358 insertions(+), 359 deletions(-) diff --git a/config/crd/bases/k8s.nginx.org_policies.yaml b/config/crd/bases/k8s.nginx.org_policies.yaml index 560fd0aa4..e4ee8908d 100644 --- a/config/crd/bases/k8s.nginx.org_policies.yaml +++ b/config/crd/bases/k8s.nginx.org_policies.yaml @@ -163,7 +163,7 @@ spec: type: string jwksURI: type: string - logoutRedirect: + postLogoutRedirectURI: type: string redirectURI: type: string diff --git a/deploy/crds.yaml b/deploy/crds.yaml index ebf74d15f..a2ba4ab51 100644 --- a/deploy/crds.yaml +++ b/deploy/crds.yaml @@ -365,7 +365,7 @@ spec: type: string jwksURI: type: string - logoutRedirect: + postLogoutRedirectURI: type: string redirectURI: type: string diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md index d3c4a8f03..a07dc443a 100644 --- a/docs/content/configuration/policy-resource.md +++ b/docs/content/configuration/policy-resource.md @@ -584,7 +584,7 @@ spec: tokenEndpoint: https://idp.example.com/openid-connect/token jwksURI: https://idp.example.com/openid-connect/certs endSessionEndpoint: https://idp.example.com/openid-connect/logout - logoutRedirect: / + postLogoutRedirectURI: / accessTokenEnable: true ``` @@ -623,7 +623,7 @@ The OIDC policy defines a few internal locations that can't be customized: `/_jw |``jwksURI`` | URL for the JSON Web Key Set (JWK) document provided by your OpenID Connect provider. | ``string`` | Yes | |``scope`` | List of OpenID Connect scopes. The scope ``openid`` always needs to be present and others can be added concatenating them with a ``+`` sign, for example ``openid+profile+email``, ``openid+email+userDefinedScope``. The default is ``openid``. | ``string`` | No | |``redirectURI`` | Allows overriding the default redirect URI. The default is ``/_codexch``. | ``string`` | No | -|``logoutRedirect`` | URL to redirect to after the logout has been performed. The default is ``/_logout``. | ``string`` | No | +|``postLogoutRedirectURI`` | URI to redirect to after the logout has been performed. Requires ``endSessionEndpoint``. The default is ``/_logout``. | ``string`` | No | |``zoneSyncLeeway`` | Specifies the maximum timeout in milliseconds for synchronizing ID/access tokens and shared values between Ingress Controller pods. The default is ``200``. | ``int`` | No | |``accessTokenEnable`` | Option of whether Bearer token is used to authorize NGINX to access protected backend. | ``boolean`` | No | {{% /table %}} diff --git a/internal/configs/version2/http.go b/internal/configs/version2/http.go index 3662ec022..00ba22145 100644 --- a/internal/configs/version2/http.go +++ b/internal/configs/version2/http.go @@ -127,18 +127,18 @@ type EgressMTLS struct { // OIDC holds OIDC configuration data. type OIDC struct { - AuthEndpoint string - ClientID string - ClientSecret string - JwksURI string - Scope string - TokenEndpoint string - EndSessionEndpoint string - RedirectURI string - LogoutRedirect string - ZoneSyncLeeway int - AuthExtraArgs string - AccessTokenEnable bool + AuthEndpoint string + ClientID string + ClientSecret string + JwksURI string + Scope string + TokenEndpoint string + EndSessionEndpoint string + RedirectURI string + PostLogoutRedirectURI string + ZoneSyncLeeway int + AuthExtraArgs string + AccessTokenEnable bool } // APIKey holds API key configuration. diff --git a/internal/configs/version2/nginx-plus.virtualserver.tmpl b/internal/configs/version2/nginx-plus.virtualserver.tmpl index a7534774a..7b2977892 100644 --- a/internal/configs/version2/nginx-plus.virtualserver.tmpl +++ b/internal/configs/version2/nginx-plus.virtualserver.tmpl @@ -90,7 +90,7 @@ server { include oidc/oidc.conf; set $oidc_pkce_enable 0; - set $oidc_logout_redirect "{{ $oidc.LogoutRedirect }}"; + set $oidc_logout_redirect "{{ $oidc.PostLogoutRedirectURI }}"; set $oidc_hmac_key "{{ $s.VSName }}"; set $zone_sync_leeway {{ $oidc.ZoneSyncLeeway }}; diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go index 1a45a0864..23facedcb 100644 --- a/internal/configs/virtualserver.go +++ b/internal/configs/virtualserver.go @@ -1306,9 +1306,9 @@ func (p *policiesCfg) addOIDCConfig( if redirectURI == "" { redirectURI = "/_codexch" } - logoutRedirect := oidc.LogoutRedirect - if logoutRedirect == "" { - logoutRedirect = "/_logout" + postLogoutRedirectURI := oidc.PostLogoutRedirectURI + if postLogoutRedirectURI == "" { + postLogoutRedirectURI = "/_logout" } scope := oidc.Scope if scope == "" { @@ -1320,18 +1320,18 @@ func (p *policiesCfg) addOIDCConfig( } oidcPolCfg.oidc = &version2.OIDC{ - AuthEndpoint: oidc.AuthEndpoint, - AuthExtraArgs: authExtraArgs, - TokenEndpoint: oidc.TokenEndpoint, - JwksURI: oidc.JWKSURI, - EndSessionEndpoint: oidc.EndSessionEndpoint, - ClientID: oidc.ClientID, - ClientSecret: string(clientSecret), - Scope: scope, - RedirectURI: redirectURI, - LogoutRedirect: logoutRedirect, - ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200), - AccessTokenEnable: oidc.AccessTokenEnable, + AuthEndpoint: oidc.AuthEndpoint, + AuthExtraArgs: authExtraArgs, + TokenEndpoint: oidc.TokenEndpoint, + JwksURI: oidc.JWKSURI, + EndSessionEndpoint: oidc.EndSessionEndpoint, + ClientID: oidc.ClientID, + ClientSecret: string(clientSecret), + Scope: scope, + RedirectURI: redirectURI, + PostLogoutRedirectURI: postLogoutRedirectURI, + ZoneSyncLeeway: generateIntFromPointer(oidc.ZoneSyncLeeway, 200), + AccessTokenEnable: oidc.AccessTokenEnable, } oidcPolCfg.key = polKey } diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index f8e913e28..5f3555eb1 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -6855,17 +6855,17 @@ func TestGeneratePolicies(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - AuthEndpoint: "http://example.com/auth", - TokenEndpoint: "http://example.com/token", - JWKSURI: "http://example.com/jwks", - ClientID: "client-id", - ClientSecret: "oidc-secret", - Scope: "scope", - RedirectURI: "/redirect", - ZoneSyncLeeway: createPointerFromInt(20), - AccessTokenEnable: true, - EndSessionEndpoint: "http://example.com/logout", - LogoutRedirect: "http://example.com/", + AuthEndpoint: "http://example.com/auth", + TokenEndpoint: "http://example.com/token", + JWKSURI: "http://example.com/jwks", + ClientID: "client-id", + ClientSecret: "oidc-secret", + Scope: "scope", + RedirectURI: "/redirect", + ZoneSyncLeeway: createPointerFromInt(20), + AccessTokenEnable: true, + EndSessionEndpoint: "http://example.com/logout", + PostLogoutRedirectURI: "http://example.com/", }, }, }, @@ -8160,13 +8160,13 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "http://foo.com/bar", - TokenEndpoint: "http://foo.com/bar", - JWKSURI: "http://foo.com/bar", - EndSessionEndpoint: "http://foo.com/bar", - LogoutRedirect: "http://foo.com/bar", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "http://foo.com/bar", + TokenEndpoint: "http://foo.com/bar", + JWKSURI: "http://foo.com/bar", + EndSessionEndpoint: "http://foo.com/bar", + PostLogoutRedirectURI: "http://foo.com/bar", + AccessTokenEnable: true, }, }, }, @@ -8209,14 +8209,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientID: "foo", - ClientSecret: "oidc-secret", - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JWKSURI: "https://foo.com/certs", - EndSessionEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + ClientID: "foo", + ClientSecret: "oidc-secret", + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JWKSURI: "https://foo.com/certs", + EndSessionEndpoint: "https://foo.com/logout", + PostLogoutRedirectURI: "https://foo.com/", + AccessTokenEnable: true, }, }, }, @@ -8227,14 +8227,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientID: "foo", - ClientSecret: "oidc-secret", - AuthEndpoint: "https://bar.com/auth", - TokenEndpoint: "https://bar.com/token", - JWKSURI: "https://bar.com/certs", - EndSessionEndpoint: "https://bar.com/logout", - LogoutRedirect: "https://bar.com/", - AccessTokenEnable: true, + ClientID: "foo", + ClientSecret: "oidc-secret", + AuthEndpoint: "https://bar.com/auth", + TokenEndpoint: "https://bar.com/token", + JWKSURI: "https://bar.com/certs", + EndSessionEndpoint: "https://bar.com/logout", + PostLogoutRedirectURI: "https://bar.com/", + AccessTokenEnable: true, }, }, }, @@ -8254,17 +8254,17 @@ func TestGeneratePoliciesFails(t *testing.T) { context: "route", oidcPolCfg: &oidcPolicyCfg{ oidc: &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - ZoneSyncLeeway: 0, - EndSessionEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + ZoneSyncLeeway: 0, + EndSessionEndpoint: "https://foo.com/logout", + PostLogoutRedirectURI: "https://foo.com/", + AccessTokenEnable: true, }, key: "default/oidc-policy-1", }, @@ -8280,16 +8280,16 @@ func TestGeneratePoliciesFails(t *testing.T) { }, expectedOidc: &oidcPolicyCfg{ oidc: &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - EndSessionEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + EndSessionEndpoint: "https://foo.com/logout", + PostLogoutRedirectURI: "https://foo.com/", + AccessTokenEnable: true, }, key: "default/oidc-policy-1", }, @@ -8314,14 +8314,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JWKSURI: "https://foo.com/certs", - EndSessionEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - ClientID: "foo", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JWKSURI: "https://foo.com/certs", + EndSessionEndpoint: "https://foo.com/logout", + PostLogoutRedirectURI: "https://foo.com/", + ClientID: "foo", + AccessTokenEnable: true, }, }, }, @@ -8332,14 +8332,14 @@ func TestGeneratePoliciesFails(t *testing.T) { }, Spec: conf_v1.PolicySpec{ OIDC: &conf_v1.OIDC{ - ClientSecret: "oidc-secret", - AuthEndpoint: "https://bar.com/auth", - TokenEndpoint: "https://bar.com/token", - JWKSURI: "https://bar.com/certs", - EndSessionEndpoint: "https://bar.com/logout", - LogoutRedirect: "https://bar.com/", - ClientID: "bar", - AccessTokenEnable: true, + ClientSecret: "oidc-secret", + AuthEndpoint: "https://bar.com/auth", + TokenEndpoint: "https://bar.com/token", + JWKSURI: "https://bar.com/certs", + EndSessionEndpoint: "https://bar.com/logout", + PostLogoutRedirectURI: "https://bar.com/", + ClientID: "bar", + AccessTokenEnable: true, }, }, }, @@ -8367,17 +8367,17 @@ func TestGeneratePoliciesFails(t *testing.T) { }, expectedOidc: &oidcPolicyCfg{ &version2.OIDC{ - AuthEndpoint: "https://foo.com/auth", - TokenEndpoint: "https://foo.com/token", - JwksURI: "https://foo.com/certs", - ClientID: "foo", - ClientSecret: "super_secret_123", - RedirectURI: "/_codexch", - Scope: "openid", - EndSessionEndpoint: "https://foo.com/logout", - LogoutRedirect: "https://foo.com/", - ZoneSyncLeeway: 200, - AccessTokenEnable: true, + AuthEndpoint: "https://foo.com/auth", + TokenEndpoint: "https://foo.com/token", + JwksURI: "https://foo.com/certs", + ClientID: "foo", + ClientSecret: "super_secret_123", + RedirectURI: "/_codexch", + Scope: "openid", + EndSessionEndpoint: "https://foo.com/logout", + PostLogoutRedirectURI: "https://foo.com/", + ZoneSyncLeeway: 200, + AccessTokenEnable: true, }, "default/oidc-policy", }, diff --git a/pkg/apis/configuration/v1/types.go b/pkg/apis/configuration/v1/types.go index 46c231053..604888212 100644 --- a/pkg/apis/configuration/v1/types.go +++ b/pkg/apis/configuration/v1/types.go @@ -648,18 +648,18 @@ type EgressMTLS struct { // OIDC defines an Open ID Connect policy. type OIDC struct { - AuthEndpoint string `json:"authEndpoint"` - TokenEndpoint string `json:"tokenEndpoint"` - JWKSURI string `json:"jwksURI"` - ClientID string `json:"clientID"` - ClientSecret string `json:"clientSecret"` - Scope string `json:"scope"` - RedirectURI string `json:"redirectURI"` - EndSessionEndpoint string `json:"endSessionEndpoint"` - LogoutRedirect string `json:"logoutRedirect"` - ZoneSyncLeeway *int `json:"zoneSyncLeeway"` - AuthExtraArgs []string `json:"authExtraArgs"` - AccessTokenEnable bool `json:"accessTokenEnable"` + AuthEndpoint string `json:"authEndpoint"` + TokenEndpoint string `json:"tokenEndpoint"` + JWKSURI string `json:"jwksURI"` + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + Scope string `json:"scope"` + RedirectURI string `json:"redirectURI"` + EndSessionEndpoint string `json:"endSessionEndpoint"` + PostLogoutRedirectURI string `json:"postLogoutRedirectURI"` + ZoneSyncLeeway *int `json:"zoneSyncLeeway"` + AuthExtraArgs []string `json:"authExtraArgs"` + AccessTokenEnable bool `json:"accessTokenEnable"` } // WAF defines an WAF policy. diff --git a/pkg/apis/configuration/validation/policy.go b/pkg/apis/configuration/validation/policy.go index 0f01ee840..8d3bbbf6c 100644 --- a/pkg/apis/configuration/validation/policy.go +++ b/pkg/apis/configuration/validation/policy.go @@ -260,9 +260,9 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.ClientSecret == "" { return field.ErrorList{field.Required(fieldPath.Child("clientSecret"), "")} } - if oidc.EndSessionEndpoint == "" && oidc.LogoutRedirect != "" { - msg := "logoutRedirect can only be set when endSessionEndpoint is set" - return field.ErrorList{field.Forbidden(fieldPath.Child("logoutRedirect"), msg)} + if oidc.EndSessionEndpoint == "" && oidc.PostLogoutRedirectURI != "" { + msg := "postLogoutRedirectURI can only be set when endSessionEndpoint is set" + return field.ErrorList{field.Forbidden(fieldPath.Child("postLogoutRedirectURI"), msg)} } allErrs := field.ErrorList{} @@ -275,8 +275,8 @@ func validateOIDC(oidc *v1.OIDC, fieldPath *field.Path) field.ErrorList { if oidc.EndSessionEndpoint != "" { allErrs = append(allErrs, validateURL(oidc.EndSessionEndpoint, fieldPath.Child("endSessionEndpoint"))...) } - if oidc.LogoutRedirect != "" { - allErrs = append(allErrs, validatePath(oidc.LogoutRedirect, fieldPath.Child("logoutRedirect"))...) + if oidc.PostLogoutRedirectURI != "" { + allErrs = append(allErrs, validatePath(oidc.PostLogoutRedirectURI, fieldPath.Child("postLogoutRedirectURI"))...) } if oidc.ZoneSyncLeeway != nil { allErrs = append(allErrs, validatePositiveIntOrZero(*oidc.ZoneSyncLeeway, fieldPath.Child("zoneSyncLeeway"))...) diff --git a/pkg/apis/configuration/validation/policy_test.go b/pkg/apis/configuration/validation/policy_test.go index b844c811b..c0a227d9a 100644 --- a/pkg/apis/configuration/validation/policy_test.go +++ b/pkg/apis/configuration/validation/policy_test.go @@ -287,18 +287,18 @@ func TestValidatePolicy_PassesOnValidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - AuthExtraArgs: []string{"foo=bar"}, - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - EndSessionEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - ZoneSyncLeeway: createPointerFromInt(10), - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + AuthExtraArgs: []string{"foo=bar"}, + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + EndSessionEndpoint: "https://foo.bar/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + ZoneSyncLeeway: createPointerFromInt(10), + AccessTokenEnable: true, }, }, }, @@ -395,16 +395,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - EndSessionEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + AccessTokenEnable: true, }, }, }, @@ -416,16 +416,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - EndSessionEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + AccessTokenEnable: true, }, }, }, @@ -450,17 +450,17 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - EndSessionEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - ZoneSyncLeeway: createPointerFromInt(-1), - AccessTokenEnable: false, + AuthEndpoint: "https://foo.bar/auth", + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + ZoneSyncLeeway: createPointerFromInt(-1), + AccessTokenEnable: false, }, }, }, @@ -472,16 +472,16 @@ func TestValidatePolicy_FailsOnInvalidInput(t *testing.T) { policy: &v1.Policy{ Spec: v1.PolicySpec{ OIDC: &v1.OIDC{ - AuthEndpoint: "https://foo.bar/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "https://foo.bar/token", - JWKSURI: "https://foo.bar/certs", - RedirectURI: "/_codexch", - EndSessionEndpoint: "https://foo.bar/logout", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", + AuthEndpoint: "https://foo.bar/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "https://foo.bar/token", + JWKSURI: "https://foo.bar/certs", + RedirectURI: "/_codexch", + EndSessionEndpoint: "https://foo.bar/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", }, }, }, @@ -1245,79 +1245,79 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { }{ { oidc: &v1.OIDC{ - AuthEndpoint: "https://accounts.google.com/o/oauth2/v2/auth", - AuthExtraArgs: []string{"foo=bar", "baz=zot"}, - TokenEndpoint: "https://oauth2.googleapis.com/token", - JWKSURI: "https://www.googleapis.com/oauth2/v3/certs", - EndSessionEndpoint: "https://oauth2.googleapis.com/revoke", - LogoutRedirect: "/_logout", - ClientID: "random-string", - ClientSecret: "random-secret", - Scope: "openid", - RedirectURI: "/foo", - ZoneSyncLeeway: createPointerFromInt(20), - AccessTokenEnable: true, + AuthEndpoint: "https://accounts.google.com/o/oauth2/v2/auth", + AuthExtraArgs: []string{"foo=bar", "baz=zot"}, + TokenEndpoint: "https://oauth2.googleapis.com/token", + JWKSURI: "https://www.googleapis.com/oauth2/v3/certs", + EndSessionEndpoint: "https://oauth2.googleapis.com/revoke", + PostLogoutRedirectURI: "/_logout", + ClientID: "random-string", + ClientSecret: "random-secret", + Scope: "openid", + RedirectURI: "/foo", + ZoneSyncLeeway: createPointerFromInt(20), + AccessTokenEnable: true, }, msg: "verify full oidc", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, msg: "verify azure endpoint", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/auth", - AuthExtraArgs: []string{"kc_idp_hint=foo"}, - TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/auth", + AuthExtraArgs: []string{"kc_idp_hint=foo"}, + TokenEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://keycloak.default.svc.cluster.local:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, }, msg: "domain with port number", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid", + AccessTokenEnable: true, }, msg: "ip address", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+offline_access", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+offline_access", + AccessTokenEnable: true, }, msg: "offline access scope", }, @@ -1333,7 +1333,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { Scope: "openid+", AccessTokenEnable: true, }, - msg: "no logout redirect", + msg: "no post logout redirect URI", }, { oidc: &v1.OIDC{ @@ -1346,7 +1346,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { Scope: "openid+", AccessTokenEnable: true, }, - msg: "no logout endpoint or logout redirect", + msg: "no end-session endpoint or post logout redirect URI", }, { oidc: &v1.OIDC{ @@ -1360,7 +1360,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { Scope: "openid+", AccessTokenEnable: true, }, - msg: "no logout endpoint redirect", + msg: "no post logout redirect URI", }, } @@ -1388,193 +1388,192 @@ func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - ClientID: "client", - ClientSecret: "secret", - Scope: "bogus", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "bogus", + AccessTokenEnable: true, }, fieldPath: "oidc.scope", msg: "missing openid in scope", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - ClientID: "client", - ClientSecret: "secret", - Scope: "openid+bogus\x7f", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "client", + ClientSecret: "secret", + Scope: "openid+bogus\x7f", + AccessTokenEnable: true, }, fieldPath: "oidc.scope", msg: "invalid unicode in scope", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.tokenEndpoint", msg: "missing required field token", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.jwksURI", msg: "missing required field jwk", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientID", msg: "missing required field clientid", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + ClientID: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientSecret", msg: "missing required field client secret", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - // EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - ClientID: "ff", - ClientSecret: "ff", - Scope: "openid+profile", - AccessTokenEnable: true, - }, - fieldPath: "oidc.logoutRedirect", + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + PostLogoutRedirectURI: "/_logout", + ClientID: "ff", + ClientSecret: "ff", + Scope: "openid+profile", + AccessTokenEnable: true, + }, + fieldPath: "oidc.postLogoutRedirectURI", msg: "missing required field logout endpoint when logout redirect is set", }, { oidc: &v1.OIDC{ - AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", - TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", - JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", - EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "ff", - ClientSecret: "-ff-", - Scope: "openid+profile", - AccessTokenEnable: true, + AuthEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/authorize", + TokenEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/oauth2/v2.0/token", + JWKSURI: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/keys", + EndSessionEndpoint: "https://login.microsoftonline.com/dd-fff-eee-1234-9be/discovery/v2.0/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "ff", + ClientSecret: "-ff-", + Scope: "openid+profile", + AccessTokenEnable: true, }, fieldPath: "oidc.clientSecret", msg: "invalid secret name", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://foo.\bar.com", - TokenEndpoint: "http://keycloak.default/", - JWKSURI: "http://keycloak.default/", - EndSessionEndpoint: "http://keycloak.default/", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://foo.\bar.com", + TokenEndpoint: "http://keycloak.default/", + JWKSURI: "http://keycloak.default/", + EndSessionEndpoint: "http://keycloak.default/", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, }, fieldPath: "oidc.authEndpoint", msg: "invalid URL", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "http://foo.bar", - RedirectURI: "/_codexch", - ClientID: "bar", - ClientSecret: "foo", - Scope: "openid", - AccessTokenEnable: true, - }, - fieldPath: "oidc.logoutRedirect", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "http://foo.bar", + RedirectURI: "/_codexch", + ClientID: "bar", + ClientSecret: "foo", + Scope: "openid", + AccessTokenEnable: true, + }, + fieldPath: "oidc.postLogoutRedirectURI", msg: "invalid logout redirect URL", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "$foo$bar", - ClientSecret: "secret", - Scope: "openid", - AccessTokenEnable: true, + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "$foo$bar", + ClientSecret: "secret", + Scope: "openid", + AccessTokenEnable: true, }, fieldPath: "oidc.clientID", msg: "invalid chars in clientID", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - AuthExtraArgs: []string{"foo;bar"}, - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", - ClientID: "foobar", - ClientSecret: "secret", - Scope: "openid", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + AuthExtraArgs: []string{"foo;bar"}, + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", + ClientID: "foobar", + ClientSecret: "secret", + Scope: "openid", }, fieldPath: "oidc.authExtraArgs", msg: "invalid chars in authExtraArgs", }, { oidc: &v1.OIDC{ - AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", - TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", - JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", - EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", - LogoutRedirect: "/_logout", - RedirectURI: "/_codexch", ClientID: "foobar", + AuthEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/auth", + TokenEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/token", + JWKSURI: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/certs", + EndSessionEndpoint: "http://127.0.0.1:8080/realms/master/protocol/openid-connect/logout", + PostLogoutRedirectURI: "/_logout", + RedirectURI: "/_codexch", ClientID: "foobar", ClientSecret: "secret", Scope: "openid", ZoneSyncLeeway: createPointerFromInt(-1), From 2e3007949d842ac591d82407d18671b15d79a664 Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:54:29 +0100 Subject: [PATCH 7/8] fix docs and test messages Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- docs/content/configuration/policy-resource.md | 2 +- pkg/apis/configuration/validation/policy_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md index a07dc443a..3092ceb2e 100644 --- a/docs/content/configuration/policy-resource.md +++ b/docs/content/configuration/policy-resource.md @@ -609,7 +609,7 @@ The configuration in the example doesn't enable TLS and the synchronization betw #### Limitations -The OIDC policy defines a few internal locations that can't be customized: `/_jwks_uri`, `/_token`, `/_refresh`, `/_id_token_validation`, `/logout`. In addition, as explained below, `/_codexch` is the default value for redirect URI, and `/_logout` is the default value for logout endpoint, both of which can be customized. Specifying one of these locations as a route in the VirtualServer or VirtualServerRoute will result in a collision and NGINX Plus will fail to reload. +The OIDC policy defines a few internal locations that can't be customized: `/_jwks_uri`, `/_token`, `/_refresh`, `/_id_token_validation`, `/logout`. In addition, as explained below, `/_codexch` is the default value for redirect URI, and `/_logout` is the default value for post logout redirect URI, both of which can be customized. Specifying one of these locations as a route in the VirtualServer or VirtualServerRoute will result in a collision and NGINX Plus will fail to reload. {{% table %}} |Field | Description | Type | Required | diff --git a/pkg/apis/configuration/validation/policy_test.go b/pkg/apis/configuration/validation/policy_test.go index c0a227d9a..bf2482b7f 100644 --- a/pkg/apis/configuration/validation/policy_test.go +++ b/pkg/apis/configuration/validation/policy_test.go @@ -1330,7 +1330,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { RedirectURI: "/_codexch", ClientID: "client", ClientSecret: "secret", - Scope: "openid+", + Scope: "openid", AccessTokenEnable: true, }, msg: "no post logout redirect URI", @@ -1343,7 +1343,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { RedirectURI: "/_codexch", ClientID: "client", ClientSecret: "secret", - Scope: "openid+", + Scope: "openid", AccessTokenEnable: true, }, msg: "no end-session endpoint or post logout redirect URI", @@ -1357,7 +1357,7 @@ func TestValidateOIDC_PassesOnValidOIDC(t *testing.T) { RedirectURI: "/_codexch", ClientID: "client", ClientSecret: "secret", - Scope: "openid+", + Scope: "openid", AccessTokenEnable: true, }, msg: "no post logout redirect URI", @@ -1484,7 +1484,7 @@ func TestValidateOIDC_FailsOnInvalidOIDC(t *testing.T) { AccessTokenEnable: true, }, fieldPath: "oidc.postLogoutRedirectURI", - msg: "missing required field logout endpoint when logout redirect is set", + msg: "missing required field end session endpoint when post logout redirect URI is set", }, { oidc: &v1.OIDC{ From 50e8fd57263a40b9ff0d2beb195f721c8b1fef2d Mon Sep 17 00:00:00 2001 From: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Date: Tue, 6 Aug 2024 13:36:46 +0100 Subject: [PATCH 8/8] update test field values Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> Signed-off-by: Haywood Shannon <5781935+haywoodsh@users.noreply.github.com> --- internal/configs/virtualserver_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go index 5f3555eb1..db53b48bd 100644 --- a/internal/configs/virtualserver_test.go +++ b/internal/configs/virtualserver_test.go @@ -6865,7 +6865,7 @@ func TestGeneratePolicies(t *testing.T) { ZoneSyncLeeway: createPointerFromInt(20), AccessTokenEnable: true, EndSessionEndpoint: "http://example.com/logout", - PostLogoutRedirectURI: "http://example.com/", + PostLogoutRedirectURI: "/_logout", }, }, }, @@ -8165,7 +8165,7 @@ func TestGeneratePoliciesFails(t *testing.T) { TokenEndpoint: "http://foo.com/bar", JWKSURI: "http://foo.com/bar", EndSessionEndpoint: "http://foo.com/bar", - PostLogoutRedirectURI: "http://foo.com/bar", + PostLogoutRedirectURI: "/_logout", AccessTokenEnable: true, }, }, @@ -8215,7 +8215,7 @@ func TestGeneratePoliciesFails(t *testing.T) { TokenEndpoint: "https://foo.com/token", JWKSURI: "https://foo.com/certs", EndSessionEndpoint: "https://foo.com/logout", - PostLogoutRedirectURI: "https://foo.com/", + PostLogoutRedirectURI: "/_logout", AccessTokenEnable: true, }, }, @@ -8233,7 +8233,7 @@ func TestGeneratePoliciesFails(t *testing.T) { TokenEndpoint: "https://bar.com/token", JWKSURI: "https://bar.com/certs", EndSessionEndpoint: "https://bar.com/logout", - PostLogoutRedirectURI: "https://bar.com/", + PostLogoutRedirectURI: "/_logout", AccessTokenEnable: true, }, }, @@ -8263,7 +8263,7 @@ func TestGeneratePoliciesFails(t *testing.T) { Scope: "openid", ZoneSyncLeeway: 0, EndSessionEndpoint: "https://foo.com/logout", - PostLogoutRedirectURI: "https://foo.com/", + PostLogoutRedirectURI: "/_logout", AccessTokenEnable: true, }, key: "default/oidc-policy-1", @@ -8288,7 +8288,7 @@ func TestGeneratePoliciesFails(t *testing.T) { RedirectURI: "/_codexch", Scope: "openid", EndSessionEndpoint: "https://foo.com/logout", - PostLogoutRedirectURI: "https://foo.com/", + PostLogoutRedirectURI: "/_logout", AccessTokenEnable: true, }, key: "default/oidc-policy-1", @@ -8319,7 +8319,7 @@ func TestGeneratePoliciesFails(t *testing.T) { TokenEndpoint: "https://foo.com/token", JWKSURI: "https://foo.com/certs", EndSessionEndpoint: "https://foo.com/logout", - PostLogoutRedirectURI: "https://foo.com/", + PostLogoutRedirectURI: "/_logout", ClientID: "foo", AccessTokenEnable: true, }, @@ -8337,7 +8337,7 @@ func TestGeneratePoliciesFails(t *testing.T) { TokenEndpoint: "https://bar.com/token", JWKSURI: "https://bar.com/certs", EndSessionEndpoint: "https://bar.com/logout", - PostLogoutRedirectURI: "https://bar.com/", + PostLogoutRedirectURI: "/_logout", ClientID: "bar", AccessTokenEnable: true, }, @@ -8375,7 +8375,7 @@ func TestGeneratePoliciesFails(t *testing.T) { RedirectURI: "/_codexch", Scope: "openid", EndSessionEndpoint: "https://foo.com/logout", - PostLogoutRedirectURI: "https://foo.com/", + PostLogoutRedirectURI: "/_logout", ZoneSyncLeeway: 200, AccessTokenEnable: true, },