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
51 changes: 51 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,57 @@ func (c *Client) GetDatabaseObjects(ctx context.Context) ([]*dbobjectv1.Database
return out, nil
}

// ListWindowsDesktops returns a page of registered Windows desktop hosts.
func (c *Client) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) {
resp, err := c.grpc.ListWindowsDesktops(ctx, &proto.ListWindowsDesktopsRequest{
Limit: int32(req.Limit),
StartKey: req.StartKey,
Labels: req.Labels,
PredicateExpression: req.PredicateExpression,
SearchKeywords: req.SearchKeywords,
WindowsDesktopFilter: req.WindowsDesktopFilter,
})
if err != nil {
return nil, trace.Wrap(err)
}

out := &types.ListWindowsDesktopsResponse{
Desktops: make([]types.WindowsDesktop, 0, len(resp.Desktops)),
NextKey: resp.NextKey,
}

for _, d := range resp.Desktops {
out.Desktops = append(out.Desktops, d)
}

return out, nil
}

// ListWindowsDesktopServices returns a page of Windows desktop services.
func (c *Client) ListWindowsDesktopServices(ctx context.Context, req types.ListWindowsDesktopServicesRequest) (*types.ListWindowsDesktopServicesResponse, error) {
resp, err := c.grpc.ListResources(ctx, &proto.ListResourcesRequest{
Limit: int32(req.Limit),
StartKey: req.StartKey,
Labels: req.Labels,
PredicateExpression: req.PredicateExpression,
SearchKeywords: req.SearchKeywords,
})
if err != nil {
return nil, trace.Wrap(err)
}

out := &types.ListWindowsDesktopServicesResponse{
DesktopServices: make([]types.WindowsDesktopService, 0, len(resp.Resources)),
NextKey: resp.NextKey,
}

for _, r := range resp.Resources {
out.DesktopServices = append(out.DesktopServices, r.GetWindowsDesktopService())
}

return out, nil
}

// GetWindowsDesktopServices returns all registered windows desktop services.
func (c *Client) GetWindowsDesktopServices(ctx context.Context) ([]types.WindowsDesktopService, error) {
resp, err := c.grpc.GetWindowsDesktopServices(ctx, &emptypb.Empty{})
Expand Down
2,903 changes: 1,851 additions & 1,052 deletions api/client/proto/authservice.pb.go

Large diffs are not rendered by default.

39 changes: 39 additions & 0 deletions api/client/proto/authservice_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions api/proto/teleport/legacy/client/proto/authservice.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1563,6 +1563,35 @@ message DeleteWindowsDesktopServiceRequest {
string Name = 1 [(gogoproto.jsontag) = "name"];
}

// ListWindowsDesktopsRequest is a request for a page of registered Windows desktop hosts.
message ListWindowsDesktopsRequest {
// Limit is the maximum amount of resources to retrieve.
int32 limit = 1;
// StartKey is used to start listing resources from a specific spot. It
// should be set to the previous NextKey value if using pagination, or
// left empty.
string start_key = 2;
// Labels is a label-based matcher if non-empty.
map<string, string> labels = 3;
// PredicateExpression defines boolean conditions that will be matched against the resource.
string predicate_expression = 4;
// SearchKeywords is a list of search keywords to match against resource field values.
repeated string search_keywords = 5;
// WindowsDesktopFilter specifies windows desktop specific filters.
types.WindowsDesktopFilter windows_desktop_filter = 6 [
(gogoproto.nullable) = false,
(gogoproto.jsontag) = "windows_desktop_filter,omitempty"
];
}

// ListWindowsDesktopsResponse contains a page of registered Windows desktop hosts.
message ListWindowsDesktopsResponse {
// Desktops is a list of Windows desktop hosts.
repeated types.WindowsDesktopV3 desktops = 1;
// NextKey is the key for the next page of SAML IdP service providers.
string next_key = 2;
}

// GetWindowsDesktopsResponse contains all registered Windows desktop hosts.
message GetWindowsDesktopsResponse {
// Servers is a list of Windows desktop hosts.
Expand Down Expand Up @@ -3355,6 +3384,8 @@ service AuthService {

// GetWindowsDesktops returns all registered Windows desktop hosts matching the supplied filter.
rpc GetWindowsDesktops(types.WindowsDesktopFilter) returns (GetWindowsDesktopsResponse);
// ListWindowsDesktops returns a page of registered Windows desktop hosts.
rpc ListWindowsDesktops(ListWindowsDesktopsRequest) returns (ListWindowsDesktopsResponse);
// CreateWindowsDesktop registers a new Windows desktop host.
rpc CreateWindowsDesktop(types.WindowsDesktopV3) returns (google.protobuf.Empty);
// UpdateWindowsDesktop updates an existing Windows desktop host.
Expand Down
13 changes: 5 additions & 8 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5731,21 +5731,18 @@ func (a *Server) UpsertWindowsDesktop(ctx context.Context, desktop types.Windows
return nil
}

func (a *Server) streamWindowsDesktops(ctx context.Context, startKey string) stream.Stream[types.WindowsDesktop] {
func (a *Server) streamWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) stream.Stream[types.WindowsDesktop] {
var done bool
return stream.PageFunc(func() ([]types.WindowsDesktop, error) {
if done {
return nil, io.EOF
}
resp, err := a.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{
Limit: 50,
StartKey: startKey,
})
resp, err := a.ListWindowsDesktops(ctx, req)
if err != nil {
return nil, trace.Wrap(err)
}
startKey = resp.NextKey
done = startKey == ""
req.StartKey = resp.NextKey
done = req.StartKey == ""
return resp.Desktops, nil
})
}
Expand Down Expand Up @@ -5780,7 +5777,7 @@ func (a *Server) desktopsLimitExceeded(ctx context.Context) (bool, error) {
}

desktops := stream.FilterMap(
a.streamWindowsDesktops(ctx, ""),
a.streamWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{Limit: 50}),
func(d types.WindowsDesktop) (struct{}, bool) {
return struct{}{}, d.NonAD()
},
Expand Down
34 changes: 34 additions & 0 deletions lib/auth/auth_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -6757,6 +6757,40 @@ func (a *ServerWithRoles) GetWindowsDesktops(ctx context.Context, filter types.W
return filtered, nil
}

// ListWindowsDesktops returns a page of registered Windows desktop hosts.
func (a *ServerWithRoles) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) {
if err := a.action(apidefaults.Namespace, types.KindWindowsDesktop, types.VerbList, types.VerbRead); err != nil {
return nil, trace.Wrap(err)
}

var resp types.ListWindowsDesktopsResponse
desktopStream := stream.FilterMap(a.authServer.streamWindowsDesktops(ctx, req), func(d types.WindowsDesktop) (types.WindowsDesktop, bool) {
if a.hasBuiltinRole(types.RoleAdmin, types.RoleProxy, types.RoleWindowsDesktop) {
return d, true
}

if err := a.checkAccessToWindowsDesktop(d); err == nil {
return d, true
}

return nil, false
})

limit := cmp.Or(req.Limit, apidefaults.DefaultChunkSize)
for desktopStream.Next() {
desktop := desktopStream.Item()
if len(resp.Desktops) == limit {
resp.NextKey = desktop.GetHostID() + "/" + desktop.GetName()
desktopStream.Done()
break
}

resp.Desktops = append(resp.Desktops, desktop)
}

return &resp, nil
}

// CreateWindowsDesktop creates a new windows desktop host.
func (a *ServerWithRoles) CreateWindowsDesktop(ctx context.Context, s types.WindowsDesktop) error {
if err := a.action(apidefaults.Namespace, types.KindWindowsDesktop, types.VerbCreate); err != nil {
Expand Down
10 changes: 0 additions & 10 deletions lib/auth/authclient/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,16 +406,6 @@ func (c *Client) DeleteAllRoles(context.Context) error {
return trace.NotImplemented(notImplementedMessage)
}

// ListWindowsDesktops not implemented: can only be called locally.
func (c *Client) ListWindowsDesktops(ctx context.Context, req types.ListWindowsDesktopsRequest) (*types.ListWindowsDesktopsResponse, error) {
return nil, trace.NotImplemented(notImplementedMessage)
}

// ListWindowsDesktopServices not implemented: can only be called locally.
func (c *Client) ListWindowsDesktopServices(ctx context.Context, req types.ListWindowsDesktopServicesRequest) (*types.ListWindowsDesktopServicesResponse, error) {
return nil, trace.NotImplemented(notImplementedMessage)
}

// DeleteAllUsers not implemented: can only be called locally.
func (c *Client) DeleteAllUsers(ctx context.Context) error {
return trace.NotImplemented(notImplementedMessage)
Expand Down
33 changes: 33 additions & 0 deletions lib/auth/grpcserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -3956,6 +3956,39 @@ func (g *GRPCServer) GetWindowsDesktops(ctx context.Context, filter *types.Windo
}, nil
}

// ListWindowsDesktops returns a page of registered Windows desktop hosts.
func (g *GRPCServer) ListWindowsDesktops(ctx context.Context, req *authpb.ListWindowsDesktopsRequest) (*authpb.ListWindowsDesktopsResponse, error) {
auth, err := g.authenticate(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

resp, err := auth.ListWindowsDesktops(ctx, types.ListWindowsDesktopsRequest{
WindowsDesktopFilter: req.WindowsDesktopFilter,
Limit: int(req.Limit),
StartKey: req.StartKey,
PredicateExpression: req.PredicateExpression,
Labels: req.Labels,
SearchKeywords: req.SearchKeywords,
})
if err != nil {
return nil, trace.Wrap(err)
}

out := &authpb.ListWindowsDesktopsResponse{
Desktops: make([]*types.WindowsDesktopV3, 0, len(resp.Desktops)),
NextKey: resp.NextKey,
}

for _, d := range resp.Desktops {
if v3, ok := d.(*types.WindowsDesktopV3); ok {
out.Desktops = append(out.Desktops, v3)
}
}

return out, nil
}

// CreateWindowsDesktop registers a new Windows desktop host.
func (g *GRPCServer) CreateWindowsDesktop(ctx context.Context, desktop *types.WindowsDesktopV3) (*emptypb.Empty, error) {
auth, err := g.authenticate(ctx)
Expand Down
44 changes: 42 additions & 2 deletions lib/cache/collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -2314,7 +2314,21 @@ var _ executor[types.Lock, services.LockGetter] = lockExecutor{}
type windowsDesktopServicesExecutor struct{}

func (windowsDesktopServicesExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WindowsDesktopService, error) {
return cache.Presence.GetWindowsDesktopServices(ctx)
resources, err := client.GetResourcesWithFilters(ctx, cache.Presence, proto.ListResourcesRequest{ResourceType: types.KindWindowsDesktopService})
if err != nil {
return nil, trace.Wrap(err)
}

desktopSvcs := make([]types.WindowsDesktopService, 0, len(resources))
for _, resource := range resources {
desktopSvc, ok := resource.(types.WindowsDesktopService)
if !ok {
return nil, trace.BadParameter("unexpected resource %T", resource)
}
desktopSvcs = append(desktopSvcs, desktopSvc)
}

return desktopSvcs, nil
}

func (windowsDesktopServicesExecutor) upsert(ctx context.Context, cache *Cache, resource types.WindowsDesktopService) error {
Expand Down Expand Up @@ -2361,7 +2375,33 @@ var _ executor[types.WindowsDesktopService, windowsDesktopServiceGetter] = windo
type windowsDesktopsExecutor struct{}

func (windowsDesktopsExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]types.WindowsDesktop, error) {
return cache.WindowsDesktops.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{})
var start string
var desktops []types.WindowsDesktop
for {
req := types.ListWindowsDesktopsRequest{
// A non zero limit is required by older versions.
Limit: apidefaults.DefaultChunkSize,
StartKey: start,
}

resp, err := cache.WindowsDesktops.ListWindowsDesktops(ctx, req)
if err != nil {
// TODO(tross): DELETE in V21.0.0
if trace.IsNotImplemented(err) {
return cache.WindowsDesktops.GetWindowsDesktops(ctx, types.WindowsDesktopFilter{})
}

return nil, trace.Wrap(err)
}

desktops = append(desktops, resp.Desktops...)
start = resp.NextKey
if resp.NextKey == "" {
break
}
}

return desktops, nil
}

func (windowsDesktopsExecutor) upsert(ctx context.Context, cache *Cache, resource types.WindowsDesktop) error {
Expand Down
Loading
Loading