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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user