LDAP Authentication¶
Traefik Enterprise can integrate with LDAP in order to restrict the access to applications.
Authentication in Traefik Enterprise is implemented as a middleware. To avoid having sensitive information such as LDAP credentials specified as labels (or in CRDs) by applications and to allow multiple middlewares to reuse the same authentication method, the reusable portion of the configuration is externalized in Authentication Sources.
Authentication Sources are defined in the static configuration of the cluster and are referenced by authentication middlewares.
Authentication Source¶
Before configuring an LDAP middleware, an LDAP Authentication Source must be defined in the static configuration.
Authentication Source Options¶
url
¶
Required, Default=""
The url
option should be set to the URL of your LDAP server. It should use either the ldaps
or ldap
protocol and end with a port, like ldaps://ldap.example.org:636
for example.
authSources:
ldapSource:
ldap:
url: ldaps://ldap.example.org:636
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
url = "ldaps://ldap.example.org:636"
startTLS
¶
Optional, Default=false
startTLS
, if set to true, instructs Traefik Enterprise to issue a StartTLS
request when initializing the connection with the LDAP server.
authSources:
ldapSource:
ldap:
startTLS: true
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
startTLS = true
certificateAuthority
¶
Optional, Default=""
The certificateAuthority
option should contain a PEM-encoded certificate to use to establish a connection with the LDAP server if the connection uses TLS but that the certificate was signed by a custom Certificate Authority.
authSources:
ldapSource:
ldap:
certificateAuthority: |-
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
certificateAuthority = """
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
"""
insecureSkipVerify
¶
Optional, Default=false
When TLS is enabled, the connection to the LDAP server is verified to be secure. This option allows Traefik Enterprise to proceed and operate even for server connections otherwise considered insecure.
authSources:
ldapSource:
ldap:
insecureSkipVerify: true
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
insecureSkipVerify = true
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.
authSources:
ldapSource:
ldap:
bindDN: cn=admin,dc=example,dc=com
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
bindDN = "cn=admin,dc=example,dc=com"
bindPassword
¶
Optional, Default=""
The password corresponding to the bindDN
specified when running in search mode, used in order to authenticate to the LDAP server.
authSources:
ldapSource:
ldap:
bindPassword: mypassword
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
bindPassword = "mypassword"
connPool
¶
Optional, Default=None
In order to minimize the impact on the performance of requests using an LDAP authentication middleware, Traefik Enterprise keeps a pool of connections to the LDAP server and reuses them instead of opening a new connection for each request.
connPool.size
¶
Optional, Default=10
The number of connections managed by the pool can be customized with the size
property.
authSources:
ldapSource:
ldap:
connPool:
size: 42
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
size = 42
connPool.burst
¶
Optional, Default=5
burst
connections are ephemeral connections that are opened when the pool is already full. Once the number of connection exceeds size
+ burst
, a Too Many Connections
error is returned.
authSources:
ldapSource:
ldap:
connPool:
burst: 42
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
burst = 42
connPool.ttl
¶
Optional, Default=60s
Pooled connections are still meant to be short-lived, so they are closed after roughly one minute by default. This behavior can be modified with the ttl
property.
authSources:
ldapSource:
ldap:
connPool:
ttl: 42s
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
ttl = 42s
LDAP Middleware¶
After declaring an LDAP Authentication Source in the static configuration of the cluster, LDAP middlewares can be added to routers.
The LDAP middleware will look for user credentials in the Authorization
header of each request. Credentials must be encoded with the following format: base64(username:password)
.
Bind Mode vs Search Mode¶
If no filter 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 filter query is specified in the middleware configuration, and the Authentication Source referenced has a bindDN
and a bindPassword
, 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 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.
Middleware Options¶
source
¶
Required, Default=""
The source
option should contain the name of the authentication source used by the middleware.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.source=ldapSource"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
source: ldapSource
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.source=ldapSource"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.source": "ldapSource"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.source=ldapSource"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
source: ldapSource
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
source = "ldapSource"
baseDN
¶
Required, Default=""
The baseDN
option should be set to the base domain name that should be used for bind and search queries.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.baseDN=dc=example,dc=com"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
baseDN: dc=example,dc=com
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.baseDN=dc=example,dc=com"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.baseDN": "dc=example,dc=com"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.baseDN=dc=example,dc=com"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
baseDN: dc=example,dc=com
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
baseDN = "dc=example,dc=com"
attribute
¶
Required, Default="cn"
The attribute used to bind a user. Bind queries use this pattern: <attr>=<username>,<baseDN>
, where the username is extracted from the request header.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.attribute=cn"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
attribute: cn
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.attribute=cn"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.attribute": "cn"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.attribute=cn"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
attribute: cn
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
attribute = "cn"
forwardUsername
¶
Optional, Default=""
The forwardUsername
option can be enabled to forward the username in a specific header, defined using the forwardUsernameHeader
option.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsername=true"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
forwardUsername: true
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsername=true"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsername": "true"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsername=true"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
forwardUsername: true
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardUsername = true
forwardUsernameHeader
¶
Required, 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
.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsernameHeader=userID"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
forwardUsernameHeader: userID
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsernameHeader=userID"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsernameHeader": "userID"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardUsernameHeader=userID"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
forwardUsernameHeader: userID
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardUsernameHeader = "userID"
forwardAuthorization
¶
Required, Default=false
The forwardAuthorization
option determines if the authorization header will be forwarded or stripped from the request after it has been approved by the middleware.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardAuthorization=true"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
forwardAuthorization: true
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardAuthorization=true"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardAuthorization": "true"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.forwardAuthorization=true"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
forwardAuthorization: true
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardAuthorization = true
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 %s
placeholder that is replaced by the username provided in the Authorization
header of the request.
For example: (&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))
.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.searchFilter=(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
searchFilter: "(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.searchFilter=(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.searchFilter": "(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.searchFilter=(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
searchFilter: "(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
searchFilter = "(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
wwwAuthenticateHeader
¶
Optional, Default=false
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.
Note
The realm
directive of the WWW-Authenticate
header can be customized with the wwwAuthenticateHeaderRealm
option.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeader=true"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
wwwAuthenticateHeader: true
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeader=true"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeader": "true"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeader=true"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
wwwAuthenticateHeader: true
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
wwwAuthenticateHeader = true
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
.
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeaderRealm=myRealm"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap
spec:
plugin:
ldapAuth:
wwwAuthenticateHeaderRealm: "myRealm"
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeaderRealm=myRealm"
"labels": {
"traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeaderRealm": "myRealm"
}
labels:
- "traefik.http.middlewares.test-ldap.plugin.ldapAuth.wwwAuthenticateHeaderRealm=myRealm"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
wwwAuthenticateHeaderRealm: "myRealm"
[http.middlewares]
[http.middlewares.test-ldap.plugin.ldapAuth]
wwwAuthenticateHeaderRealm = "myRealm"
Advanced Configuration Examples¶
For applications to be secured with LDAP authentication, an ldapAuth
middleware must be created and enabled in the router. Here are some examples of the middleware configuration in its simplest form depending on the provider you're using:
labels:
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.source=ldapSource"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.baseDN=dc=example,dc=org"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap-auth
spec:
plugin:
ldapAuth:
source: ldapSource
baseDN: dc=example,dc=org
http:
middlewares:
test-inflightreq:
plugin:
ldapAuth:
source: ldapSource
baseDN: dc=example,dc=org
[http.middlewares]
[http.middlewares.test-ldap-auth.plugin.ldapAuth]
source = "ldapSource"
baseDN = "dc=example,dc=org"
Below is a more advanced configuration example using search, bind and the WWW-Authenticate
header:
labels:
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.source=ldapSource"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.baseDN=dc=example,dc=org"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.searchFilter=(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.forwardUsername=true"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.forwardUsernameHeader=Custom-Username-Header-Name"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.wwwAuthenticateHeader=true"
- "traefik.http.middlewares.test-ldap-auth.plugin.ldapAuth.wwwAuthenticateHeaderRealm=traefikee"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-ldap-auth
spec:
plugin:
ldapAuth:
source: ldapSource
baseDN: dc=example,dc=org
searchFilter: (&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))
forwardUsername: true
forwardUsernameHeader: Custom-Username-Header-Name
wwwAuthenticateHeader: true
wwwAuthenticateHeaderRealm: traefikee
http:
middlewares:
test-ldap-auth:
plugin:
ldapAuth:
source: ldapSource
baseDN: dc=example,dc=org
searchFilter: (&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))
forwardUsername: true
forwardUsernameHeader: Custom-Username-Header-Name
wwwAuthenticateHeader: true
wwwAuthenticateHeaderRealm: traefikee
[http.middlewares]
[http.middlewares.test-ldap-auth.plugin.ldapAuth]
source = "ldapSource"
baseDN = "dc=example,dc=org"
searchFilter = "(&(objectClass=inetOrgPerson)(gidNumber=500)(uid=%s))"
forwardUsername = true
forwardUsernameHeader = "Custom-Username-Header-Name"
wwwAuthenticateHeader = true
wwwAuthenticateHeaderRealm = "traefikee"