Change:
<!-- Thanks for filing an issue! Before hitting the button, please answer these questions.--Is this a request for help? (If yes, you should use our troubleshooting guide and community support channels, see ): No What keywords did you search in Kubernetes issues before filing this one? (If you have found any duplicates, you should instead reply there.): impersonate system:authenticated Is this a BUG REPORT or FEATURE REQUEST? (choose one): FEATURE REQUEST <!-- If this is a BUG REPORT, please: Fill in as much of the template below as you can. If you leave out information, we can't help you as well. If this is a FEATURE REQUEST, please: Describe in detail the feature/behavior/change you'd like to see. In both cases, be ready for followup questions, and please respond in a timely manner. If we can't reproduce a bug or think a feature already exists, we might close your issue. If we're wrong, PLEASE feel free to reopen it and explain why. --Kubernetes version (use ): Environment: Cloud provider or hardware configuration: baremetal OS (e.g. from /etc/os-release): Centos7 Kernel (e.g. ): Install tools: custom Others: Using RBAC What happened: Impersonating a user is not setting group which causes impersonate to fail What you expected to happen: If a user is in the tokens file they and they are impersonated the group should be for authz. How to reproduce it (as minimally and precisely as possible): sure group has cluster role a test user via token file a user with impersonate access submit a command via kubectl That request will fail with 403 response even though the user is in the group. Anything else we need to know: cc
We can probably be smart and put the authenticated group adder around the result of the impersonation filter. you see any issues with that?
We provide the group field to provide this kind of information. I'm not sure I would expect my request to the server about a particular user/group tuple to be evaluated for a different user/group tuple.
for impersonation, we already add groups when known (service accounts). doing so for the system:authenticated/system:unauthenticated groups makes sense to me
Only when the groups aren't specified, right? If memory serves, that's how we did it downstream where we can make group determination.

Discussion:
} // if groups are not specified, then we need to look them up differently depending on the type of user <del> // if they are specified, then they are the authority </del> <ins> // if they are specified, then they are the authority (including the inclusion of system:authenticated/system:unauthenticated groups) </ins> groupsSpecified := len(req.Header[authenticationapi.ImpersonateGroupHeader]) > 0 // make sure we're allowed to impersonate each thing we're requesting.  While we're iterating through, start building username

} } <ins> if !groupsSpecified && username != user.Anonymous { // When impersonating a non-anonymous user, if no groups were specified // if neither the system:authenticated nor system:unauthenticated groups are explicitly included, // include the system:authenticated group in the impersonated user info found := false for _, group := range groups { if group == user.AllAuthenticated || group == user.AllUnauthenticated { found = true break } } if !found { groups = append(groups, user.AllAuthenticated) } } </ins> newUser := &user.DefaultInfo{ Name:   username, Groups: groups,

impersonationUserExtras: map[string][]string{"scopes": {"scope-a", "scope-b"}}, expectedUser: &user.DefaultInfo{ Name:   "system:admin", <del> Groups: []string{}, </del> <ins> Groups: []string{"system:authenticated"}, </ins> Extra:  map[string][]string{"scopes": {"scope-a", "scope-b"}}, }, expectedCode: http.StatusOK,

impersonationUser: "tester", expectedUser: &user.DefaultInfo{ Name:   "tester", <del> Groups: []string{}, </del> <ins> Groups: []string{"system:authenticated"}, </ins> Extra:  map[string][]string{}, }, expectedCode: http.StatusOK,

impersonationUser: "system:serviceaccount:foo:default", expectedUser: &user.DefaultInfo{ Name:   "system:serviceaccount:foo:default", <del> Groups: []string{"system:serviceaccounts", "system:serviceaccounts:foo"}, </del> <ins> Groups: []string{"system:serviceaccounts", "system:serviceaccounts:foo", "system:authenticated"}, Extra:  map[string][]string{}, }, expectedCode: http.StatusOK, }, { name: "anonymous-username-prevents-adding-authenticated-group", user: &user.DefaultInfo{ Name: "system:admin", }, impersonationUser: "system:anonymous", expectedUser: &user.DefaultInfo{ Name:   "system:anonymous", Groups: []string{}, Extra:  map[string][]string{}, }, expectedCode: http.StatusOK, }, { name: "unauthenticated-group-prevents-adding-authenticated-group", user: &user.DefaultInfo{ Name: "system:admin", }, impersonationUser:   "unknown", impersonationGroups: []string{"system:unauthenticated"}, expectedUser: &user.DefaultInfo{ Name:   "unknown", Groups: []string{"system:unauthenticated"}, Extra:  map[string][]string{}, }, expectedCode: http.StatusOK, }, { name: "unauthenticated-group-prevents-double-adding-authenticated-group", user: &user.DefaultInfo{ Name: "system:admin", }, impersonationUser:   "unknown", impersonationGroups: []string{"system:authenticated"}, expectedUser: &user.DefaultInfo{ Name:   "unknown", Groups: []string{"system:authenticated"}, </ins> Extra:  map[string][]string{}, }, expectedCode: http.StatusOK,