LDAP Authentication¶
TraefikEE can integrate with LDAP in order to restrict the access to applications.
Authentication in TraefikEE 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]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
url = "ldaps://ldap.example.org:636"
authSources:
ldapSource:
ldap:
url: ldaps://ldap.example.org:636
startTLS
¶
Optional, Default=false
startTLS
, if set to true, instructs TraefikEE to issue a StartTLS
request when initializing the connection with the LDAP server.
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
startTLS = true
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]
[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-----
"""
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 TraefikEE to proceed and operate even for server connections otherwise considered insecure.
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
insecureSkipVerify = true
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.
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
bindDN = "cn=admin,dc=example,dc=com"
authSources:
ldapSource:
ldap:
bindDN: cn=admin,dc=example,dc=com
bindPassword
¶
Optional, Default=""
The password to use in order to authenticate to the LDAP server.
[authSources]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
bindPassword = "mypassword"
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, TraefikEE 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]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
size = 42
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]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
burst = 42
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]
[authSources.ldapSource]
[authSources.ldapSource.ldap]
[authSources.ldapSource.ldap.connPool]
ttl = 42s
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 that 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 password, 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 the bind request with this record to LDAP, 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]
[http.middlewares.test-ldap.plugin.ldapAuth]
source = "ldapSource"
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
baseDN = "dc=example,dc=com"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
baseDN: dc=example,dc=com
attribute
¶
Required, Default="cn"
The attribute used to search and bind a user. Queries use this pattern <attr>=<username>,<baseDN>
.
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
attribute = "cn"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
attribute: cn
forwardUsername
¶
Optional, Default=""
The forwardUsername
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardUsername = true
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardUsernameHeader = "userID"
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 a 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]
[http.middlewares.test-ldap.plugin.ldapAuth]
forwardAuthorization = true
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
forwardAuthorization: true
searchFilter
¶
Optional, Default=""
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]
[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))"
wwwAuthenticateHeader
¶
Optional, Default=false
When wwwAuthenticateHeader
is enabled, the WWW-Authenticate
header is set to Basic realm="<wwwAuthenticateHeaderRealm>"
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
wwwAuthenticateHeader = true
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]
[http.middlewares.test-ldap.plugin.ldapAuth]
wwwAuthenticateHeaderRealm = "myRealm"
http:
middlewares:
test-ldap:
plugin:
ldapAuth:
wwwAuthenticateHeaderRealm: "myRealm"
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.
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]
[http.middlewares.test-ldap-auth.plugin.ldapAuth]
source = "ldapSource"
baseDN = "dc=example,dc=org"
http:
middlewares:
test-inflightreq:
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]
[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:
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