RBAC: Add legacy authorization checks to service accounts (#93753)

* Extract a helper funtion to perform list with authorization checks

* Add k8s verb to utils package

* Construct default mapping when no custom mapping is passed

* Configure authorization checks for service accounts

* Fix helper and add filtering to service accounts
This commit is contained in:
Karl Persson
2024-09-27 15:53:11 +02:00
committed by GitHub
parent 7710f1c3cf
commit 0160f4f72c
14 changed files with 424 additions and 118 deletions
+24 -83
View File
@@ -11,7 +11,6 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
"github.com/grafana/authlib/claims"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/apimachinery/utils"
iamv0 "github.com/grafana/grafana/pkg/apis/iam/v0alpha1"
"github.com/grafana/grafana/pkg/registry/apis/iam/common"
@@ -62,99 +61,40 @@ func (s *LegacyStore) ConvertToTable(ctx context.Context, object runtime.Object,
}
func (s *LegacyStore) List(ctx context.Context, options *internalversion.ListOptions) (runtime.Object, error) {
ns, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
return nil, err
}
res, err := common.List(
ctx, resource.GetName(), s.ac, common.PaginationFromListOptions(options),
func(ctx context.Context, ns claims.NamespaceInfo, p common.Pagination) (*common.ListResponse[iamv0.User], error) {
found, err := s.store.ListUsers(ctx, ns, legacy.ListUserQuery{
Pagination: p,
})
if s.ac != nil {
return s.listWithCheck(ctx, ns, common.PaginationFromListOptions(options))
}
return s.listWithoutCheck(ctx, ns, common.PaginationFromListOptions(options))
}
func (s *LegacyStore) listWithCheck(ctx context.Context, ns claims.NamespaceInfo, p common.Pagination) (runtime.Object, error) {
ident, err := identity.GetRequester(ctx)
if err != nil {
return nil, err
}
check, err := s.ac.Compile(ctx, ident, claims.AccessRequest{
Verb: "list",
Resource: resource.GetName(),
Namespace: ns.Value,
})
if err != nil {
return nil, err
}
list := func(p common.Pagination) ([]iamv0.User, int64, int64, error) {
found, err := s.store.ListUsers(ctx, ns, legacy.ListUserQuery{
Pagination: p,
})
if err != nil {
return nil, 0, 0, err
}
out := make([]iamv0.User, 0, len(found.Users))
for _, u := range found.Users {
if check(ns.Value, strconv.FormatInt(u.ID, 10)) {
out = append(out, toUserItem(&u, ns.Value))
if err != nil {
return nil, err
}
}
return out, found.Continue, found.RV, nil
}
users := make([]iamv0.User, 0, len(found.Users))
for _, u := range found.Users {
users = append(users, toUserItem(&u, ns.Value))
}
return &common.ListResponse[iamv0.User]{
Items: users,
RV: found.RV,
Continue: found.Continue,
}, nil
},
)
items, c, rv, err := list(p)
if err != nil {
return nil, err
}
outer:
for len(items) < int(p.Limit) && c != 0 {
var more []iamv0.User
more, c, _, err = list(common.Pagination{Limit: p.Limit, Continue: c})
if err != nil {
return nil, err
}
for _, u := range more {
if len(items) == int(p.Limit) {
break outer
}
items = append(items, u)
}
}
obj := &iamv0.UserList{Items: items}
obj.ListMeta.Continue = common.OptionalFormatInt(c)
obj.ListMeta.ResourceVersion = common.OptionalFormatInt(rv)
obj := &iamv0.UserList{Items: res.Items}
obj.ListMeta.Continue = common.OptionalFormatInt(res.Continue)
obj.ListMeta.ResourceVersion = common.OptionalFormatInt(res.RV)
return obj, nil
}
func (s *LegacyStore) listWithoutCheck(ctx context.Context, ns claims.NamespaceInfo, p common.Pagination) (runtime.Object, error) {
found, err := s.store.ListUsers(ctx, ns, legacy.ListUserQuery{
Pagination: p,
})
if err != nil {
return nil, err
}
list := &iamv0.UserList{}
for _, item := range found.Users {
list.Items = append(list.Items, toUserItem(&item, ns.Value))
}
list.ListMeta.Continue = common.OptionalFormatInt(found.Continue)
list.ListMeta.ResourceVersion = common.OptionalFormatInt(found.RV)
return list, nil
}
func (s *LegacyStore) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
ns, err := request.NamespaceInfoFrom(ctx, true)
if err != nil {
@@ -191,6 +131,7 @@ func toUserItem(u *user.User, ns string) iamv0.User {
Email: u.Email,
EmailVerified: u.EmailVerified,
Disabled: u.IsDisabled,
InternalID: u.ID,
},
}
obj, _ := utils.MetaAccessor(item)