
* providers/google: initial account sync to google workspace Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start separating scim sync client Signed-off-by: Jens Langhammer <jens@goauthentik.io> * generalize more...ish Signed-off-by: Jens Langhammer <jens@goauthentik.io> * set dispatch_uid Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start generalizing task Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fully separate tasks Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix more Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix signals...? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start google dedupe Signed-off-by: Jens Langhammer <jens@goauthentik.io> * drawing the rest of the owl Signed-off-by: Jens Langhammer <jens@goauthentik.io> * more Signed-off-by: Jens Langhammer <jens@goauthentik.io> * juse use a whole lot less magic Signed-off-by: Jens Langhammer <jens@goauthentik.io> * member sync, better implement conflict/retry-able exceptions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * max wizards taller Signed-off-by: Jens Langhammer <jens@goauthentik.io> * gen api, basic UI Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix some bugs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix a bunch more bugs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * generalize sync status API Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rework sync chart Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add slugify to evaluator Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add test property mappings Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rename to google workspace Signed-off-by: Jens Langhammer <jens@goauthentik.io> * handle existing objects Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix credential render Signed-off-by: Jens Langhammer <jens@goauthentik.io> * verify email has correct domain before syncing user Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix missing docstring Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix lock not being used Signed-off-by: Jens Langhammer <jens@goauthentik.io> * abstract more common stuff away Signed-off-by: Jens Langhammer <jens@goauthentik.io> * backport time limit fix https://github.com/goauthentik/authentik/pull/9546 Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start discovery Signed-off-by: Jens Langhammer <jens@goauthentik.io> * implement discover for google Signed-off-by: Jens Langhammer <jens@goauthentik.io> * prevent same issue as with https://github.com/goauthentik/authentik/pull/9557 Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix sync status Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make group name unique in API Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix reference to old wrapper Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start adding tests man this api client is awful Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add SkipObject Signed-off-by: Jens Langhammer <jens@goauthentik.io> * dont use weak ref Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add group tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add user and group delete options Signed-off-by: Jens Langhammer <jens@goauthentik.io> * set user agent Signed-off-by: Jens Langhammer <jens@goauthentik.io> * if the api's testing tools are awful, let's just make our own Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more tests and already fix some more bugs Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add discover Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add preview banner Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add group import test Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only import users/groups in the correct parent group Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix conflicting args Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix missing schedule Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix web ui Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add default_group_email_domain Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
86 lines
3.5 KiB
Python
86 lines
3.5 KiB
Python
"""Sync LDAP Users and groups into authentik"""
|
|
|
|
from collections.abc import Generator
|
|
|
|
from django.core.exceptions import FieldError
|
|
from django.db.utils import IntegrityError
|
|
from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
|
|
|
|
from authentik.core.expression.exceptions import SkipObjectException
|
|
from authentik.core.models import Group
|
|
from authentik.events.models import Event, EventAction
|
|
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten
|
|
|
|
|
|
class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
|
"""Sync LDAP Users and groups into authentik"""
|
|
|
|
@staticmethod
|
|
def name() -> str:
|
|
return "groups"
|
|
|
|
def get_objects(self, **kwargs) -> Generator:
|
|
if not self._source.sync_groups:
|
|
self.message("Group syncing is disabled for this Source")
|
|
return iter(())
|
|
return self.search_paginator(
|
|
search_base=self.base_dn_groups,
|
|
search_filter=self._source.group_object_filter,
|
|
search_scope=SUBTREE,
|
|
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES],
|
|
**kwargs,
|
|
)
|
|
|
|
def sync(self, page_data: list) -> int:
|
|
"""Iterate over all LDAP Groups and create authentik_core.Group instances"""
|
|
if not self._source.sync_groups:
|
|
self.message("Group syncing is disabled for this Source")
|
|
return -1
|
|
group_count = 0
|
|
for group in page_data:
|
|
if "attributes" not in group:
|
|
continue
|
|
attributes = group.get("attributes", {})
|
|
group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
|
|
if self._source.object_uniqueness_field not in attributes:
|
|
self.message(
|
|
f"Cannot find uniqueness field in attributes: '{group_dn}'",
|
|
attributes=attributes.keys(),
|
|
dn=group_dn,
|
|
)
|
|
continue
|
|
uniq = flatten(attributes[self._source.object_uniqueness_field])
|
|
try:
|
|
defaults = self.build_group_properties(group_dn, **attributes)
|
|
defaults["parent"] = self._source.sync_parent_group
|
|
if "name" not in defaults:
|
|
raise IntegrityError("Name was not set by propertymappings")
|
|
# Special check for `users` field, as this is an M2M relation, and cannot be sync'd
|
|
if "users" in defaults:
|
|
del defaults["users"]
|
|
ak_group, created = self.update_or_create_attributes(
|
|
Group,
|
|
{
|
|
f"attributes__{LDAP_UNIQUENESS}": uniq,
|
|
},
|
|
defaults,
|
|
)
|
|
self._logger.debug("Created group with attributes", **defaults)
|
|
except SkipObjectException:
|
|
continue
|
|
except (IntegrityError, FieldError, TypeError, AttributeError) as exc:
|
|
Event.new(
|
|
EventAction.CONFIGURATION_ERROR,
|
|
message=(
|
|
f"Failed to create group: {str(exc)} "
|
|
"To merge new group with existing group, set the groups's "
|
|
f"Attribute '{LDAP_UNIQUENESS}' to '{uniq}'"
|
|
),
|
|
source=self._source,
|
|
dn=group_dn,
|
|
).save()
|
|
else:
|
|
self._logger.debug("Synced group", group=ak_group.name, created=created)
|
|
group_count += 1
|
|
return group_count
|