sources/ldap: allow multiple server URIs for loadbalancing and failover
closes #1874 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
7e316b5fc2
commit
75051687e6
|
@ -68,9 +68,9 @@ class DomainlessURLValidator(URLValidator):
|
|||
)
|
||||
self.schemes = ["http", "https", "blank"] + list(self.schemes)
|
||||
|
||||
def __call__(self, value):
|
||||
def __call__(self, value: str):
|
||||
# Check if the scheme is valid.
|
||||
scheme = value.split("://")[0].lower()
|
||||
if scheme not in self.schemes:
|
||||
value = "default" + value
|
||||
return super().__call__(value)
|
||||
super().__call__(value)
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import Optional, Type
|
|||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ldap3 import ALL, Connection, Server
|
||||
from ldap3 import ALL, ROUND_ROBIN, Connection, Server, ServerPool
|
||||
from rest_framework.serializers import Serializer
|
||||
|
||||
from authentik.core.models import Group, PropertyMapping, Source
|
||||
|
@ -12,11 +12,22 @@ from authentik.lib.models import DomainlessURLValidator
|
|||
LDAP_TIMEOUT = 15
|
||||
|
||||
|
||||
class MultiURLValidator(DomainlessURLValidator):
|
||||
"""Same as DomainlessURLValidator but supports multiple URLs separated with a comma."""
|
||||
|
||||
def __call__(self, value: str):
|
||||
if "," in value:
|
||||
for url in value.split(","):
|
||||
super().__call__(url)
|
||||
else:
|
||||
super().__call__(value)
|
||||
|
||||
|
||||
class LDAPSource(Source):
|
||||
"""Federate LDAP Directory with authentik, or create new accounts in LDAP."""
|
||||
|
||||
server_uri = models.TextField(
|
||||
validators=[DomainlessURLValidator(schemes=["ldap", "ldaps"])],
|
||||
validators=[MultiURLValidator(schemes=["ldap", "ldaps"])],
|
||||
verbose_name=_("Server URI"),
|
||||
)
|
||||
bind_cn = models.TextField(verbose_name=_("Bind CN"), blank=True)
|
||||
|
@ -88,9 +99,15 @@ class LDAPSource(Source):
|
|||
def connection(self) -> Connection:
|
||||
"""Get a fully connected and bound LDAP Connection"""
|
||||
if not self._connection:
|
||||
server = Server(self.server_uri, get_info=ALL, connect_timeout=LDAP_TIMEOUT)
|
||||
servers = []
|
||||
if "," in self.server_uri:
|
||||
for server in self.server_uri.split(","):
|
||||
servers.append(Server(server, get_info=ALL, connect_timeout=LDAP_TIMEOUT))
|
||||
else:
|
||||
servers = [Server(self.server_uri, get_info=ALL, connect_timeout=LDAP_TIMEOUT)]
|
||||
pool = ServerPool(servers, ROUND_ROBIN, active=True, exhaust=True)
|
||||
self._connection = Connection(
|
||||
server,
|
||||
pool,
|
||||
raise_exceptions=True,
|
||||
user=self.bind_cn,
|
||||
password=self.bind_password,
|
||||
|
|
|
@ -4199,6 +4199,10 @@ msgstr "Sources"
|
|||
msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
|
||||
msgstr "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts
|
||||
msgid "Specify multiple server URIs by separating them with a comma."
|
||||
msgstr "Specify multiple server URIs by separating them with a comma."
|
||||
|
||||
#: src/pages/flows/BoundStagesList.ts
|
||||
#: src/pages/flows/StageBindingForm.ts
|
||||
msgid "Stage"
|
||||
|
|
|
@ -4162,6 +4162,10 @@ msgstr "Sources"
|
|||
msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
|
||||
msgstr "Sources d'identités, qui peuvent soit être synchronisées dans la base de données d'Authentik, soit être utilisées par les utilisateurs pour s'authentifier et s'inscrire."
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts
|
||||
msgid "Specify multiple server URIs by separating them with a comma."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/flows/BoundStagesList.ts
|
||||
#: src/pages/flows/StageBindingForm.ts
|
||||
msgid "Stage"
|
||||
|
|
|
@ -4191,6 +4191,10 @@ msgstr ""
|
|||
msgid "Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/sources/ldap/LDAPSourceForm.ts
|
||||
msgid "Specify multiple server URIs by separating them with a comma."
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/flows/BoundStagesList.ts
|
||||
#: src/pages/flows/StageBindingForm.ts
|
||||
msgid "Stage"
|
||||
|
|
|
@ -124,6 +124,9 @@ export class LDAPSourceForm extends ModelForm<LDAPSource, string> {
|
|||
class="pf-c-form-control"
|
||||
required
|
||||
/>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${t`Specify multiple server URIs by separating them with a comma.`}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal name="startTls">
|
||||
<div class="pf-c-check">
|
||||
|
|
|
@ -43,6 +43,10 @@ Use these settings:
|
|||
|
||||
For authentik to be able to write passwords back to Active Directory, make sure to use `ldaps://`
|
||||
|
||||
You can specify multiple servers by separating URIs with a comma, like `ldap://dc1.ad.company,ldap://dc2.ad.company`.
|
||||
|
||||
When using a DNS entry with multiple Records, authentik will select a random entry when first connecting.
|
||||
|
||||
- Bind CN: `<name of your service user>@ad.company`
|
||||
- Bind Password: The password you've given the user above
|
||||
- Base DN: The base DN which you want authentik to sync
|
||||
|
|
|
@ -30,7 +30,7 @@ The following placeholders will be used:
|
|||
|
||||
```
|
||||
$ ldapmodify -x -D "cn=Directory Manager" -W -h ipa1.freeipa.company -p 389
|
||||
|
||||
|
||||
dn: cn=ipa_pwd_extop,cn=plugins,cn=config
|
||||
changetype: modify
|
||||
add: passSyncManagersDNs
|
||||
|
@ -45,6 +45,11 @@ In authentik, create a new LDAP Source in Resources -> Sources.
|
|||
Use these settings:
|
||||
|
||||
- Server URI: `ldaps://ipa1.freeipa.company`
|
||||
|
||||
You can specify multiple servers by separating URIs with a comma, like `ldap://ipa1.freeipa.company,ldap://ipa2.freeipa.company`.
|
||||
|
||||
When using a DNS entry with multiple Records, authentik will select a random entry when first connecting.
|
||||
|
||||
- Bind CN: `uid=svc_authentik,cn=users,cn=accounts,dc=freeipa,dc=company`
|
||||
- Bind Password: The password you've given the user above
|
||||
- Base DN: `dc=freeipa,dc=company`
|
||||
|
|
|
@ -15,6 +15,11 @@ For FreeIPA, follow the [FreeIPA Integration](../freeipa/index.md)
|
|||
:::
|
||||
|
||||
- Server URI: URI to your LDAP server/Domain Controller.
|
||||
|
||||
You can specify multiple servers by separating URIs with a comma, like `ldap://ldap1.company,ldap://ldap2.company`.
|
||||
|
||||
When using a DNS entry with multiple Records, authentik will select a random entry when first connecting.
|
||||
|
||||
- Bind CN: CN of the bind user. This can also be a UPN in the format of `user@domain.tld`.
|
||||
- Bind password: Password used during the bind process.
|
||||
- Enable StartTLS: Enables StartTLS functionality. To use LDAPS instead, use port `636`.
|
||||
|
|
Reference in a new issue