mirror of
https://github.com/gravitational/teleport
synced 2024-10-19 16:53:57 +00:00
Add non_ad_hosts to windows desktop service config (#19806)
Co-authored-by: Zac Bergquist <zac.bergquist@goteleport.com> Co-authored-by: Isaiah Becker-Mayer <isaiah@goteleport.com>
This commit is contained in:
parent
ab51a9b5ea
commit
9ecfca3c73
|
@ -4205,6 +4205,9 @@ message WindowsDesktopSpecV3 {
|
|||
string Domain = 2 [(gogoproto.jsontag) = "domain"];
|
||||
// HostID is the ID of the host the Windows Desktop Service proxying the desktop.
|
||||
string HostID = 3 [(gogoproto.jsontag) = "host_id"];
|
||||
// NonAD marks this desktop as a standalone host that is
|
||||
// not joined to an Active Directory domain.
|
||||
bool NonAD = 4 [(gogoproto.jsontag) = "non_ad"];
|
||||
}
|
||||
|
||||
// RegisterUsingTokenRequest is a request to register with the auth server using
|
||||
|
|
|
@ -370,6 +370,9 @@ const (
|
|||
// that the resource originates from.
|
||||
OriginLabel = TeleportNamespace + "/origin"
|
||||
|
||||
// ADLabel is a resource metadata label name used to identify if resource is part of Active Directory
|
||||
ADLabel = TeleportNamespace + "/ad"
|
||||
|
||||
// OriginDefaults is an origin value indicating that the resource was
|
||||
// constructed as a default value.
|
||||
OriginDefaults = "defaults"
|
||||
|
|
|
@ -155,6 +155,9 @@ type WindowsDesktop interface {
|
|||
GetDomain() string
|
||||
// GetHostID returns the ID of the Windows Desktop Service reporting the desktop.
|
||||
GetHostID() string
|
||||
// NonAD checks whether this is a standalone host that
|
||||
// is not joined to an Active Directory domain.
|
||||
NonAD() bool
|
||||
}
|
||||
|
||||
var _ WindowsDesktop = &WindowsDesktopV3{}
|
||||
|
@ -194,6 +197,11 @@ func (d *WindowsDesktopV3) CheckAndSetDefaults() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// NonAD checks whether host is part of Active Directory
|
||||
func (d *WindowsDesktopV3) NonAD() bool {
|
||||
return d.Spec.NonAD
|
||||
}
|
||||
|
||||
// GetAddr returns the network address of this host.
|
||||
func (d *WindowsDesktopV3) GetAddr() string {
|
||||
return d.Spec.Addr
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1543,6 +1543,10 @@ func applyMetricsConfig(fc *FileConfig, cfg *service.Config) error {
|
|||
|
||||
// applyWindowsDesktopConfig applies file configuration for the "windows_desktop_service" section.
|
||||
func applyWindowsDesktopConfig(fc *FileConfig, cfg *service.Config) error {
|
||||
if err := fc.WindowsDesktop.Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
|
||||
cfg.WindowsDesktop.Enabled = true
|
||||
|
||||
if fc.WindowsDesktop.ListenAddress != "" {
|
||||
|
@ -1581,6 +1585,10 @@ func applyWindowsDesktopConfig(fc *FileConfig, cfg *service.Config) error {
|
|||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
cfg.WindowsDesktop.NonADHosts, err = utils.AddrsFromStrings(fc.WindowsDesktop.NonADHosts, defaults.RDPListenPort)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if fc.WindowsDesktop.LDAP.DEREncodedCAFile != "" && fc.WindowsDesktop.LDAP.PEMEncodedCACert != "" {
|
||||
return trace.BadParameter("WindowsDesktopService can not use both der_ca_file and ldap_ca_cert")
|
||||
}
|
||||
|
|
|
@ -2140,6 +2140,94 @@ func TestWindowsDesktopService(t *testing.T) {
|
|||
fc.WindowsDesktop.Discovery.LabelAttributes = []string{"this?is not* a valid key 🚨"}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "NOK - hosts specified but ldap not specified",
|
||||
expectError: require.Error,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Hosts = []string{"127.0.0.1:3389"}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - hosts specified and ldap specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Hosts = []string{"127.0.0.1:3389"}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "something",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - no hosts specified and ldap not specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Hosts = []string{}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - no hosts specified and ldap specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Hosts = []string{}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "something",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "NOK - discovery specified but ldap not specified",
|
||||
expectError: require.Error,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Discovery = LDAPDiscoveryConfig{
|
||||
BaseDN: "something",
|
||||
}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - discovery specified and ldap specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Discovery = LDAPDiscoveryConfig{
|
||||
BaseDN: "something",
|
||||
}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "something",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - discovery not specified and ldap not specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Discovery = LDAPDiscoveryConfig{
|
||||
BaseDN: "",
|
||||
}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - discovery not specified and ldap specified",
|
||||
expectError: require.NoError,
|
||||
mutate: func(fc *FileConfig) {
|
||||
fc.WindowsDesktop.Discovery = LDAPDiscoveryConfig{
|
||||
BaseDN: "",
|
||||
}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "something",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "OK - valid config",
|
||||
expectError: require.NoError,
|
||||
|
@ -2147,6 +2235,9 @@ func TestWindowsDesktopService(t *testing.T) {
|
|||
fc.WindowsDesktop.EnabledFlag = "yes"
|
||||
fc.WindowsDesktop.ListenAddress = "0.0.0.0:3028"
|
||||
fc.WindowsDesktop.Hosts = []string{"127.0.0.1:3389"}
|
||||
fc.WindowsDesktop.LDAP = LDAPConfig{
|
||||
Addr: "something",
|
||||
}
|
||||
fc.WindowsDesktop.HostLabels = []WindowsHostLabelRule{
|
||||
{Match: ".*", Labels: map[string]string{"key": "value"}},
|
||||
}
|
||||
|
|
|
@ -1941,15 +1941,34 @@ type WindowsDesktopService struct {
|
|||
LDAP LDAPConfig `yaml:"ldap"`
|
||||
// Discovery configures desktop discovery via LDAP.
|
||||
Discovery LDAPDiscoveryConfig `yaml:"discovery,omitempty"`
|
||||
// Hosts is a list of static Windows hosts connected to this service in
|
||||
// gateway mode.
|
||||
// Hosts is a list of static, AD-connected Windows hosts. This gives users
|
||||
// a way to specify AD-connected hosts that won't be found by the filters
|
||||
// specified in `discovery` (or if `discovery` is omitted).
|
||||
Hosts []string `yaml:"hosts,omitempty"`
|
||||
// NonADHosts is a list of standalone Windows hosts that are not
|
||||
// jointed to an Active Directory domain.
|
||||
NonADHosts []string `yaml:"non_ad_hosts,omitempty"`
|
||||
// HostLabels optionally applies labels to Windows hosts for RBAC.
|
||||
// A host can match multiple rules and will get a union of all
|
||||
// the matched labels.
|
||||
HostLabels []WindowsHostLabelRule `yaml:"host_labels,omitempty"`
|
||||
}
|
||||
|
||||
// Check checks whether the WindowsDesktopService is valid or not
|
||||
func (wds *WindowsDesktopService) Check() error {
|
||||
if len(wds.Hosts) > 0 && wds.LDAP.Addr == "" {
|
||||
return trace.BadParameter("if hosts are specified in the windows_desktop_service, " +
|
||||
"the ldap configuration for their corresponding Active Directory domain controller must also be specified")
|
||||
}
|
||||
|
||||
if wds.Discovery.BaseDN != "" && wds.LDAP.Addr == "" {
|
||||
return trace.BadParameter("if discovery is specified in the windows_desktop_service, " +
|
||||
"ldap configuration must also be specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WindowsHostLabelRule describes how a set of labels should be a applied to
|
||||
// a Windows host.
|
||||
type WindowsHostLabelRule struct {
|
||||
|
|
|
@ -1301,7 +1301,15 @@ type WindowsDesktopConfig struct {
|
|||
|
||||
// Hosts is an optional list of static Windows hosts to expose through this
|
||||
// service.
|
||||
// Hosts is an optional list of static, AD-connected Windows hosts. This gives users
|
||||
// a way to specify AD-connected hosts that won't be found by the filters
|
||||
// specified in Discovery (or if Discovery is omitted).
|
||||
Hosts []utils.NetAddr
|
||||
|
||||
// NonADHosts is an optional list of static Windows hosts to expose through this
|
||||
// service. These hosts are not part of Active Directory.
|
||||
NonADHosts []utils.NetAddr
|
||||
|
||||
// ConnLimiter limits the connection and request rates.
|
||||
ConnLimiter limiter.Config
|
||||
// HostLabels specifies rules that are used to apply labels to Windows hosts.
|
||||
|
|
|
@ -219,6 +219,7 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus.
|
|||
HostUUID: cfg.HostUUID,
|
||||
PublicAddr: publicAddr,
|
||||
StaticHosts: cfg.WindowsDesktop.Hosts,
|
||||
NonADHosts: cfg.WindowsDesktop.NonADHosts,
|
||||
OnHeartbeat: process.onHeartbeat(teleport.ComponentWindowsDesktop),
|
||||
},
|
||||
ShowDesktopWallpaper: cfg.WindowsDesktop.ShowDesktopWallpaper,
|
||||
|
|
|
@ -193,7 +193,9 @@ func (s *WindowsService) lookupDesktop(ctx context.Context, hostname string) (ad
|
|||
if err == nil && len(addrs) > 0 {
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
if s.dnsResolver == nil {
|
||||
return nil, trace.NewAggregate(err, trace.Errorf("DNS lookup for %v failed and there's no LDAP server to fallback to", hostname))
|
||||
}
|
||||
s.cfg.Log.WithError(err).Debugf("DNS lookup for %v failed, falling back to LDAP server", hostname)
|
||||
return s.dnsResolver.LookupHost(ctx, hostname)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -106,6 +107,7 @@ type WindowsService struct {
|
|||
lc *windows.LDAPClient
|
||||
|
||||
mu sync.Mutex // mu protects the fields that follow
|
||||
ldapConfigured bool
|
||||
ldapInitialized bool
|
||||
ldapCertRenew *time.Timer
|
||||
|
||||
|
@ -165,6 +167,7 @@ type WindowsServiceConfig struct {
|
|||
// user-selected wallpaper vs a system-default, single-color wallpaper.
|
||||
ShowDesktopWallpaper bool
|
||||
// LDAPConfig contains parameters for connecting to an LDAP server.
|
||||
// LDAP functionality is disabled if Addr is empty.
|
||||
windows.LDAPConfig
|
||||
// DiscoveryBaseDN is the base DN for searching for Windows Desktops.
|
||||
// Desktop discovery is disabled if this field is empty.
|
||||
|
@ -192,8 +195,10 @@ type HeartbeatConfig struct {
|
|||
PublicAddr string
|
||||
// OnHeartbeat is called after each heartbeat attempt.
|
||||
OnHeartbeat func(error)
|
||||
// StaticHosts is an optional list of static Windows hosts to register.
|
||||
// StaticHosts is an optional list of AD-connected static Windows hosts to register.
|
||||
StaticHosts []utils.NetAddr
|
||||
// NonADHosts is an optional list of static Windows hosts to register, that are not part of Active Directory.
|
||||
NonADHosts []utils.NetAddr
|
||||
}
|
||||
|
||||
func (cfg *WindowsServiceConfig) checkAndSetDiscoveryDefaults() error {
|
||||
|
@ -246,8 +251,10 @@ func (cfg *WindowsServiceConfig) CheckAndSetDefaults() error {
|
|||
if err := cfg.Heartbeat.CheckAndSetDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if err := cfg.LDAPConfig.Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
if cfg.LDAPConfig.Addr != "" {
|
||||
if err := cfg.LDAPConfig.Check(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
}
|
||||
if err := cfg.checkAndSetDiscoveryDefaults(); err != nil {
|
||||
return trace.Wrap(err)
|
||||
|
@ -297,14 +304,26 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
|
|||
return nil, trace.Wrap(err, "fetching cluster name")
|
||||
}
|
||||
|
||||
// Here we assume the LDAP server is an Active Directory Domain Controller,
|
||||
// which means it should also be a DNS server that can resolve Windows hosts.
|
||||
dnsServer, _, err := net.SplitHostPort(cfg.LDAPConfig.Addr)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
var resolver *net.Resolver
|
||||
if cfg.LDAPConfig.Addr != "" {
|
||||
// Here we assume the LDAP server is an Active Directory Domain Controller,
|
||||
// which means it should also be a DNS server that can resolve Windows hosts.
|
||||
dnsServer, _, err := net.SplitHostPort(cfg.LDAPConfig.Addr)
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
dnsAddr := net.JoinHostPort(dnsServer, "53")
|
||||
cfg.Log.Debugln("DNS lookups will be performed against", dnsAddr)
|
||||
resolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
// Ignore the address provided, and always explicitly dial
|
||||
// the domain controller.
|
||||
d := net.Dialer{Timeout: dnsDialTimeout}
|
||||
return d.DialContext(ctx, network, dnsAddr)
|
||||
},
|
||||
}
|
||||
}
|
||||
dnsAddr := net.JoinHostPort(dnsServer, "53")
|
||||
cfg.Log.Debugln("DNS lookups will be performed against", dnsAddr)
|
||||
|
||||
ctx, close := context.WithCancel(context.Background())
|
||||
s := &WindowsService{
|
||||
|
@ -313,15 +332,7 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
|
|||
AccessPoint: cfg.AccessPoint,
|
||||
AcceptedUsage: []string{teleport.UsageWindowsDesktopOnly},
|
||||
},
|
||||
dnsResolver: &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
// Ignore the address provided, and always explicitly dial
|
||||
// the domain controller.
|
||||
d := net.Dialer{Timeout: dnsDialTimeout}
|
||||
return d.DialContext(ctx, network, dnsAddr)
|
||||
},
|
||||
},
|
||||
dnsResolver: resolver,
|
||||
lc: &windows.LDAPClient{Cfg: cfg.LDAPConfig},
|
||||
clusterName: clusterName.GetClusterName(),
|
||||
closeCtx: ctx,
|
||||
|
@ -337,11 +348,14 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
|
|||
LC: s.lc,
|
||||
})
|
||||
|
||||
// initialize LDAP - if this fails it will automatically schedule a retry.
|
||||
// we don't want to return an error in this case, because failure to start
|
||||
// the service brings down the entire Teleport process
|
||||
if err := s.initializeLDAP(); err != nil {
|
||||
s.cfg.Log.WithError(err).Error("initializing LDAP client, will retry")
|
||||
if s.cfg.LDAPConfig.Addr != "" {
|
||||
s.ldapConfigured = true
|
||||
// initialize LDAP - if this fails it will automatically schedule a retry.
|
||||
// we don't want to return an error in this case, because failure to start
|
||||
// the service brings down the entire Teleport process
|
||||
if err := s.initializeLDAP(); err != nil {
|
||||
s.cfg.Log.WithError(err).Error("initializing LDAP client, will retry")
|
||||
}
|
||||
}
|
||||
|
||||
ok := false
|
||||
|
@ -374,7 +388,7 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
|
|||
if err := s.startDesktopDiscovery(); err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
} else if len(s.cfg.Heartbeat.StaticHosts) == 0 {
|
||||
} else if len(s.cfg.Heartbeat.StaticHosts) == 0 && len(s.cfg.Heartbeat.NonADHosts) == 0 {
|
||||
s.cfg.Log.Warnln("desktop discovery via LDAP is disabled, and no hosts are defined in the configuration; there will be no Windows desktops available to connect")
|
||||
} else {
|
||||
s.cfg.Log.Infoln("desktop discovery via LDAP is disabled, set 'base_dn' to enable")
|
||||
|
@ -570,30 +584,42 @@ func (s *WindowsService) startServiceHeartbeat() error {
|
|||
// service itself is running.
|
||||
func (s *WindowsService) startStaticHostHeartbeats() error {
|
||||
for _, host := range s.cfg.Heartbeat.StaticHosts {
|
||||
heartbeat, err := srv.NewHeartbeat(srv.HeartbeatConfig{
|
||||
Context: s.closeCtx,
|
||||
Component: teleport.ComponentWindowsDesktop,
|
||||
Mode: srv.HeartbeatModeWindowsDesktop,
|
||||
Announcer: s.cfg.AccessPoint,
|
||||
GetServerInfo: s.staticHostHeartbeatInfo(host, s.cfg.HostLabelsFn),
|
||||
KeepAlivePeriod: apidefaults.ServerKeepAliveTTL(),
|
||||
AnnouncePeriod: apidefaults.ServerAnnounceTTL/2 + utils.RandomDuration(apidefaults.ServerAnnounceTTL/10),
|
||||
CheckPeriod: defaults.HeartbeatCheckPeriod,
|
||||
ServerTTL: apidefaults.ServerAnnounceTTL,
|
||||
OnHeartbeat: s.cfg.Heartbeat.OnHeartbeat,
|
||||
})
|
||||
if err != nil {
|
||||
if err := s.startStaticHostHeartbeat(host, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, host := range s.cfg.Heartbeat.NonADHosts {
|
||||
if err := s.startStaticHostHeartbeat(host, true); err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
go func() {
|
||||
if err := heartbeat.Run(); err != nil {
|
||||
s.cfg.Log.WithError(err).Error("Heartbeat ended with error")
|
||||
}
|
||||
}()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *WindowsService) startStaticHostHeartbeat(host utils.NetAddr, nonAD bool) error {
|
||||
heartbeat, err := srv.NewHeartbeat(srv.HeartbeatConfig{
|
||||
Context: s.closeCtx,
|
||||
Component: teleport.ComponentWindowsDesktop,
|
||||
Mode: srv.HeartbeatModeWindowsDesktop,
|
||||
Announcer: s.cfg.AccessPoint,
|
||||
GetServerInfo: s.staticHostHeartbeatInfo(host, s.cfg.HostLabelsFn, nonAD),
|
||||
KeepAlivePeriod: apidefaults.ServerKeepAliveTTL(),
|
||||
AnnouncePeriod: apidefaults.ServerAnnounceTTL/2 + utils.RandomDuration(apidefaults.ServerAnnounceTTL/10),
|
||||
CheckPeriod: defaults.HeartbeatCheckPeriod,
|
||||
ServerTTL: apidefaults.ServerAnnounceTTL,
|
||||
OnHeartbeat: s.cfg.Heartbeat.OnHeartbeat,
|
||||
})
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
go func() {
|
||||
if err := heartbeat.Run(); err != nil {
|
||||
s.cfg.Log.WithError(err).Error("Heartbeat ended with error")
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Close instructs the server to stop accepting new connections and abort all
|
||||
// established ones. Close does not wait for the connections to be finished.
|
||||
func (s *WindowsService) Close() error {
|
||||
|
@ -635,6 +661,20 @@ func (s *WindowsService) Serve(plainLis net.Listener) error {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *WindowsService) readyForConnections() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// If LDAP was not configured, we assume all hosts are non-AD
|
||||
// and the server can accept connections right away.
|
||||
if !s.ldapConfigured {
|
||||
return true
|
||||
}
|
||||
|
||||
// If LDAP was configured, then we need to wait for it to be initialized
|
||||
// before accepting connections.
|
||||
return s.ldapInitialized
|
||||
}
|
||||
|
||||
func (s *WindowsService) ldapReady() bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
@ -659,7 +699,7 @@ func (s *WindowsService) handleConnection(proxyConn *tls.Conn) {
|
|||
|
||||
// don't handle connections until the LDAP initialization retry loop has succeeded
|
||||
// (it would fail anyway, but this presents a better error to the user)
|
||||
if !s.ldapReady() {
|
||||
if !s.readyForConnections() {
|
||||
const msg = "This service cannot accept connections until LDAP initialization has completed."
|
||||
log.Error(msg)
|
||||
sendTDPError(msg)
|
||||
|
@ -966,7 +1006,7 @@ func (s *WindowsService) getServiceHeartbeatInfo() (types.Resource, error) {
|
|||
// staticHostHeartbeatInfo generates the Windows Desktop resource
|
||||
// for heartbeating statically defined hosts
|
||||
func (s *WindowsService) staticHostHeartbeatInfo(netAddr utils.NetAddr,
|
||||
getHostLabels func(string) map[string]string) func() (types.Resource, error) {
|
||||
getHostLabels func(string) map[string]string, nonAD bool) func() (types.Resource, error) {
|
||||
return func() (types.Resource, error) {
|
||||
addr := netAddr.String()
|
||||
name, err := s.nameForStaticHost(addr)
|
||||
|
@ -977,6 +1017,7 @@ func (s *WindowsService) staticHostHeartbeatInfo(netAddr utils.NetAddr,
|
|||
// as the name is a randomly generated UUID
|
||||
labels := getHostLabels(addr)
|
||||
labels[types.OriginLabel] = types.OriginConfigFile
|
||||
labels[types.ADLabel] = strconv.FormatBool(!nonAD)
|
||||
desktop, err := types.NewWindowsDesktopV3(
|
||||
name,
|
||||
labels,
|
||||
|
@ -984,6 +1025,7 @@ func (s *WindowsService) staticHostHeartbeatInfo(netAddr utils.NetAddr,
|
|||
Addr: addr,
|
||||
Domain: s.cfg.Domain,
|
||||
HostID: s.cfg.Heartbeat.HostUUID,
|
||||
NonAD: nonAD,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
@ -1046,21 +1088,26 @@ func (s *WindowsService) generateUserCert(ctx context.Context, username string,
|
|||
fmt.Sprintf("(%s=%s)", windows.AttrObjectClass, windows.ClassUser),
|
||||
fmt.Sprintf("(%s=%s)", windows.AttrSAMAccountName, username),
|
||||
}
|
||||
entries, err := s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), windows.CombineLDAPFilters(filters), []string{windows.AttrObjectSid})
|
||||
if err != nil {
|
||||
return nil, nil, trace.Wrap(err)
|
||||
|
||||
var activeDirectorySID string
|
||||
if !desktop.NonAD() {
|
||||
entries, err := s.lc.ReadWithFilter(s.cfg.LDAPConfig.DomainDN(), windows.CombineLDAPFilters(filters), []string{windows.AttrObjectSid})
|
||||
if err != nil {
|
||||
return nil, nil, trace.Wrap(err)
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
return nil, nil, trace.NotFound("LDAP failed to return objectSid for Windows username: %v", username)
|
||||
} else if len(entries) > 1 {
|
||||
s.cfg.Log.Warnf("LDAP unexpectedly returned multiple entries for objectSid for username: %v, taking the first", username)
|
||||
}
|
||||
activeDirectorySID, err = windows.ADSIDStringFromLDAPEntry(entries[0])
|
||||
if err != nil {
|
||||
return nil, nil, trace.Wrap(err)
|
||||
}
|
||||
s.cfg.Log.Debugf("Found objectSid %v for Windows username %v", activeDirectorySID, username)
|
||||
// Generate credentials with the user's SID
|
||||
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
return nil, nil, trace.NotFound("LDAP failed to return objectSid for Windows username: %v", username)
|
||||
} else if len(entries) > 1 {
|
||||
s.cfg.Log.Warnf("LDAP unexpectedly returned multiple entries for objectSid for username: %v, taking the first", username)
|
||||
}
|
||||
activeDirectorySID, err := windows.ADSIDStringFromLDAPEntry(entries[0])
|
||||
if err != nil {
|
||||
return nil, nil, trace.Wrap(err)
|
||||
}
|
||||
s.cfg.Log.Debugf("Found objectSid %v for Windows username %v", activeDirectorySID, username)
|
||||
// Generate credentials with the user's SID
|
||||
return s.generateCredentials(ctx, username, desktop.GetDomain(), ttl, activeDirectorySID)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue