mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +00:00
Merge pull request #33332 from ericchiang/oidc-allow-string-as-group-claim
Automatic merge from submit-queue oidc authenticator: allow string value as groups claim Allow the group claim to be a single string instead of an array of strings. This means the following claim { "role": "admin" } Will be mapped to the groups ["admin"] cc @kubernetes/sig-auth @mlbiam closes #33290
This commit is contained in:
commit
33eabe675b
@ -401,7 +401,7 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||||||
|
|
||||||
fs.StringVar(&s.OIDCGroupsClaim, "oidc-groups-claim", "", ""+
|
fs.StringVar(&s.OIDCGroupsClaim, "oidc-groups-claim", "", ""+
|
||||||
"If provided, the name of a custom OpenID Connect claim for specifying user groups. "+
|
"If provided, the name of a custom OpenID Connect claim for specifying user groups. "+
|
||||||
"The claim value is expected to be an array of strings. This flag is experimental, "+
|
"The claim value is expected to be a string or array of strings. This flag is experimental, "+
|
||||||
"please see the authentication documentation for further details.")
|
"please see the authentication documentation for further details.")
|
||||||
|
|
||||||
fs.Var(&s.RuntimeConfig, "runtime-config", ""+
|
fs.Var(&s.RuntimeConfig, "runtime-config", ""+
|
||||||
|
@ -73,7 +73,7 @@ type OIDCOptions struct {
|
|||||||
|
|
||||||
// GroupsClaim, if specified, causes the OIDCAuthenticator to try to populate the user's
|
// GroupsClaim, if specified, causes the OIDCAuthenticator to try to populate the user's
|
||||||
// groups with a ID Token field. If the GrouppClaim field is present in a ID Token the value
|
// groups with a ID Token field. If the GrouppClaim field is present in a ID Token the value
|
||||||
// must be a list of strings.
|
// must be a string or list of strings.
|
||||||
GroupsClaim string
|
GroupsClaim string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,10 +251,14 @@ func (a *OIDCAuthenticator) AuthenticateToken(value string) (user.Info, bool, er
|
|||||||
if a.groupsClaim != "" {
|
if a.groupsClaim != "" {
|
||||||
groups, found, err := claims.StringsClaim(a.groupsClaim)
|
groups, found, err := claims.StringsClaim(a.groupsClaim)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Custom claim is present, but isn't an array of strings.
|
// Groups type is present but is not an array of strings, try to decode as a string.
|
||||||
return nil, false, fmt.Errorf("custom group claim contains invalid object: %v", err)
|
group, _, err := claims.StringClaim(a.groupsClaim)
|
||||||
}
|
if err != nil {
|
||||||
if found {
|
// Custom claim is present, but isn't an array of strings or a string.
|
||||||
|
return nil, false, fmt.Errorf("custom group claim contains invalid type: %T", claims[a.groupsClaim])
|
||||||
|
}
|
||||||
|
info.Groups = []string{group}
|
||||||
|
} else if found {
|
||||||
info.Groups = groups
|
info.Groups = groups
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import (
|
|||||||
oidctesting "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/oidc/testing"
|
oidctesting "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/oidc/testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func generateToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups []string, iat, exp time.Time) string {
|
func generateToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups interface{}, iat, exp time.Time) string {
|
||||||
signer := op.PrivKey.Signer()
|
signer := op.PrivKey.Signer()
|
||||||
claims := oidc.NewClaims(iss, sub, aud, iat, exp)
|
claims := oidc.NewClaims(iss, sub, aud, iat, exp)
|
||||||
claims.Add(usernameClaim, value)
|
claims.Add(usernameClaim, value)
|
||||||
@ -49,15 +49,15 @@ func generateToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud str
|
|||||||
return jwt.Encode()
|
return jwt.Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateGoodToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups []string) string {
|
func generateGoodToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups interface{}) string {
|
||||||
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now(), time.Now().Add(time.Hour))
|
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now(), time.Now().Add(time.Hour))
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateMalformedToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups []string) string {
|
func generateMalformedToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups interface{}) string {
|
||||||
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now(), time.Now().Add(time.Hour)) + "randombits"
|
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now(), time.Now().Add(time.Hour)) + "randombits"
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateExpiredToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups []string) string {
|
func generateExpiredToken(t *testing.T, op *oidctesting.OIDCProvider, iss, sub, aud string, usernameClaim, value, groupsClaim string, groups interface{}) string {
|
||||||
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now().Add(-2*time.Hour), time.Now().Add(-1*time.Hour))
|
return generateToken(t, op, iss, sub, aud, usernameClaim, value, groupsClaim, groups, time.Now().Add(-2*time.Hour), time.Now().Add(-1*time.Hour))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,6 +239,24 @@ func TestOIDCAuthentication(t *testing.T) {
|
|||||||
true,
|
true,
|
||||||
"",
|
"",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Group claim is a string rather than an array. Map that string to a single group.
|
||||||
|
"email",
|
||||||
|
"groups",
|
||||||
|
generateGoodToken(t, op, srv.URL, "client-foo", "client-foo", "email", "foo@example.com", "groups", "group1"),
|
||||||
|
&user.DefaultInfo{Name: "foo@example.com", Groups: []string{"group1"}},
|
||||||
|
true,
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Group claim is not a string or array of strings. Throw out this as invalid.
|
||||||
|
"email",
|
||||||
|
"groups",
|
||||||
|
generateGoodToken(t, op, srv.URL, "client-foo", "client-foo", "email", "foo@example.com", "groups", 1),
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
"custom group claim contains invalid type: float64",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"sub",
|
"sub",
|
||||||
"",
|
"",
|
||||||
|
Loading…
Reference in New Issue
Block a user