Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 40 additions & 31 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -1472,31 +1472,18 @@ func (a *ServerWithRoles) checkUnifiedAccess(resource types.ResourceWithLabels,

// ListUnifiedResources returns a paginated list of unified resources filtered by user access.
func (a *ServerWithRoles) ListUnifiedResources(ctx context.Context, req *proto.ListUnifiedResourcesRequest) (*proto.ListUnifiedResourcesResponse, error) {
// Fetch full list of resources in the backend.
var (
unifiedResources types.ResourcesWithLabels
nextKey string
)

filter := services.MatchResourceFilter{
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
Kinds: req.Kinds,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
Kinds: req.Kinds,
}

// If a predicate expression was provided, evaluate it with an empty
// server to determine if the expression is valid before attempting
// to do any listing.
if filter.PredicateExpression != "" {
parser, err := services.NewResourceParser(&types.ServerV2{})
if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}

if _, err := parser.EvalBoolPredicate(filter.PredicateExpression); err != nil {
return nil, trace.BadParameter("failed to parse predicate expression: %s", err.Error())
}
filter.PredicateExpression = expression
}

// Populate resourceAccessMap with any access errors the user has for each possible
Expand Down Expand Up @@ -1562,6 +1549,11 @@ func (a *ServerWithRoles) ListUnifiedResources(ctx context.Context, req *proto.L
return nil, trace.Wrap(err)
}

// Fetch full list of resources in the backend.
var (
unifiedResources types.ResourcesWithLabels
nextKey string
)
if req.PinnedOnly {
prefs, err := a.authServer.GetUserPreferences(ctx, a.context.User.GetName())
if err != nil {
Expand Down Expand Up @@ -1823,11 +1815,19 @@ func (a *ServerWithRoles) ListResources(ctx context.Context, req proto.ListResou
// `ListResources`) to ensure that it will be applied only to resources
// the user has access to.
filter := services.MatchResourceFilter{
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
filter.PredicateExpression = expression
}

req.Labels = nil
req.SearchKeywords = nil
req.PredicateExpression = ""
Expand Down Expand Up @@ -2056,15 +2056,24 @@ func (a *ServerWithRoles) listResourcesWithSort(ctx context.Context, req proto.L
return nil, trace.NotImplemented("resource type %q is not supported for listResourcesWithSort", req.ResourceType)
}

params := local.FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
StartKey: req.StartKey,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
params.PredicateExpression = expression
}

// Apply request filters and get pagination info.
resp, err := local.FakePaginate(resources, local.FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
StartKey: req.StartKey,
})
resp, err := local.FakePaginate(resources, params)
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
25 changes: 17 additions & 8 deletions lib/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -3048,14 +3048,23 @@ func (c *Cache) ListResources(ctx context.Context, req proto.ListResourcesReques
return nil, trace.Wrap(err)
}

return local.FakePaginate(servers.AsResources(), local.FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
StartKey: req.StartKey,
})
params := local.FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
StartKey: req.StartKey,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
params.PredicateExpression = expression
}

return local.FakePaginate(servers.AsResources(), params)
}
}

Expand Down
46 changes: 30 additions & 16 deletions lib/kube/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,10 +216,17 @@ func (s *Server) listKubernetesResources(

limit := int(req.Limit)
filter := services.MatchResourceFilter{
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
filter.PredicateExpression = expression
}

rsp := &proto.ListKubernetesResourcesResponse{}
Expand Down Expand Up @@ -525,19 +532,26 @@ func (s *Server) listResourcesUsingFakePagination(
return nil, trace.Wrap(err)
}
}

// map the request to the fake pagination request.
params := local.FakePaginateParams{
StartKey: req.StartKey,
Limit: req.Limit,
ResourceType: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
params.PredicateExpression = expression
}

// Apply request filters and get pagination info.
fakeRsp, err := local.FakePaginate(
sortedClusters.AsResources(),
// map the request to the fake pagination request.
local.FakePaginateParams{
StartKey: req.StartKey,
Limit: req.Limit,
ResourceType: req.ResourceType,
Labels: req.Labels,
PredicateExpression: req.PredicateExpression,
SearchKeywords: req.SearchKeywords,
},
)
fakeRsp, err := local.FakePaginate(sortedClusters.AsResources(), params)
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
10 changes: 6 additions & 4 deletions lib/services/fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,13 @@ func FuzzParserEvalBoolPredicate(f *testing.F) {
})
require.NoError(t, err)

parser, err := NewResourceParser(resource)
require.NoError(t, err)

require.NotPanics(t, func() {
parser.EvalBoolPredicate(expr)
parser, err := NewResourceExpression(expr)
if err != nil {
return
}

parser.Evaluate(resource)
})
})
}
30 changes: 22 additions & 8 deletions lib/services/local/desktops.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,17 @@ func (s *WindowsDesktopService) ListWindowsDesktops(ctx context.Context, req typ
rangeStart := backend.Key(windowsDesktopsPrefix, req.StartKey)
rangeEnd := backend.RangeEnd(backend.ExactKey(windowsDesktopsPrefix))
filter := services.MatchResourceFilter{
ResourceKind: types.KindWindowsDesktop,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
ResourceKind: types.KindWindowsDesktop,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
filter.PredicateExpression = expression
}

// Get most limit+1 results to determine if there will be a next key.
Expand Down Expand Up @@ -245,10 +252,17 @@ func (s *WindowsDesktopService) ListWindowsDesktopServices(ctx context.Context,
rangeStart := backend.Key(windowsDesktopServicesPrefix, req.StartKey)
rangeEnd := backend.RangeEnd(backend.ExactKey(windowsDesktopServicesPrefix))
filter := services.MatchResourceFilter{
ResourceKind: types.KindWindowsDesktopService,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
ResourceKind: types.KindWindowsDesktopService,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
filter.PredicateExpression = expression
}

// Get most limit+1 results to determine if there will be a next key.
Expand Down
43 changes: 30 additions & 13 deletions lib/services/local/presence.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/teleport/lib/utils/typical"
)

// PresenceService records and reports the presence of all components
Expand Down Expand Up @@ -1587,10 +1588,17 @@ func (s *PresenceService) listResources(ctx context.Context, req proto.ListResou
rangeStart := backend.Key(append(keyPrefix, req.StartKey)...)
rangeEnd := backend.RangeEnd(backend.ExactKey(keyPrefix...))
filter := services.MatchResourceFilter{
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
ResourceKind: req.ResourceType,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
filter.PredicateExpression = expression
}

// Get most limit+1 results to determine if there will be a next key.
Expand Down Expand Up @@ -1724,14 +1732,23 @@ func (s *PresenceService) listResourcesWithSort(ctx context.Context, req proto.L
return nil, trace.NotImplemented("resource type %q is not supported for ListResourcesWithSort", req.ResourceType)
}

return FakePaginate(resources, FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
StartKey: req.StartKey,
})
params := FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
StartKey: req.StartKey,
}

if req.PredicateExpression != "" {
expression, err := services.NewResourceExpression(req.PredicateExpression)
if err != nil {
return nil, trace.Wrap(err)
}
params.PredicateExpression = expression
}

return FakePaginate(resources, params)
}

// FakePaginateParams is used in FakePaginate to help filter down listing of resources into pages
Expand All @@ -1751,7 +1768,7 @@ type FakePaginateParams struct {
// Labels is a label-based matcher if non-empty.
Labels map[string]string
// PredicateExpression defines boolean conditions that will be matched against the resource.
PredicateExpression string
PredicateExpression typical.Expression[types.ResourceWithLabels, bool]
// SearchKeywords is a list of search keywords to match against resource field values.
SearchKeywords []string
// SortBy describes which resource field and which direction to sort by.
Expand Down
11 changes: 5 additions & 6 deletions lib/services/local/presence_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -862,12 +862,11 @@ func TestListResources_Helpers(t *testing.T) {
require.NoError(t, err)

return FakePaginate(types.Servers(nodes).AsResources(), FakePaginateParams{
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
PredicateExpression: req.PredicateExpression,
StartKey: req.StartKey,
ResourceType: req.ResourceType,
Limit: req.Limit,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
StartKey: req.StartKey,
})
},
},
Expand Down
Loading