Change ldap provider keeping groups acl for all users

Hi all
Right now we have the following situation: Indico 3 with one ldap provider

  1. open ldap provider with circa 1500 users and 100 groups
  2. no local groups
  3. several acl applied to events categories and so on

We would like to migrate to a different ldap provider (AAD Based)

  1. The migration of users is quite simple. You have to add to every user a “secondary email” that is the identity we use to access the new ldap provider
  2. The migration of the acl is not so easy. We took a look at the indico db and you have several tables named “principal” where you have multipass_group_name and multipass_group_provider fields. Our idea is to change in “multipass_group_provider” the original ldap with the new one (aad based)

Is this the correct way to do the migration?
Is there a formal flow to follow for the migration?

Thanks
Nicola

1 Like

Why do your group names change? If they are the same, the recommendation would be to keep the same IDENTITY_PROVIDERS dict key - that way nothing needs to change in the DB at all!
If you do have to update all these acl entries let me know and I’ll share a snippet how to iterate over all the relevant models to update them.

The secondary email thing is only needed if the email is different. The login logic works like this: If there’s an indico user that has an identity which matches the provider name and identifier, then that one is used. If not, the user is looked up by email address and the user is offered to link the new login method to that account. So if the main email address stays the same, no change is needed.

Thank you very much for the quick reply

  1. Yes, the group names are the same. So we can keep the same dict key
  2. Your scripts will be anyway greatly appreciated
  3. Yes, the emails will be different. So we need to implement a logic adding a secondary email to every user

Thank you very much
Nicola

Hi, coming back to this after a number of tests, we experience the following behavior:
Group names are the same in both identity providers
TESTEVENT protection is setup with a TESTGROUP the TESTUSER is member of
The identity provider is changed from openldap to AD keeping the same dict key
TESTUSER logins with the new email (belonging to AD and already present in Indico as a primary email) and is offered to merge profiles
TESTUSER has access to TESTEVENT (up to now it is all ok as expected)
TESTGROUP is removed from TESTEVENT
TESTGROUP is added back to TESTEVENT (now retrieved from AD - this creates a new principal ID in the Indico database)
TESTUSER cannot access to the TESTEVENT.
Our feeling is that group membership is not retrieved correctly.

Find below the LDAP conf in use. Can you suggest some troubleshooting path, or point out any mistake?
Thanks!!!

#LDAP
LOCAL_IDENTITIES = False
EXTERNAL_REGISTRATION_URL = 'https://xxx'

_ldap_config = {
    'uri': 'ldaps://ldaps.mydomain.com',
    'bind_dn': 'ldapclient@mydomain.com',
    'bind_password': 'mypassword',
    'timeout': 30,
    'verify_cert': False,
    'useTLS': True,
    'page_size': 2500,

    'uid': 'userPrincipalName',
    'user_base': 'OU=AADDC Users,DC=mydomain,DC=com',
    'user_filter': '(mail=*)',

    'gid': 'cn',
    'group_base': 'OU=AADDC Users,DC=mydomain,DC=com',
    'group_filter': '(objectClass=group)',
    'member_of_attr': 'memberOf',

    'ad_group_style': True,
}


AUTH_PROVIDERS= {
    'ldap': {
        'type': 'ldap',
        'title': 'MY LDAP',
        'ldap': _ldap_config,
        'default': True
    }
}

IDENTITY_PROVIDERS = {
    'ldap': {
        'type': 'ldap',
        'title': 'MY LDAP',
        'ldap': _ldap_config,
        'mapping': {
            'first_name': 'givenName',
            'last_name': 'sn',
            'email': 'mail',
            'affiliation': 'department',
#            'phone': 'telephoneNumber',
        },
        'trusted_email': True,
        'default_group_provider': True,
#        'synced_fields': {'first_name', 'last_name', 'affiliation', 'phone', 'address'}
    }
}

Group membership check results are cached for 30 minutes. So testing changes you just made maybe problematic. The cache key uses the identity provider name and group name to identify the group.

TESTGROUP is removed from TESTEVENT
TESTGROUP is added back to TESTEVENT (now retrieved from AD - this creates a new principal ID in the Indico database)

This doesn’t change anything in the database. Multipass groups are never “stored” in the database - they are just referenced (by provider and group name) in the ACL entry. So removing and adding should not change anything.


Some things that are useful for testing via indico shell:

list(User.get(USER_ID).iter_all_multipass_groups())

This shows you a list of all the groups the user is a member of according to Indico. LDAP-wise this is a different operation than checking membership, but it’s useful nonetheless.


To check the members for a specific group (tip: you can also do this in a more high-level way in the Indico admin area):

from indico.modules.groups.core import GroupProxy
list(GroupProxy('GROUPNAME', 'PROVIDERNAME').group)

To check if a user is in a group:

from indico.modules.groups.core import GroupProxy
'USERIDENTIFIER' in GroupProxy('GROUPNAME', 'PROVIDERNAME').group

The USERIDENTIFIER is shown on the “Accounts” page when viewing the user in Indico. In the shell you can do User.get(USERID).identities to have a look at them.

thanks to your indication we found the problem:

We initially enabled the ad_groups_style flag
But, this is the point, our test user belongs to a Microsoft 365 group, not a Security group

the “get_token_groups from_user_dn” function only returns to me memberships for “security group”, not microsoft 365 (tokenGroup attribute seems to work in this way)

As soon as i turned off ad_groups_style flags, everything works fine

So we lost nested group membership, but luckly, we dont use it.

Just to summarize:
ad_groups_style works fine with security groups membership, but not with Microsoft 365 one.

To be sure we should try with another tenant to see if the behaviour is identical

Thanks again
Nicola