netbox-community / netbox

The premier source of truth powering network automation. Open source under Apache 2. Try NetBox Cloud free: https://netboxlabs.com/free-netbox-cloud/
http://netboxlabs.com/oss/netbox/
Apache License 2.0
16.15k stars 2.58k forks source link

LDAP group membership changes not reflected in Netbox #881

Closed martink2 closed 7 years ago

martink2 commented 7 years ago

We are using LDAP for authentication and authorization in Netbox with the following relevant config parts:

AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    "is_active": "CN=CP_CONV_NETBOX_USE,OU=Permissions,OU=xxx,DC=ad,DC=global,DC=cloud,DC=xxx",
    "is_staff": "CN=CP_CONV_NETBOX_OWN,OU=Permissions,OU=xxx,DC=ad,DC=global,DC=cloud,DC=xxx",
    "is_superuser": "CN=CP_CONV_NETBOX_OWN,OU=Permissions,OU=xxx,DC=ad,DC=global,DC=cloud,DC=xxx"
}

When a member of group CP_CONV_NETBOX_OWN logs in he gets the staff and superuser flags set correctly. If the user is later removed from the CP_CONV_NETBOX_OWN group and is only a member of CP_CONV_NETBOX_USE his staff and superuser status is not removed from Netbox.

Not sure if this is intended behaviour but we were assuming user permissions on LDAP users can be revoked as well.

Thanks for any advise on the topic.

specialcircumstances commented 7 years ago

Could it be related to the AUTH_LDAP_MIRROR_GROUPS setting?

AUTH_LDAP_MIRROR_GROUPS

Default: False

If True, LDAPBackend will mirror a user’s LDAP group membership in the Django database. Any time a user authenticates, we will create all of his LDAP groups as Django groups and update his Django group membership to exactly match his LDAP group membership. If the LDAP server has nested groups, the Django database will end up with a flattened representation.

[https://pythonhosted.org/django-auth-ldap/reference.html#std:setting-AUTH_LDAP_MIRROR_GROUPS]

[(https://pythonhosted.org/django-auth-ldap/permissions.html)]

martink2 commented 7 years ago

Hi,

as far as i can see AUTH_LDAP_MIRROR_GROUPS does behave like expected and mirrors the membership status.

The AUTH_LDAP_USER_FLAGS_BY_GROUP however seem to remain with a user even if he is later on removed from the group that has given him the flag.

User Login -> Member CP_CONV_NETBOX_OWN -> is SuperUser -> logout -> Remove from CP_CONV_NETBOX_OWN -> login -> still SuperUser.

specialcircumstances commented 7 years ago

I'm far from an expert here, but I had a look through the ldap module code [here]https://bitbucket.org/psagers/django-auth-ldap

The mirror groups function does a compare:

        target_group_names = frozenset(self._get_groups().get_group_names())
        current_group_names = frozenset(self._user.groups.values_list('name', flat=True).iterator())

        if target_group_names != current_group_names:

whereas the AUTH_LDAP_PROFILE_FLAGS_BY_GROUP looks like this:

    def _populate_user_from_group_memberships(self):
        for field, group_dns in self.settings.USER_FLAGS_BY_GROUP.items():
            if isinstance(group_dns, basestring):
                group_dns = [group_dns]
            value = any(self._get_groups().is_member_of(dn) for dn in group_dns)
            setattr(self._user, field, value)

but I think that should work. My understanding it it's steps through the mapped groups in AUTH_USERS_LDAP_FLAGS_BY_GROUP and checks if the mapped LDAP group is present, if there's a match then value = 1, otherwise value = 0

I guess therefore, it's not getting called... working backwards from there....

Can you try setting the following to force the populate and avoid any caching... (although these should be defaults as I understand it)

AUTH_LDAP_ALWAYS_UPDATE_USER = True AUTH_LDAP_CACHE_GROUPS = False

Should note this isn't likely to be a Netbox issue, it's more a django-auth-ldap issue, so if we get nowhere it might be worth checking with the author https://bitbucket.org/psagers/

jeremystretch commented 7 years ago

Going to close this out as there doesn't seem to be anything actionable from the dev side.