authn: fix cache mutation by AuthenticatedGroupAdder

The cached token authenticator returns a cache value. The group adder changes it.

Kubernetes-commit: e09e81e4f6e62f9fef89736e79d04983a77e695f
This commit is contained in:
Dr. Stefan Schimanski 2022-05-11 16:17:29 +02:00 committed by Kubernetes Publisher
parent a0fc11eb6a
commit 3677d6afcf
5 changed files with 62 additions and 13 deletions

View File

@ -51,11 +51,16 @@ func (g *AuthenticatedGroupAdder) AuthenticateRequest(req *http.Request) (*authe
} }
} }
r.User = &user.DefaultInfo{ newGroups := make([]string, 0, len(r.User.GetGroups())+1)
newGroups = append(newGroups, r.User.GetGroups()...)
newGroups = append(newGroups, user.AllAuthenticated)
ret := *r // shallow copy
ret.User = &user.DefaultInfo{
Name: r.User.GetName(), Name: r.User.GetName(),
UID: r.User.GetUID(), UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), user.AllAuthenticated), Groups: newGroups,
Extra: r.User.GetExtra(), Extra: r.User.GetExtra(),
} }
return r, true, nil return &ret, true, nil
} }

View File

@ -41,11 +41,17 @@ func (g *GroupAdder) AuthenticateRequest(req *http.Request) (*authenticator.Resp
if err != nil || !ok { if err != nil || !ok {
return nil, ok, err return nil, ok, err
} }
r.User = &user.DefaultInfo{
newGroups := make([]string, 0, len(r.User.GetGroups())+len(g.Groups))
newGroups = append(newGroups, r.User.GetGroups()...)
newGroups = append(newGroups, g.Groups...)
ret := *r // shallow copy
ret.User = &user.DefaultInfo{
Name: r.User.GetName(), Name: r.User.GetName(),
UID: r.User.GetUID(), UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), g.Groups...), Groups: newGroups,
Extra: r.User.GetExtra(), Extra: r.User.GetExtra(),
} }
return r, true, nil return &ret, true, nil
} }

View File

@ -26,10 +26,14 @@ import (
) )
func TestGroupAdder(t *testing.T) { func TestGroupAdder(t *testing.T) {
capacity := make([]string, 0, 1024)
response := &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: append(capacity, "original")}}
orig := toJson(response)
adder := authenticator.Request( adder := authenticator.Request(
NewGroupAdder( NewGroupAdder(
authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
return &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: []string{"original"}}}, true, nil return response, true, nil
}), }),
[]string{"added"}, []string{"added"},
), ),
@ -39,12 +43,16 @@ func TestGroupAdder(t *testing.T) {
if want := []string{"original", "added"}; !reflect.DeepEqual(r.User.GetGroups(), want) { if want := []string{"original", "added"}; !reflect.DeepEqual(r.User.GetGroups(), want) {
t.Errorf("Unexpected groups\ngot:\t%#v\nwant:\t%#v", r.User.GetGroups(), want) t.Errorf("Unexpected groups\ngot:\t%#v\nwant:\t%#v", r.User.GetGroups(), want)
} }
if got := toJson(response); got != orig {
t.Errorf("Expected response from delegate to be unmodified: orig=%v got=%v", orig, got)
}
} }
func TestAuthenticatedGroupAdder(t *testing.T) { func TestAuthenticatedGroupAdder(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
inputUser user.Info inputUser *user.DefaultInfo
expectedUser user.Info expectedUser user.Info
}{ }{
{ {
@ -94,10 +102,16 @@ func TestAuthenticatedGroupAdder(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
capacity := make([]string, 0, 1024)
user := test.inputUser
user.Groups = append(capacity, user.Groups...) // make sure there is capacity in the groups array to trigger potential mutation
response := &authenticator.Response{User: user}
orig := toJson(response)
adder := authenticator.Request( adder := authenticator.Request(
NewAuthenticatedGroupAdder( NewAuthenticatedGroupAdder(
authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) { authenticator.RequestFunc(func(req *http.Request) (*authenticator.Response, bool, error) {
return &authenticator.Response{User: test.inputUser}, true, nil return response, true, nil
}), }),
), ),
) )
@ -106,6 +120,10 @@ func TestAuthenticatedGroupAdder(t *testing.T) {
if !reflect.DeepEqual(r.User, test.expectedUser) { if !reflect.DeepEqual(r.User, test.expectedUser) {
t.Errorf("Unexpected user\ngot:\t%#v\nwant:\t%#v", r.User, test.expectedUser) t.Errorf("Unexpected user\ngot:\t%#v\nwant:\t%#v", r.User, test.expectedUser)
} }
if got := toJson(response); got != orig {
t.Errorf("Expected response from delegate to be unmodified: orig=%v got=%v", orig, got)
}
} }
} }

View File

@ -41,11 +41,17 @@ func (g *TokenGroupAdder) AuthenticateToken(ctx context.Context, token string) (
if err != nil || !ok { if err != nil || !ok {
return nil, ok, err return nil, ok, err
} }
r.User = &user.DefaultInfo{
newGroups := make([]string, 0, len(r.User.GetGroups())+len(g.Groups))
newGroups = append(newGroups, r.User.GetGroups()...)
newGroups = append(newGroups, g.Groups...)
ret := *r // shallow copy
ret.User = &user.DefaultInfo{
Name: r.User.GetName(), Name: r.User.GetName(),
UID: r.User.GetUID(), UID: r.User.GetUID(),
Groups: append(r.User.GetGroups(), g.Groups...), Groups: newGroups,
Extra: r.User.GetExtra(), Extra: r.User.GetExtra(),
} }
return r, true, nil return &ret, true, nil
} }

View File

@ -18,6 +18,7 @@ package group
import ( import (
"context" "context"
"encoding/json"
"reflect" "reflect"
"testing" "testing"
@ -26,10 +27,14 @@ import (
) )
func TestTokenGroupAdder(t *testing.T) { func TestTokenGroupAdder(t *testing.T) {
capacity := make([]string, 0, 1024)
response := &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: append(capacity, "original")}}
orig := toJson(response)
adder := authenticator.Token( adder := authenticator.Token(
NewTokenGroupAdder( NewTokenGroupAdder(
authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) {
return &authenticator.Response{User: &user.DefaultInfo{Name: "user", Groups: []string{"original"}}}, true, nil return response, true, nil
}), }),
[]string{"added"}, []string{"added"},
), ),
@ -39,4 +44,13 @@ func TestTokenGroupAdder(t *testing.T) {
if !reflect.DeepEqual(r.User.GetGroups(), []string{"original", "added"}) { if !reflect.DeepEqual(r.User.GetGroups(), []string{"original", "added"}) {
t.Errorf("Expected original,added groups, got %#v", r.User.GetGroups()) t.Errorf("Expected original,added groups, got %#v", r.User.GetGroups())
} }
if got := toJson(response); got != orig {
t.Errorf("Expected response from delegate to be unmodified: orig=%v got=%v", orig, got)
}
}
func toJson(x interface{}) string {
b, _ := json.Marshal(x)
return string(b)
} }