"You shall authenticate to the LDAP to pass" - Gandalpher, the gopher
This project is an in-progress effort to create an open-source middleware that enables authentication via LDAP in a similar way to Traefik Enterprise.
Traefik plugins are developed using the compiled Go language. Rather than being pre-compiled and linked, however, plugins are executed on the fly by Yaegi, an embedded Go interpreter. Due to traefik/yaegi#1275 and traefik/yaegi#1484, the ldap-go
module only works after the listed version.
whoami:image: "traefik/whoami"container_name: "whoami"labels:- traefik.enable=true- traefik.http.routers.whoami.rule=Host(`whoami.localhost`)- traefik.http.routers.whoami.entrypoints=web# ldapAuth Register Middleware ====================================================- traefik.http.routers.whoami.middlewares=ldap_auth# ldapAuth Options=================================================================- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.enabled=true- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.logLevel=DEBUG- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.attribute=uid- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.baseDN=dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].url=ldap://ldap.forumsys.com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].port=389# =================================================================================
[...]labels:- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.attribute=uid- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.baseDN=dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].url=ldap://ldap.forumsys.com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].port=389
[...]labels:- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.attribute=uid- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.baseDN=dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.searchFilter=({{.Attribute}}={{.Username}})- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].url=ldap://ldap.forumsys.com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].port=389
[...]labels:- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.attribute=uid- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.baseDN=dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.bindDN=uid=tesla,dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.bindPassword=password- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.searchFilter=({{.Attribute}}={{.Username}})- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].url=ldap://ldap.forumsys.com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].port=389
[...]labels:- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.attribute=uid- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.baseDN=dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.bindDN=uid=tesla,dc=example,dc=com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.bindPassword=password- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.searchFilter=(&(objectClass=person)({{.Attribute}}={{.Username}}))- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].url=ldap://ldap.forumsys.com- traefik.http.middlewares.ldap_auth.plugin.ldapAuth.serverList[0].port=389
The Operation Mode
detected will be used to perform all subsequent requests.
If no searchFilter
is specified in its configuration, the middleware runs in the default bind mode, meaning it tries to make a simple bind request to the LDAP server with the credentials provided in the request headers. If the bind succeeds, the middleware forwards the request, otherwise, it returns a 401 Unauthorized status code.
If a searchFilter
query is specified in the configuration, then the middleware runs in search mode. In this mode, a search query with the given filter is issued to the LDAP server before trying to bind. If bindDN
and bindPassword
have also been provided, then the search query will use these credentials. If the result of this search returns only 1
record, it tries to issue a bind request with this record, otherwise, it aborts a 401 Unauthorized status code.
enabled
Optional, Default: true
Controls whether requests will be checked against LDAP or not before being delivered.
logLevel
Optional, Default: INFO
Set LogLevel
for detailed information about plugin operation.
serverList.url
Required, Default: ""
LDAP server address where queries will be performed.
serverList.port
Required, Default: 389
LDAP server port where queries will be performed.
serverList.weight
Optional, Default: 0
LDAP server weight to sort serverList
. Higher weight, higher precedence.
cacheTimeout
Optional, Default: 300
Indicates the number of seconds
until the session cookie expires. A zero or negative number will expire the cookie immediately.
cacheCookieName
Optional, Default: ldapAuth_session_token
The session cookie name.
cacheCookiePath
Optional, Default: ""
The session cookie path. By default, the cookie path will be set to the request path.
cacheCookieSecure
Optional, Default: false
Set to true if the session cookie should have the secure flag. The cookie will only be transmitted over an HTTPS connection.
cacheKey
Needs traefik
>= v2.8.5
Optional, Default: super-secret-key
The key used to encrypt session cookie information. You must
use a strong value here.
serverList.startTLS
Optional, Default: false
If set to true, instruct ldapAuth
to issue a StartTLS
request when initializing the connection with the LDAP server.
serverList.insecureSkipVerify
Optional, Default: false
When connecting to a ldaps
server or startTLS
is enabled, the connection to the LDAP server is verified to be secure. This option allows ldapAuth
to proceed and operate even for server connections otherwise considered insecure.
serverList.minVersionTLS
Optional, Default: tls.VersionTLS12
Contains the minimum TLS version that is acceptable. By default, TLS 1.2
is currently used as the minimum. TLS 1.0
is the minimum supported by this package.
This option value must match crypto/tls versions constants.
serverList.maxVersionTLS
Optional, Default: tls.VersionTLS13
Contains the maximum TLS version that is acceptable. By default, the maximum version supported by this package is used, which is currently TLS 1.3
.
This option value must match crypto/tls versions constants.
serverList.certificateAuthority
Optional, Default: ""
The serverList.certificateAuthority
option should contain one or more PEM-encoded certificates to use to establish a connection with the LDAP server if the connection uses TLS but the certificate was signed by a custom Certificate Authority.
Example:
ServerList:CertificateAuthority: |------BEGIN CERTIFICATE-----MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNVBAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRlY29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFtaWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGlEL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2jRKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzEapQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QPAwel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FXozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ98TwDIK/39WEB/V607As+KoYazQG8drorw==-----END CERTIFICATE-----
attribute
Optional, Default: cn
The attribute used to bind a user in Bind Mode
. Bind queries use this pattern: <attribute>=<username>,<baseDN>
, where the username is extracted from the request header. If AllowedGroups
option was used in Bind Mode
, the same pattern is added when searching if the user belongs to the group.
searchFilter
Optional, Default: ""
If not empty, the middleware will run in Search Mode
, filtering search results with the given query.
Filter queries can use the {{.Option}}
format, from text/template go package, as placeholders that are replaced by the equivalent value from config. Additionally, the username provided in the Authorization header of the request can also be used.
For example: (&(objectClass=inetOrgPerson)(gidNumber=500)({{.Attribute}}={{.Username}}))
.
Will be replaced to: (&(objectClass=inetOrgPerson)(gidNumber=500)(uid=tesla))
.
Note1: All filter options must start with Uppercase to be replaced correctly.
Note2: searchFilter
must not escape curly braces when using labels.
Note3: searchFilter
must escape curly braces when using yml file.
Note4: searchFilter
must escape curly braces when using toml file.
baseDN
Required, Default: ""
From where the plugin will search for users.
bindDN
Optional, Default: ""
The domain name to bind to in order to authenticate to the LDAP server when running on Search Mode
. Leaving this empty with Search Mode
means binds are anonymous, which is rarely expected behavior. It is not used when running in Bind Mode
.
bindPassword
Optional, Default: ""
The password corresponding to the bindDN
specified when running in Search Mode
, is used in order to authenticate to the LDAP server.
forwardUsername
Optional, Default: true
The forwardUsername
option can be enabled to forward the username in a specific header, defined using the forwardUsernameHeader
option.
forwardUsernameHeader
Optional, Default: Username
Name of the header to put the username in when forwarding it. This is not used if the forwardUsername
option is set to false
.
forwardAuthorization
Optional, Default: false
The forwardAuthorization
option determines if the authorization header will be forwarded or stripped from the request after the middleware has approved it. Attention
, enabling this option may expose the password of the LDAP user who is making the request.
forwardExtraLDAPHeaders
Optional, Default: false
The forwardExtraLDAPHeaders
option determines if the LDAP Extra Headers, Ldap-Extra-Attr-DN
and
Ldap-Extra-Attr-CN
, will be added or not to request. This is not used if the forwardUsername
option is set to false
or if searchFilter
is empty.
wwwAuthenticateHeader
Optional, Default: true
If the LDAP middleware receives a request with a missing or invalid Authorization header and wwwAuthenticateHeader
is enabled, it will set a WWW-Authenticate
header in the 401 Unauthorized response. See the WWW-Authenticate header documentation for more information.
wwwAuthenticateHeaderRealm
Optional, Default: ""
The name of the realm to specify in the WWW-Authenticate
header. This option is ineffective unless the wwwAuthenticateHeader
option is set to true.
enableNestedGroupFilter
Optional, Default: false
If you need to search the user's nested group and the LDAP
server support to search for LDAP_MATCHING_RULE_IN_CHAIN groups, you can enabled it by settings this parameter to true
, it is disabled by default.
allowedGroups
Needs traefik
>= v2.8.2
Optional, Default: []
The list of LDAP group DNs that users must be members of to be granted access. If a user is in any of the listed groups, then that user is granted access.
If set to an empty list, all users with an LDAP account can log in, without performing any group membership checks unless allowedUsers
is set. In that case, the user must be a part of the allowedUsers
list.
allowedGroups
is not supported with labels, because multiple value labels are separated with commas. You must use toml
or yaml
configuration file. For more details, check examples page.
allowedUsers
Needs traefik
>= v2.8.2
Optional, Default: []
The list of LDAP user DNs or usernames to be granted access. If a user is in the listed users, then that user is granted access.
If set to an empty list, all users with an LDAP account can log in, unless allowedGroups
is set. In that case, group membership checks will be performed.
allowedUsers
is not supported with labels, because multiple value labels are separated with commas. You must use toml
or yaml
configuration file. For more details, check examples page.