Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create WindowsDesktops for matching DynamicWindowsDesktops #46991

Open
wants to merge 8 commits into
base: probakowski/register-resources-cache
Choose a base branch
from
2 changes: 1 addition & 1 deletion api/client/dynamicwindows/dynamicwindows.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (c *Client) GetDynamicWindowsDesktop(ctx context.Context, name string) (typ
return desktop, trace.Wrap(err)
}

func (c *Client) ListDynamicWindowsDesktop(ctx context.Context, pageSize int, pageToken string) ([]types.DynamicWindowsDesktop, string, error) {
func (c *Client) ListDynamicWindowsDesktops(ctx context.Context, pageSize int, pageToken string) ([]types.DynamicWindowsDesktop, string, error) {
resp, err := c.grpcClient.ListDynamicWindowsDesktops(ctx, &dynamicwindows.ListDynamicWindowsDesktopsRequest{
PageSize: int32(pageSize),
PageToken: pageToken,
Expand Down
3 changes: 3 additions & 0 deletions lib/auth/authclient/clt.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"errors"
"fmt"
"github.com/gravitational/teleport/api/client/dynamicwindows"
"net"
"net/url"
"time"
Expand Down Expand Up @@ -1594,6 +1595,8 @@ type ClientI interface {
types.WebSessionsGetter
types.WebTokensGetter

DynamicDesktopClient() *dynamicwindows.Client

// TrustClient returns a client to the Trust service.
TrustClient() trustpb.TrustServiceClient

Expand Down
90 changes: 90 additions & 0 deletions lib/srv/desktop/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"maps"
"net"
"net/netip"
"strings"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/gravitational/trace"
"github.com/sirupsen/logrus"

"github.com/gravitational/teleport"
apidefaults "github.com/gravitational/teleport/api/defaults"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/auth/windows"
Expand Down Expand Up @@ -302,3 +304,91 @@ func (s *WindowsService) ldapEntryToWindowsDesktop(ctx context.Context, entry *l
desktop.SetExpiry(s.cfg.Clock.Now().UTC().Add(apidefaults.ServerAnnounceTTL * 3))
return desktop, nil
}

// startDynamicReconciler starts resource watcher and reconciler that registers/unregisters Windows desktops
// according to the up-to-date list of dynamic Windows desktops resources.
func (s *WindowsService) startDynamicReconciler(ctx context.Context) (*services.DynamicWindowsDesktopWatcher, error) {
if len(s.cfg.ResourceMatchers) == 0 {
s.cfg.Logger.DebugContext(ctx, "Not starting dynamic desktop resource watcher.")
return nil, nil
}
s.cfg.Logger.DebugContext(ctx, "Starting dynamic desktop resource watcher.")
dynamicDesktopClient := s.cfg.AuthClient.DynamicDesktopClient()
watcher, err := services.NewDynamicWindowsDesktopWatcher(ctx, services.DynamicWindowsDesktopWatcherConfig{
DynamicWindowsDesktopGetter: dynamicDesktopClient,
ResourceWatcherConfig: services.ResourceWatcherConfig{
Component: teleport.ComponentWindowsDesktop,
Client: s.cfg.AccessPoint,
},
})
if err != nil {
return nil, trace.Wrap(err)
}

currentResources := make(map[string]types.WindowsDesktop)
var newResources map[string]types.WindowsDesktop

reconciler, err := services.NewReconciler(services.ReconcilerConfig[types.WindowsDesktop]{
Matcher: func(desktop types.WindowsDesktop) bool {
return services.MatchResourceLabels(s.cfg.ResourceMatchers, desktop.GetAllLabels())
},
GetCurrentResources: func() map[string]types.WindowsDesktop {
return currentResources
},
GetNewResources: func() map[string]types.WindowsDesktop {
return newResources
},
OnCreate: s.upsertDesktop,
OnUpdate: s.updateDesktop,
OnDelete: s.deleteDesktop,
})
if err != nil {
return nil, trace.Wrap(err)
}
go func() {
defer s.cfg.Logger.DebugContext(ctx, "DynamicWindowsDesktop resource watcher done.")
defer watcher.Close()
for {
select {
case desktops := <-watcher.DynamicWindowsDesktopsC:
newResources = make(map[string]types.WindowsDesktop)
for _, dynamicDesktop := range desktops {
desktop, err := s.toWindowsDesktop(dynamicDesktop)
if err != nil {
s.cfg.Logger.WarnContext(ctx, "Can't create desktop resource", "error", err)
continue
}
newResources[dynamicDesktop.GetName()] = desktop
}
if err := reconciler.Reconcile(ctx); err != nil {
s.cfg.Logger.WarnContext(ctx, "Reconciliation failed, will retry", "error", err)
continue
}
currentResources = newResources
case <-watcher.Done():
return
case <-ctx.Done():
return
}
}
}()
return watcher, nil
}

func (s *WindowsService) toWindowsDesktop(dynamicDesktop types.DynamicWindowsDesktop) (*types.WindowsDesktopV3, error) {
width, height := dynamicDesktop.GetScreenSize()
desktopLabels := dynamicDesktop.GetAllLabels()
labels := make(map[string]string, len(desktopLabels)+1)
maps.Copy(labels, desktopLabels)
labels[types.OriginLabel] = types.OriginDynamic
return types.NewWindowsDesktopV3(dynamicDesktop.GetName(), labels, types.WindowsDesktopSpecV3{
Addr: dynamicDesktop.GetAddr(),
Domain: dynamicDesktop.GetDomain(),
HostID: s.cfg.Heartbeat.HostUUID,
NonAD: dynamicDesktop.NonAD(),
ScreenSize: &types.Resolution{
Width: width,
Height: height,
},
})
}
4 changes: 4 additions & 0 deletions lib/srv/desktop/windows_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
return nil, trace.Wrap(err)
}

if _, err := s.startDynamicReconciler(ctx); err != nil {
return nil, trace.Wrap(err)
}

if len(s.cfg.DiscoveryBaseDN) > 0 {
if err := s.startDesktopDiscovery(); err != nil {
return nil, trace.Wrap(err)
Expand Down
Loading