diff --git a/CHANGELOG/CHANGELOG-1.30.md b/CHANGELOG/CHANGELOG-1.30.md index b269ada4bab..c87cfd0d87f 100644 --- a/CHANGELOG/CHANGELOG-1.30.md +++ b/CHANGELOG/CHANGELOG-1.30.md @@ -1584,7 +1584,7 @@ name | architectures ([#123344](https://github.com/kubernetes/kubernetes/pull/123344), [@nilekhc](https://github.com/nilekhc)) - When configuring a JWT authenticator: - If `username.expression` used 'claims.email', then 'claims.email_verified' must have been used in `username.expression` or `extra[*].valueExpression` or `claimValidationRules[*].expression`. An example claim validation rule expression that matches the validation automatically applied when `username.claim` is set to 'email' is 'claims.?email_verified.orValue(true)'. + If `username.expression` used 'claims.email', then 'claims.email_verified' must have been used in `username.expression` or `extra[*].valueExpression` or `claimValidationRules[*].expression`. An example claim validation rule expression that matches the validation automatically applied when `username.claim` is set to 'email' is 'claims.?email_verified.orValue(true) == true'. ([#123737](https://github.com/kubernetes/kubernetes/pull/123737), [@enj](https://github.com/enj)) - `readOnly` volumes now support recursive read-only mounts for kernel versions >= 5.12." ([#123180](https://github.com/kubernetes/kubernetes/pull/123180), [@AkihiroSuda](https://github.com/AkihiroSuda)) @@ -2416,7 +2416,7 @@ name | architectures If username.expression uses 'claims.email', then 'claims.email_verified' must be used in username.expression or extra[*].valueExpression or claimValidationRules[*].expression. An example claim validation rule expression that matches the validation automatically - applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'. ([#123737](https://github.com/kubernetes/kubernetes/pull/123737), [@enj](https://github.com/enj)) [SIG API Machinery and Auth] + applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. ([#123737](https://github.com/kubernetes/kubernetes/pull/123737), [@enj](https://github.com/enj)) [SIG API Machinery and Auth] ### Feature diff --git a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go index dee2c115a15..0a50799c26e 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go @@ -352,7 +352,9 @@ type ClaimMappings struct { // If username.expression uses 'claims.email', then 'claims.email_verified' must be used in // username.expression or extra[*].valueExpression or claimValidationRules[*].expression. // An example claim validation rule expression that matches the validation automatically - // applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'. + // applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing + // the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified + // claim will be caught at runtime. // // In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, // the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. diff --git a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go index a0e13593b3b..72fe602b95d 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1beta1/types.go @@ -323,7 +323,9 @@ type ClaimMappings struct { // If username.expression uses 'claims.email', then 'claims.email_verified' must be used in // username.expression or extra[*].valueExpression or claimValidationRules[*].expression. // An example claim validation rule expression that matches the validation automatically - // applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'. + // applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true) == true'. By explicitly comparing + // the value to true, we let type-checking see the result will be a boolean, and to make sure a non-boolean email_verified + // claim will be caught at runtime. // // In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, // the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. diff --git a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go index 2e39d375f1c..6d761b59318 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go @@ -585,6 +585,61 @@ func TestValidateAuthenticationConfiguration(t *testing.T) { }, want: "", }, + { + name: "valid authentication configuration that uses verified email via claim validation rule", + in: &api.AuthenticationConfiguration{ + JWT: []api.JWTAuthenticator{ + { + Issuer: api.Issuer{ + URL: "https://issuer-url", + Audiences: []string{"audience"}, + }, + ClaimValidationRules: []api.ClaimValidationRule{ + { + // By explicitly comparing the value to true, we let type-checking see the result will be + // a boolean, and to make sure a non-boolean email_verified claim will be caught at runtime. + Expression: `claims.?email_verified.orValue(true) == true`, + }, + }, + // allow email claim only when email_verified is present and true + ClaimMappings: api.ClaimMappings{ + Username: api.PrefixedClaimOrExpression{ + Expression: `{claims.?email: "panda"}`, + }, + }, + }, + }, + }, + want: "", + }, + { + name: "valid authentication configuration that uses verified email via claim validation rule incorrectly", + in: &api.AuthenticationConfiguration{ + JWT: []api.JWTAuthenticator{ + { + Issuer: api.Issuer{ + URL: "https://issuer-url", + Audiences: []string{"audience"}, + }, + ClaimValidationRules: []api.ClaimValidationRule{ + { + // This expression was previously documented in the godoc for the JWT authenticator + // and was incorrect. It was changed to the above expression in the previous test case. + // Testing the old expression here to confirm it fails validation. + Expression: `claims.?email_verified.orValue(true)`, + }, + }, + // allow email claim only when email_verified is present and true + ClaimMappings: api.ClaimMappings{ + Username: api.PrefixedClaimOrExpression{ + Expression: `{claims.?email: "panda"}`, + }, + }, + }, + }, + }, + want: `[jwt[0].claimValidationRules[0].expression: Invalid value: "claims.?email_verified.orValue(true)": must evaluate to bool, jwt[0].claimMappings.username.expression: Invalid value: "{claims.?email: \"panda\"}": claims.email_verified must be used in claimMappings.username.expression or claimMappings.extra[*].valueExpression or claimValidationRules[*].expression when claims.email is used in claimMappings.username.expression]`, + }, { name: "valid authentication configuration", in: &api.AuthenticationConfiguration{