Skip to content

Commit

Permalink
Make LDAP desktop discovery disabled by default
Browse files Browse the repository at this point in the history
Since our LDAP-based desktop discovery is not very configurable,
we opt to have it disabled by default.

Teleport will log a warning if desktop discovery is disabled and there
are no statically defined Windows desktops. In this case, the Windows
Desktop Service will simply sit idle, as there will be no desktops
available to connect to.

This commit implements the above, but also paves the way towards
a more flexible discovery system (described in the RFD).

We introduce a new config section:

    discovery:
      base_dn: '*'
      filters:
      - filter1
      - filter2

For now, the only valid value for base_dn is the wildcard, which
instructs Teleport to search from the domain root. Additionally,
teleport will validate that any provided filters are valid but
does not currently respect them when performing the search.

Future updates will allow for changing the base DN to something
more specific and filtering the results with LDAP filters.
  • Loading branch information
zmb3 committed Oct 22, 2021
1 parent 2c0739d commit 747f370
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 10 deletions.
6 changes: 6 additions & 0 deletions docs/pages/desktop-access/reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ windows_desktop_service:
# Plain text file containing the LDAP password for authentication.
# This is usually the same password you use to login to the Domain Controller.
password_file: /var/lib/ldap-pass
# (optional) settings for enabling automatic desktop discovery via LDAP
discovery:
# currently supported values:
# '*' to search from the root of the domain
# '' to disable desktop discovery
base_dn: '*'
# Rules for applying labels to Windows hosts based on regular expressions
# matched against the host name. If multiple rules match, the desktop will
# get the union of all matching labels.
Expand Down
9 changes: 9 additions & 0 deletions lib/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

"golang.org/x/crypto/ssh"

"github.com/go-ldap/ldap/v3"
"github.com/gravitational/trace"

"github.com/gravitational/teleport"
Expand Down Expand Up @@ -1183,6 +1184,14 @@ func applyWindowsDesktopConfig(fc *FileConfig, cfg *service.Config) error {
}
cfg.WindowsDesktop.ListenAddr = *listenAddr
}

for _, filter := range fc.WindowsDesktop.Discovery.Filters {
if _, err := ldap.CompileFilter(ldap.EscapeFilter(filter)); err != nil {
return trace.BadParameter("WindowsDesktopService specifies invalid LDAP filter %q", filter)
}
}
cfg.WindowsDesktop.Discovery = fc.WindowsDesktop.Discovery

var err error
cfg.WindowsDesktop.PublicAddrs, err = utils.AddrsFromStrings(fc.WindowsDesktop.PublicAddr, defaults.WindowsDesktopListenPort)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions lib/config/configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,7 @@ func makeConfigFixture() string {
},
}

// Windows Desktop Service
conf.WindowsDesktop = WindowsDesktopService{
Service: Service{
EnabledFlag: "yes",
Expand Down
2 changes: 2 additions & 0 deletions lib/config/fileconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,8 @@ type WindowsDesktopService struct {
PublicAddr apiutils.Strings `yaml:"public_addr,omitempty"`
// LDAP is the LDAP connection parameters.
LDAP LDAPConfig `yaml:"ldap"`
// Discovery configures desktop discovery via LDAP.
Discovery service.LDAPDiscoveryConfig `yaml:"discovery,omitempty"`
// Hosts is a list of static Windows hosts connected to this service in
// gateway mode.
Hosts []string `yaml:"hosts,omitempty"`
Expand Down
14 changes: 14 additions & 0 deletions lib/service/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,10 @@ type WindowsDesktopConfig struct {
PublicAddrs []utils.NetAddr
// LDAP is the LDAP connection parameters.
LDAP LDAPConfig

// Discovery configures automatic desktop discovery via LDAP.
Discovery LDAPDiscoveryConfig

// Hosts is an optional list of static Windows hosts to expose through this
// service.
Hosts []utils.NetAddr
Expand All @@ -855,6 +859,16 @@ type WindowsDesktopConfig struct {
HostLabels HostLabelRules
}

type LDAPDiscoveryConfig struct {
// BaseDN is the base DN to search for desktops.
// Use the value '*' to search from the root of the domain,
// or leave blank to disable desktop discovery.
BaseDN string `yaml:"base_dn"`
// Filters are additional LDAP filters to apply to the search.
// See: https://ldap.com/ldap-filters/
Filters []string `yaml:"filters"`
}

// HostLabelRules is a collection of rules describing how to apply labels to hosts.
type HostLabelRules []HostLabelRule

Expand Down
3 changes: 2 additions & 1 deletion lib/service/desktop.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus.
}
},
},
LDAPConfig: desktop.LDAPConfig(cfg.WindowsDesktop.LDAP),
LDAPConfig: desktop.LDAPConfig(cfg.WindowsDesktop.LDAP),
DiscoveryBaseDN: cfg.WindowsDesktop.Discovery.BaseDN,
})
if err != nil {
return trace.Wrap(err)
Expand Down
18 changes: 15 additions & 3 deletions lib/srv/desktop/windows_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ type WindowsServiceConfig struct {
HostLabelsFn func(host string) map[string]string
// LDAPConfig contains parameters for connecting to an LDAP server.
LDAPConfig
// DiscoveryBaseDN is the base DN for searching for Windows Desktops.
// Desktop discovery is disabled if this field is empty.
DiscoveryBaseDN string
// TODO(zmb3): add support for LDAP filters as defined in RFD #34
}

// LDAPConfig contains parameters for connecting to an LDAP server.
Expand Down Expand Up @@ -323,9 +327,17 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) {
return nil, trace.Wrap(err)
}

if err := s.startDiscoveredHostHeartbeats(); err != nil {
s.Close()
return nil, trace.Wrap(err)
// for now, the only valid base DN is '*'
// TODO(zmb3): allow further customizing the search
if s.cfg.DiscoveryBaseDN == types.Wildcard {
if err := s.startDiscoveredHostHeartbeats(); err != nil {
s.Close()
return nil, trace.Wrap(err)
}
} else if len(s.cfg.Heartbeat.StaticHosts) == 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")
}

return s, nil
Expand Down
21 changes: 15 additions & 6 deletions rfd/0034-desktop-access-windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,10 @@ translates the Teleport desktop protocol into RDP:
It can also talk to `localhost` RDP service, if installed on a Windows machine
in agent mode (described below).

If configured with Active Directory Domain Controller credentials,
`windows_desktop_service` also discovers all available Windows hosts from
Active Directory and registers them in Teleport as `WindowsDesktop` objects.
Without Domain Controller credentials, `windows_desktop_service` uses a static
list of Windows hosts provided in `teleport.yaml`.
`windows_desktop_service` has the ability to automatically discover available
Windows hosts from Active Directory by performing an LDAP search. In addition,
`windows_desktop_service` can use a static list of Windows hosts provided in
`teleport.yaml`.

### Supported versions

Expand Down Expand Up @@ -182,13 +181,17 @@ connect to. Internally, Teleport tracks known Windows hosts using

There are 3 ways that `windows_desktop_service` discovers Windows hosts to
register:
- hardcoded list of standalone hosts provided in the config file (see
- hardcoded list of hosts provided in the config file (see
[configuration](#configuration))
- list of Active Directory-enrolled hosts obtained from AD via LDAPS (LDAP over
SSL)
- LDAP library: https://pkg.go.dev/github.com/go-ldap/ldap/v3
- local host, when running on a Windows machine in agent mode

By default, Teleport will only register hosts that are provided in the
configuration file. To enable host discovery over LDAP, additional configuration
is necessary (see [configuration](#configuration)).

#### Automatic Host Labels

Teleport will automatically apply the following host labels to hosts which are
Expand Down Expand Up @@ -243,6 +246,12 @@ windows_desktop_service:
- win1.example.com
- win2.example.com
- ...
# (optional) settings for enabling automatic desktop discovery via LDAP
discovery:
base_dn: '*' # wildcard searches from the root, leave empty to disable discovery
filters: # additional LDAP filters: https://ldap.com/ldap-filters/
- filter1 # note: multiple filters are combined into an AND filter
- filter2
# (optional) host_labels applies labels to windows hosts for RBAC.
# Each entry maps to a subset of hosts by regexp and applies a group of labels.
# A host can match multiple regexps and will get a union of all the labels.
Expand Down

0 comments on commit 747f370

Please sign in to comment.