1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-02 01:21:21 +03:00

AC-448 Add support for mapping LDAP users to teams based on LDAP group membership.

This commit is contained in:
Chris Church 2014-04-15 14:22:41 -04:00
parent e8b0d7451e
commit 7eed13cca4
3 changed files with 128 additions and 4 deletions

View File

@ -13,6 +13,7 @@ class LDAPSettings(BaseLDAPSettings):
defaults = dict(BaseLDAPSettings.defaults.items() + {
'ORGANIZATION_MAP': {},
'TEAM_MAP': {},
}.items())
class LDAPBackend(BaseLDAPBackend):
@ -83,10 +84,10 @@ def _update_m2m_from_groups(user, ldap_user, rel, opts, remove=False):
@receiver(populate_user)
def on_populate_user(sender, **kwargs):
'''
Handle signal from LDAP backend to populate the user object. Update user's
organization membership according to their LDAP groups.
Handle signal from LDAP backend to populate the user object. Update user
organization/team memberships according to their LDAP groups.
'''
from awx.main.models import Organization
from awx.main.models import Organization, Team
user = kwargs['user']
ldap_user = kwargs['ldap_user']
backend = ldap_user.backend
@ -105,6 +106,18 @@ def on_populate_user(sender, **kwargs):
_update_m2m_from_groups(user, ldap_user, org.users, users_opts,
remove_users)
# Update team membership based on group memberships.
team_map = getattr(backend.settings, 'TEAM_MAP', {})
for team_name, team_opts in team_map.items():
if 'organization' not in team_opts:
continue
org, created = Organization.objects.get_or_create(name=team_opts['organization'])
team, created = Team.objects.get_or_create(name=team_name, organization=org)
users_opts = team_opts.get('users', None)
remove = bool(team_opts.get('remove', False))
_update_m2m_from_groups(user, ldap_user, team.users, users_opts,
remove)
# Update user profile to store LDAP DN.
profile = user.profile
if profile.ldap_dn != ldap_user.dn:

View File

@ -854,6 +854,39 @@ class LdapTest(BaseTest):
else:
self.assertFalse(user in org.users.all())
def test_ldap_team_mapping(self):
for name in ('USER_SEARCH', 'ALWAYS_UPDATE_USER', 'USER_ATTR_MAP',
'GROUP_SEARCH', 'GROUP_TYPE', 'USER_FLAGS_BY_GROUP'):
self.use_test_setting(name)
self.assertEqual(User.objects.filter(username=self.ldap_username).count(), 0)
self.use_test_setting('TEAM_MAP', {})
self.use_test_setting('TEAM_MAP_RESULT', {})
for team_name, team_opts in settings.AUTH_LDAP_TEAM_MAP.items():
self.assertEqual(Team.objects.filter(name=team_name).count(), 0)
self.assertEqual(Organization.objects.filter(name=team_opts['organization']).count(), 0)
user = self.check_login()
for team_name, team_opts in settings.AUTH_LDAP_TEAM_MAP.items():
self.assertEqual(Team.objects.filter(name=team_name, organization__name=team_opts['organization']).count(), 1)
for team_name, team_result in settings.AUTH_LDAP_TEAM_MAP_RESULT.items():
team = Team.objects.get(name=team_name)
if team_result.get('users', False):
self.assertTrue(user in team.users.all())
else:
self.assertFalse(user in team.users.all())
# Try again with different test mapping.
self.use_test_setting('TEAM_MAP', {}, from_name='TEAM_MAP_2')
self.use_test_setting('TEAM_MAP_RESULT', {},
from_name='TEAM_MAP_2_RESULT')
user = self.check_login()
for team_name, team_opts in settings.AUTH_LDAP_TEAM_MAP.items():
self.assertEqual(Team.objects.filter(name=team_name, organization__name=team_opts['organization']).count(), 1)
for team_name, team_result in settings.AUTH_LDAP_TEAM_MAP_RESULT.items():
team = Team.objects.get(name=team_name)
if team_result.get('users', False):
self.assertTrue(user in team.users.all())
else:
self.assertFalse(user in team.users.all())
def test_prevent_changing_ldap_user_fields(self):
for name in ('USER_SEARCH', 'ALWAYS_UPDATE_USER', 'USER_ATTR_MAP',
'GROUP_SEARCH', 'GROUP_TYPE', 'USER_FLAGS_BY_GROUP'):

View File

@ -234,7 +234,7 @@ AUTH_LDAP_USER_FLAGS_BY_GROUP = {
# If True/False, all LDAP users will be added/removed as admins.
# If a string or list of strings, specifies the group DN(s). User will be
# added as an org admin if the user is a member of ANY of these groups.
# - remove_admins: True/False. Defaults to False. If True, a user who is not an
# - remove_admins: True/False. Defaults to False. If True, a user who is not a
# member of the given groups will be removed from the organization's admins.
# - users: None, True/False, string or list/tuple of strings. Same rules apply
# as for admins.
@ -251,6 +251,33 @@ AUTH_LDAP_ORGANIZATION_MAP = {
#},
}
# Mapping between team members (users) and LDAP groups. Keys are team names
# (will be created if not present). Values are dictionaries of options for
# each team's membership, where each can contain the following parameters:
# - organization: string. The name of the organization to which the team
# belongs. The team will be created if the combination of organization and
# team name does not exist. The organization will first be created if it
# does not exist.
# - users: None, True/False, string or list/tuple of strings.
# If None, team members will not be updated.
# If True/False, all LDAP users will be added/removed as team members.
# If a string or list of strings, specifies the group DN(s). User will be
# added as a team member if the user is a member of ANY of these groups.
# - remove: True/False. Defaults to False. If True, a user who is not a member
# of the given groups will be removed from the team.
AUTH_LDAP_TEAM_MAP = {
'My Team': {
'organization': 'Test Org',
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
'remove': True,
},
'Other Team': {
'organization': 'Test Org 2',
'users': 'CN=Other Users,CN=Users,DC=example,DC=com',
'remove': False,
},
}
###############################################################################
# SCM TEST SETTINGS
###############################################################################
@ -387,6 +414,57 @@ TEST_AUTH_LDAP_ORGANIZATION_MAP_2_RESULT = {
'Test Org 2': {'admins': True, 'users': False},
}
# Test mapping between team users and LDAP groups.
TEST_AUTH_LDAP_TEAM_MAP = {
'Domain Users Team': {
'organization': 'Test Org',
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
'remove': False,
},
'Admins Team': {
'organization': 'Admins Org',
'users': 'CN=Domain Admins,CN=Users,DC=example,DC=com',
'remove': True,
},
'Everyone Team': {
'organization': 'Test Org 2',
'users': True,
},
}
# Expected results from team mapping. After login, should user be a member of
# the given team?
TEST_AUTH_LDAP_TEAM_MAP_RESULT = {
'Domain Users Team': {'users': False},
'Admins Team': {'users': True},
'Everyone Team': {'users': True},
}
# Second test mapping for teams to remove user.
TEST_AUTH_LDAP_TEAM_MAP_2 = {
'Domain Users Team': {
'organization': 'Test Org',
'users': ['CN=Domain Users,CN=Users,DC=example,DC=com'],
'remove': False,
},
'Admins Team': {
'organization': 'Admins Org',
'users': 'CN=Administrators,CN=Builtin,DC=example,DC=com',
'remove': True,
},
'Everyone Team': {
'organization': 'Test Org 2',
'users': False,
'remove': False,
},
}
# Expected results from second team mapping. After login, should user be a
# member of the given team?
TEST_AUTH_LDAP_TEAM_MAP_2_RESULT = {
'Domain Users Team': {'users': False},
'Admins Team': {'users': False},
'Everyone Team': {'users': True},
}
###############################################################################
# INVENTORY IMPORT TEST SETTINGS
###############################################################################