Added functionality to where user can add organization alias to org mapping so that the user doesn't have to match the saml attr exactly as the org name

This commit is contained in:
dluong 2021-08-18 17:38:59 -04:00 committed by Rebeccah
parent ab3de5898d
commit 9781a9094f
No known key found for this signature in database
GPG Key ID: 40B19D22F2604B29
4 changed files with 64 additions and 17 deletions

View File

@ -614,6 +614,7 @@ class SocialSingleOrganizationMapField(HybridDictField):
users = SocialMapField(allow_null=True, required=False)
remove_admins = fields.BooleanField(required=False)
remove_users = fields.BooleanField(required=False)
organization_alias = SocialMapField(allow_null=True, required=False)
child = _Forbidden()
@ -723,7 +724,6 @@ class SAMLTeamAttrTeamOrgMapField(HybridDictField):
team = fields.CharField(required=True, allow_null=False)
team_alias = fields.CharField(required=False, allow_null=True)
organization = fields.CharField(required=True, allow_null=False)
organization_alias = fields.CharField(required=False, allow_null=True)
child = _Forbidden()

View File

@ -77,7 +77,7 @@ def _update_m2m_from_expression(user, related, expr, remove=True):
related.remove(user)
def _update_org_from_attr(user, related, attr, remove, remove_admins, remove_auditors):
def _update_org_from_attr(user, related, attr, remove, remove_admins, remove_auditors, backend):
from awx.main.models import Organization
from django.conf import settings
@ -86,7 +86,15 @@ def _update_org_from_attr(user, related, attr, remove, remove_admins, remove_aud
for org_name in attr:
try:
if settings.SAML_AUTO_CREATE_OBJECTS:
org = Organization.objects.get_or_create(name=org_name)[0]
try:
organization_alias = backend.setting('ORGANIZATION_MAP').get(org_name).get('organization_alias')
if organization_alias is not None:
organization_name = organization_alias
else:
organization_name = org_name
except Exception:
organization_name = org_name
org = Organization.objects.get_or_create(name=organization_name)[0]
org.create_default_galaxy_credential()
else:
org = Organization.objects.get(name=org_name)
@ -117,7 +125,12 @@ def update_user_orgs(backend, details, user=None, *args, **kwargs):
org_map = backend.setting('ORGANIZATION_MAP') or {}
for org_name, org_opts in org_map.items():
org = Organization.objects.get_or_create(name=org_name)[0]
organization_alias = org_opts.get('organization_alias')
if organization_alias:
organization_name = organization_alias
else:
organization_name = org_name
org = Organization.objects.get_or_create(name=organization_name)[0]
org.create_default_galaxy_credential()
# Update org admins from expression(s).
@ -173,9 +186,9 @@ def update_user_orgs_by_saml_attr(backend, details, user=None, *args, **kwargs):
attr_admin_values = kwargs.get('response', {}).get('attributes', {}).get(org_map.get('saml_admin_attr'), [])
attr_auditor_values = kwargs.get('response', {}).get('attributes', {}).get(org_map.get('saml_auditor_attr'), [])
_update_org_from_attr(user, "member_role", attr_values, remove, False, False)
_update_org_from_attr(user, "admin_role", attr_admin_values, False, remove_admins, False)
_update_org_from_attr(user, "auditor_role", attr_auditor_values, False, False, remove_auditors)
_update_org_from_attr(user, "member_role", attr_values, remove, False, False, backend)
_update_org_from_attr(user, "admin_role", attr_admin_values, False, remove_admins, False, backend)
_update_org_from_attr(user, "auditor_role", attr_auditor_values, False, False, remove_auditors, backend)
def update_user_teams_by_saml_attr(backend, details, user=None, *args, **kwargs):
@ -195,16 +208,12 @@ def update_user_teams_by_saml_attr(backend, details, user=None, *args, **kwargs)
team_name = team_name_map.get('team', None)
team_alias = team_name_map.get('team_alias', None)
organization_name = team_name_map.get('organization', None)
organization_alias = team_name_map.get('organization_alias', None)
if team_name in saml_team_names:
if not organization_name:
# Settings field validation should prevent this.
logger.error("organization name invalid for team {}".format(team_name))
continue
if organization_alias:
organization_name = organization_alias
try:
if settings.SAML_AUTO_CREATE_OBJECTS:
org = Organization.objects.get_or_create(name=organization_name)[0]

View File

@ -32,7 +32,16 @@ class TestSAMLMap:
def backend(self):
class Backend:
s = {
'ORGANIZATION_MAP': {'Default': {'remove': True, 'admins': 'foobar', 'remove_admins': True, 'users': 'foo', 'remove_users': True}},
'ORGANIZATION_MAP': {
'Default': {
'remove': True,
'admins': 'foobar',
'remove_admins': True,
'users': 'foo',
'remove_users': True,
'organization_alias': '',
}
},
'TEAM_MAP': {'Blue': {'organization': 'Default', 'remove': True, 'users': ''}, 'Red': {'organization': 'Default', 'remove': True, 'users': ''}},
}
@ -77,6 +86,11 @@ class TestSAMLMap:
assert org.admin_role.members.count() == 2
assert org.member_role.members.count() == 2
# Test organization alias feature
backend.setting('ORGANIZATION_MAP')['Default']['organization_alias'] = 'Default_Alias'
update_user_orgs(backend, None, u1)
assert Organization.objects.get(name="Default_Alias") is not None
for o in Organization.objects.all():
assert o.galaxy_credentials.count() == 1
assert o.galaxy_credentials.first().name == 'Ansible Galaxy'
@ -191,7 +205,28 @@ class TestSAMLAttr:
return MockSettings()
def test_update_user_orgs_by_saml_attr(self, orgs, users, galaxy_credential, kwargs, mock_settings):
@pytest.fixture
def backend(self):
class Backend:
s = {
'ORGANIZATION_MAP': {
'Default1': {
'remove': True,
'admins': 'foobar',
'remove_admins': True,
'users': 'foo',
'remove_users': True,
'organization_alias': 'o1_alias',
}
}
}
def setting(self, key):
return self.s[key]
return Backend()
def test_update_user_orgs_by_saml_attr(self, orgs, users, galaxy_credential, kwargs, mock_settings, backend):
with mock.patch('django.conf.settings', mock_settings):
o1, o2, o3 = orgs
u1, u2, u3 = users
@ -224,6 +259,9 @@ class TestSAMLAttr:
assert o2.member_role.members.count() == 3
assert o3.member_role.members.count() == 1
update_user_orgs_by_saml_attr(backend, None, u1, **kwargs)
assert Organization.objects.get(name="o1_alias").member_role.members.count() == 1
for o in Organization.objects.all():
assert o.galaxy_credentials.count() == 1
assert o.galaxy_credentials.first().name == 'Ansible Galaxy'
@ -298,11 +336,11 @@ class TestSAMLAttr:
update_user_teams_by_saml_attr(None, None, u1, **kwargs)
assert Team.objects.filter(name='Yellow', organization__name='Default4').count() == 0
assert Team.objects.filter(name='Yellow_Alias', organization__name='Default4_Alias').count() == 1
assert Team.objects.get(name='Yellow_Alias', organization__name='Default4_Alias').member_role.members.count() == 1
assert Team.objects.filter(name='Yellow_Alias', organization__name='Default4').count() == 1
assert Team.objects.get(name='Yellow_Alias', organization__name='Default4').member_role.members.count() == 1
# only Org 4 got created/updated
org = Organization.objects.get(name='Default4_Alias')
org = Organization.objects.get(name='Default4')
assert org.galaxy_credentials.count() == 1
assert org.galaxy_credentials.first().name == 'Ansible Galaxy'

View File

@ -79,7 +79,7 @@ class TestSAMLTeamAttrField:
'remove': True,
'saml_attr': 'foobar',
'team_org_map': [
{'team': 'Engineering', 'team_alias': 'Engineering Team', 'organization': 'Ansible', 'organization_alias': 'Awesome Org'},
{'team': 'Engineering', 'team_alias': 'Engineering Team', 'organization': 'Ansible'},
{'team': 'Engineering', 'organization': 'Ansible2'},
{'team': 'Engineering2', 'organization': 'Ansible'},
],