ldap

package module
v0.0.0-...-c041881 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 3, 2024 License: MPL-2.0 Imports: 20 Imported by: 4

README

ldap

Go Reference

ldap is a package for writing clients that authenticate using Active Directory or LDAP.

Primary types provided by the package:

  • ldap.Client
  • ldap.ClientConfig

Examples

  • CLI example which implements an ldap user authentication CLI.

An abbreviated example of authenticating a user:

client, err := ldap.NewClient(ctx, &clientConfig)
if err != nil { 
  // handle error appropriately
}

// authenticate and get the user's groups as well.
result, err := client.Authenticate(ctx, username, passwd, ldap.WithGroups())
if err != nil { 
  // handle error appropriately
}

if result.Success {
  // user successfully authenticated...
  if len(result.Groups) > 0 {
    // we found some groups associated with the authenticated user...
  } 
}

Configuration

ldap.ClientConfig provides connection details for your LDAP server, information on how to authenticate users, and instructions on how to query for group membership. The configuration options are categorized and detailed below.

Connection parameters
  • URLS ([]string, required) - The LDAP server to connect to. Examples: ldap://ldap.myorg.com, ldaps://ldap.myorg.com:636. If there's more than one URL configured, the directories will be tried in-order if there are errors during the connection process.
  • StartTLS (bool, optional) - If true, issues a StartTLS command after establishing an unencrypted connection.
  • InsecureTLS (bool, optional) - If true, skips LDAP server SSL certificate verification - insecure, use with caution!
  • Certificate (string, optional) - CA certificate to use when verifying LDAP server certificate, must be x509 PEM encoded.
  • ClientTLSCert (string, optional) - Client certificate to provide to the LDAP server, must be x509 PEM encoded.
  • ClientTLSKey (string, optional) - Client certificate key to provide to the LDAP server, must be x509 PEM encoded.
Binding parameters

There are two alternate methods of resolving the user object used to authenticate the end user: Search or User Principal Name. When using Search, the bind can be either anonymous or authenticated. User Principal Name is a method of specifying users supported by Active Directory. More information on UPN can be found here.

  • BindDN (string, optional) - Distinguished name of object to bind when performing user and group search. Example: cn=application-acct,ou=Users,dc=example,dc=com
  • BindPassword (string, optional) - Password to use along with binddn when performing user search.
  • UserDN (string, optional) - Base DN under which to perform user search. Example: ou=Users,dc=example,dc=com
  • UserAttr (string, optional) - Attribute on user attribute object matching the username passed when authenticating. Examples: "cn", "uid"
  • UserFilter (string, optional) - Go template used to construct a ldap user search filter. The template can access the following context variables: [UserAttr, Username]. The default userfilter is ({{.UserAttr}}={{.Username}}) or (userPrincipalName={{.Username}}@UPNDomain) if the upndomain parameter is set. The user search filter can be used to restrict what user can attempt to log in. For example, to limit login to users that are not contractors, you could write (&(objectClass=user)({{.UserAttr}}={{.Username}})(!(employeeType=Contractor))).
  • DiscoverDN (bool, optional) - If true, use anonymous bind to discover the bind DN of a user
  • UserDN (string, optional) - Base DN under which to perform user search. Example: ou=Users,dc=example,dc=com
  • UserAttr (string, optional) - Attribute on user attribute object matching the username passed when authenticating. Examples: cn, uid
  • UserFilter (string, optional) - Go template used to construct a ldap user search filter. The template can access the following context variables: [UserAttr, Username]. The default UserFilter is ({{.UserAttr}}={{.Username}}) or (userPrincipalName={{.Username}}@UPNDomain) if the UPNDomain parameter is set. The user search filter can be used to restrict what user can attempt to log in. For example, to limit login to users that are not contractors, you could write (&(objectClass=user)({{.UserAttr}}={{.Username}})(!(employeeType=Contractor))).
  • AllowEmptyPasswordBinds (bool, optional) - This option prevents users from bypassing authentication when providing an empty password. The default is false.
  • AnonymousGroupSearch (bool, optional) - Use anonymous binds when performing LDAP group searches. Defaults to false.
Binding - User Principal Name (AD)
  • UPNDomain (string, optional) - userPrincipalDomain used to construct the UPN string for the authenticating user. The constructed UPN will appear as [username]@UPNDomain. Example: example.com, which will result in binding as username@example.com.
Alias dereferencing
  • DerefAliases (string, optional) - Will control how aliases are dereferenced when performing the search. Possible values are: never, finding, searching, and always. If unset, a default of never is used. When set to finding, it will only dereference aliases during name resolution of the base. When set to searching, it will dereference aliases after name resolution.
Group Membership Resolution

Once a user has been authenticated, the LDAP auth method must know how to resolve which groups the user is a member of. The configuration for this can vary depending on your LDAP server and your directory schema. There are two main strategies when resolving group membership - the first is searching for the authenticated user object and following an attribute to groups it is a member of. The second is to search for group objects of which the authenticated user is a member of. Both methods are supported.

  • GroupFilter (string, optional) - Go template used when constructing the group membership query. The template can access the following context variables: [UserDN, Username]. The default is (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}})), which is compatible with several common directory schemas. To support nested group resolution for Active Directory, instead use the following query: (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}})).
  • GroupDN (string, required) - LDAP search base to use for group membership search. This can be the root containing either groups or users. Example: ou=Groups,dc=example,dc=com
  • GroupAttr (string, optional) - LDAP attribute to follow on objects returned by GroupFilter in order to enumerate user group membership. Examples: for GroupFilter queries returning group objects, use: cn. For queries returning user objects, use: memberOf. The default is cn. Note: When using Authenticated Search for binding parameters (see above) the distinguished name defined for BindDN is used for the group search. Otherwise, the authenticating user is used to perform the group search.
User Attributes

Using configuration you can choose to optionally include an authenticated user's DN and entry attributes in the results of an authentication request.

  • IncludeUserAttributes (bool, optional) - If true, specifies that the authenticating user's DN and attributes be included an authentication AuthResult. Note: the default password attribute for both openLDAP (userPassword) and AD (unicodePwd) will always be excluded.

  • ExcludeUserAttributes ([]string, optional) - If specified, optionally defines a set of user attributes to be excluded when an authenticating user's attributes are included in an AuthResult.Note: the default password attribute for both openLDAP (userPassword) and AD (unicodePwd) will always be excluded.

Other
  • MaximumPageSize (int, optional) - If set to a value greater than 0, the LDAP backend will use the LDAP server's paged search control to request pages of up to the given size. This can be used to avoid hitting the LDAP server's maximum result size limit. Otherwise, the LDAP backend will not use the paged search control.

Documentation

Index

Constants

View Source
const (
	// DefaultTimeout is the timeout value used for both dialing and requests to
	// the LDAP server
	DefaultTimeout = 60

	// DefaultURL for the ClientConfig.URLs
	DefaultURL = "ldaps://127.0.0.1:686"

	// DefaultUserAttr is the "username" attribute of the entry's DN and is
	// typically either the cn in ActiveDirectory or uid in openLDAP  (default:
	// cn)
	DefaultUserAttr = "cn"

	// DefaultGroupFilter for the ClientConfig.GroupFilter
	DefaultGroupFilter = `(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`

	// DefaultGroupAttr for the ClientConfig.GroupAttr
	DefaultGroupAttr = "cn"

	// DefaultTLSMinVersion for the ClientConfig.TLSMinVersion
	DefaultTLSMinVersion = "tls12"

	// DefaultTLSMaxVersion for the ClientConfig.TLSMaxVersion
	DefaultTLSMaxVersion = "tls13"

	// DefaultOpenLDAPUserPasswordAttribute defines the attribute name for the
	// openLDAP default password attribute which will always be excluded
	DefaultOpenLDAPUserPasswordAttribute = "userPassword"

	// DefaultADUserPasswordAttribute defines the attribute name for the
	// AD default password attribute which will always be excluded
	DefaultADUserPasswordAttribute = "unicodePwd"

	// DefaultDerefAliases defines the default for dereferencing aliases
	DefaultDerefAliases = "never"
)

Variables

View Source
var (
	// ErrUnknown is an unknown/undefined error
	ErrUnknown = errors.New("unknown")

	// ErrInvalidParameter is an invalid parameter error
	ErrInvalidParameter = errors.New("invalid parameter")

	// ErrInternal is an internal error
	ErrInternal = errors.New("internal error")
)

Functions

func ApplyOpts

func ApplyOpts(opts interface{}, opt ...Option)

ApplyOpts takes a pointer to the options struct as a set of default options and applies the slice of opts as overrides.

func EscapeFilter

func EscapeFilter(filter string) string

func SIDBytes

func SIDBytes(revision uint8, identifierAuthority uint16) ([]byte, error)

SIDBytes creates a SID from the provided revision and identifierAuthority

Types

type Attribute

type Attribute struct {
	// Name is the name of the LDAP attribute
	Name string
	// Vals are the LDAP attribute values
	Vals []string
}

type AuthResult

type AuthResult struct {
	// Success represents whether or not the attempt was successful
	Success bool

	// Groups are the groups that were associated with the authenticated
	// user (optional, see WithGroups() option)
	Groups []string

	// UserDN of the authenticated user (optional see WithUserAttributes()
	// option along with IncludeUserAttributes and ExcludedUserAttributes config
	// fields).
	UserDN string

	// UserAttributes that are associated with the authenticated user (optional
	// see WithUserAttributes() option along with IncludeUserAttributes and
	// ExcludedUserAttributes config fields)
	UserAttributes map[string][]string

	// Warnings are warnings that happen during either authentication or when
	// attempting to find the groups associated with the authenticated user (see
	// the WithGroups option)
	Warnings []Warning
}

AuthResult is the result from a user authentication request via Client.Authenticate(...)

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client provides a client for making requests to a directory service.

func NewClient

func NewClient(ctx context.Context, conf *ClientConfig) (*Client, error)

NewClient will create a new client from the configuration. The following defaults will be used if no config value is provided for them:

  • URLs: see constant DefaultURL
  • UserAttr: see constant DefaultUserAttr
  • GroupAttr: see constant DefaultGroupAttr
  • GroupFilter: see constant DefaultGroupFilter
  • TLSMinVersion: see constant DefaultTLSMinVersion
  • TLSMaxVersion: see constant DefaultTLSMaxVersion

func (*Client) Authenticate

func (c *Client) Authenticate(ctx context.Context, username, password string, opt ...Option) (*AuthResult, error)

Authenticate the user using the client's configured directory service. If the WithGroups option is specified, it will also return the user's groups from the directory.

Supported options: WithUserAttributes, WithGroups, WithDialer, WithURLs, WithLowerUserAttributeKeys, WithEmptyAnonymousGroupSearch

func (*Client) Close

func (c *Client) Close(ctx context.Context)

Close will close the client's connection to the directory service.

type ClientConfig

type ClientConfig struct {
	// URLs are the URLs to use when connecting to a directory (default:
	// ldap://127.0.0.1).  When multiple URLs are specified; they are tried
	// in the order specified.
	URLs []string `json:"urls"`

	// UserDN is the base distinguished name to use when searching for users
	// (eg: ou=People,dc=example,dc=org)
	UserDN string `json:"userdn"`

	// AnonymousGroupSearch specifies that an anonymous bind should be used when
	// searching for groups (if true, the bind credentials will still be used
	// for the initial connection test).
	AnonymousGroupSearch bool `json:"anonymous_group_search"`

	// AllowEmptyAnonymousGroupSearches: if true it removes the userDN from
	// unauthenticated group searches (optional).
	AllowEmptyAnonymousGroupSearch bool `json:"allow_empty_anonymous_group_search"`

	// GroupDN is the distinguished name to use as base when searching for group
	// membership (eg: ou=Groups,dc=example,dc=org)
	GroupDN string `json:"groupdn"`

	// GroupFilter is a Go template for querying the group membership of user
	// (optional).  The template can access the following context variables:
	// UserDN, Username
	//
	// Example:
	// (&(objectClass=group)(member:1.2.840.113556.1.4.1941:={{.UserDN}}))
	// Default: (|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))`
	GroupFilter string `json:"groupfilter"`

	// GroupAttr is the attribute which identifies group members in entries
	// returned from GroupFilter queries.  Examples: for groupattr queries
	// returning group objects, use: cn. For queries returning user objects,
	// use: memberOf.
	// Default: cn
	GroupAttr string `json:"groupattr"`

	// UPNDomain is the userPrincipalName domain, which enables a
	// userPrincipalDomain login with [username]@UPNDomain (optional)
	UPNDomain string `json:"upndomain"`

	// UserFilter (optional) is a Go template used to construct a ldap user
	// search filter. The template can access the following context variables:
	// [UserAttr, Username]. The default userfilter is
	// ({{.UserAttr}}={{.Username}}) or
	// (userPrincipalName={{.Username}}@UPNDomain) if the upndomain parameter
	// is set. The user search filter can be used to  restrict what user can
	// attempt to log in. For example, to limit login to users that are not
	// contractors, you could write
	// (&(objectClass=user)({{.UserAttr}}={{.Username}})(!(employeeType=Contractor)))
	UserFilter string `json:"userfilter"`

	// UserAttr is the "username" attribute of the entry's DN and is typically
	// either the cn in ActiveDirectory or uid in openLDAP  (default: cn)
	UserAttr string `json:"userattr"`

	// Certificates to use verify the identity of the directory service and is a
	// set of PEM encoded x509 (optional)
	Certificates []string `json:"certificates"`

	// ClientTLSCert is the client certificate used with the ClientTLSKey to
	// authenticate the client to the directory service.  It must be PEM encoded
	// x509 (optional)
	ClientTLSCert string `json:"client_tls_cert"`

	// ClientTLSKey is the client certificate key used with the ClientTLSCert to
	// authenticate the client to the directory service.  It must be a PEM
	// encoded x509 (optional)
	ClientTLSKey string `json:"client_tls_key"`

	// InsecureTLS will skip the verification of the directory service's
	// certificate when making a client connection (optional).
	// Warning: this is insecure
	InsecureTLS bool `json:"insecure_tls"`

	// StartTLS will issue the StartTLS command after establishing an initial
	// non-TLS connection (optional)
	StartTLS bool `json:"starttls"`

	// BindDN is the distinguished name used when the client binds
	// (authenticates) to a directory service
	BindDN string `json:"binddn"`

	// BindPassword is the password used with the BindDN when the client binds
	// (authenticates) to a directory service (optional)
	BindPassword string `json:"bindpass"`

	// AllowEmptyPasswordBinds: if true it allows binds even if the user's
	// password is empty (zero length) (optional).
	AllowEmptyPasswordBinds bool `json:"allow_empty_passwd_bind"`

	// DiscoverDN: if true, it will use an anonymous bind with a search
	// to discover the bind DN of a user (optional)
	DiscoverDN bool `json:"discoverdn"`

	// TLSMinVersion version to use. Accepted values are
	// 'tls10', 'tls11', 'tls12' or 'tls13'. Defaults to 'tls12'
	TLSMinVersion string `json:"tls_min_version"`

	// TLSMaxVersion version to use. Accepted values are 'tls10', 'tls11',
	// 'tls12' or 'tls13'. Defaults to 'tls12'
	TLSMaxVersion string `json:"tls_max_version"`

	// UseTokenGroups: if true, use the Active Directory tokenGroups constructed
	// attribute of the user to find the group memberships. This will find all
	// security groups including nested ones.",
	UseTokenGroups bool `json:"use_token_groups"`

	// RequestTimeout in seconds is used when dialing to establish the
	// connection and when making requests against the server via a connection
	// before returning back an error. If not set, then the DefaultTimeout is
	// used.
	RequestTimeout int `json:"request_timeout"`

	// IncludeUserAttributes optionally specifies that the authenticating user's
	// DN and attributes be included an authentication AuthResult.
	//
	// Note: the default password attribute for both openLDAP (userPassword) and
	// AD (unicodePwd) will always be excluded.
	IncludeUserAttributes bool

	// ExcludedUserAttributes optionally defines a set of user attributes to be
	// excluded when an authenticating user's attributes are included in an
	// AuthResult (see: Config.IncludeUserAttributes or the WithUserAttributes()
	// option).
	//
	// Note: the default password attribute for both openLDAP (userPassword) and
	// AD (unicodePwd) will always be excluded.
	ExcludedUserAttributes []string

	// LowerUserAttributeKeys optionally specifies that the authenticating user's
	// DN and attributes be included in AuthResult use lowercase key names rather
	// than the default camel case.
	LowerUserAttributeKeys bool

	// IncludeUserGroups optionally specifies that the authenticating user's
	// group membership be included an authentication AuthResult.
	IncludeUserGroups bool

	// MaximumPageSize optionally specifies a maximum ldap search result size to
	// use when retrieving the authenticated user's group memberships. This can
	// be used to avoid reaching the LDAP server's max result size.
	MaximumPageSize int `json:"max_page_size"`

	// DerefAliases will control how aliases are dereferenced when
	// performing the search. Possible values are: never, finding, searching,
	// and always. If unset, a default of "never" is used. When set to
	// "finding", it will only dereference aliases during name resolution of the
	// base. When set to "searching", it will dereference aliases after name
	// resolution.
	DerefAliases string `json:"dereference_aliases"`

	// DeprecatedVaultPre111GroupCNBehavior: if true, group searching reverts to
	// the pre 1.1.1 Vault behavior.
	// see: https://www.vaultproject.io/docs/upgrading/upgrade-to-1.1.1
	DeprecatedVaultPre111GroupCNBehavior *bool `json:"use_pre111_group_cn_behavior"`
}

type Option

type Option func(interface{})

Option defines a common functional options type which can be used in a variadic parameter pattern.

func WithEmptyAnonymousGroupSearch

func WithEmptyAnonymousGroupSearch() Option

WithEmptyAnonymousGroupSearch removes userDN from anonymous group searches.

func WithGroups

func WithGroups() Option

WithGroups requests that the groups be included in the response.

func WithLowerUserAttributeKeys

func WithLowerUserAttributeKeys() Option

WithLowerUserAttributeKeys returns a User Attribute map where the keys are all cast to lower case. This is necessary for some clients, such as Vault, where user configured user attribute key names have always been stored lower case.

func WithURLs

func WithURLs(urls ...string) Option

WithURLs provides a set of optional ldap URLs for directory services

func WithUserAttributes

func WithUserAttributes() Option

WithUserAttributes requests that authenticating user's DN and attributes be included in the response. Note: the default password attribute for both openLDAP (userPassword) and AD (unicodePwd) will always be excluded. To exclude additional attributes see: Config.ExcludedUserAttributes.

type Warning

type Warning string

Warning is a warning message

Directories

Path Synopsis
examples
cli Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL