diff --git a/pkg/utils/user_group.go b/pkg/utils/user_group.go index 95aec74d..d5e94781 100644 --- a/pkg/utils/user_group.go +++ b/pkg/utils/user_group.go @@ -20,23 +20,29 @@ import ( "sort" ) -type UserGroupList []string - -func (u UserGroupList) Len() int { - return len(u) +type UserGroupList interface { + Find(needle string) (found bool) } -func (u UserGroupList) Less(i, j int) bool { - return u[i] < u[j] +type userGroupList []string + +func NewUserGroupList(groups []string) UserGroupList { + list := make(userGroupList, len(groups)) + for k, v := range groups { + list[k] = v + } + sort.SliceStable(list, func(i, j int) bool { + return list[i] < list[j] + }) + return list } -func (u UserGroupList) Swap(i, j int) { - u[i], u[j] = u[j], u[i] -} - -func (u UserGroupList) IsInCapsuleGroup(capsuleGroup string) (ok bool) { - sort.Sort(u) - i := sort.SearchStrings(u, capsuleGroup) - ok = i < u.Len() && u[i] == capsuleGroup +// Find sorts itself using the SliceStable and perform a binary-search for the given string. +func (u userGroupList) Find(needle string) (found bool) { + sort.SliceStable(u, func(i, j int) bool { + return i < j + }) + i := sort.SearchStrings(u, needle) + found = i < len(u) && u[i] == needle return } diff --git a/pkg/utils/user_group_test.go b/pkg/utils/user_group_test.go index 2a220f9b..b36ba7c6 100644 --- a/pkg/utils/user_group_test.go +++ b/pkg/utils/user_group_test.go @@ -19,5 +19,5 @@ func TestIsInCapsuleGroup(t *testing.T) { capsuleGroup := "kubernetes-abilitytologin" - assert.True(t, UserGroupList(groups).IsInCapsuleGroup(capsuleGroup), nil) + assert.True(t, NewUserGroupList(groups).Find(capsuleGroup), nil) } diff --git a/pkg/webhook/utils/in_capsule_group.go b/pkg/webhook/utils/in_capsule_group.go index 7fad6cc8..7fe68622 100644 --- a/pkg/webhook/utils/in_capsule_group.go +++ b/pkg/webhook/utils/in_capsule_group.go @@ -40,7 +40,14 @@ type handler struct { // If the user performing action is not a Capsule user, can be skipped func (h handler) isCapsuleUser(req admission.Request) bool { - return utils.UserGroupList(req.UserInfo.Groups).IsInCapsuleGroup(h.capsuleGroup) + g := utils.NewUserGroupList(req.UserInfo.Groups) + // if the user is a ServiceAccount belonging to the kube-system namespace, definitely, it's not a Capsule user + // and we can skip the check in case of Capsule user group assigned to system:authenticated + // (ref: https://github.com/clastix/capsule/issues/234) + if g.Find("system:serviceaccounts:kube-system") { + return false + } + return g.Find(h.capsuleGroup) } func (h *handler) OnCreate(client client.Client, decoder *admission.Decoder) webhook.Func {