diff --git a/awx/sso/fields.py b/awx/sso/fields.py index dddd1ee6a1..78f750fbbd 100644 --- a/awx/sso/fields.py +++ b/awx/sso/fields.py @@ -740,7 +740,9 @@ class SAMLOrgAttrField(HybridDictField): 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() diff --git a/awx/sso/pipeline.py b/awx/sso/pipeline.py index 212e3824ba..6d7e05da90 100644 --- a/awx/sso/pipeline.py +++ b/awx/sso/pipeline.py @@ -187,13 +187,22 @@ def update_user_teams_by_saml_attr(backend, details, user=None, *args, **kwargs) team_ids = [] for team_name_map in team_map.get('team_org_map', []): - team_name = team_name_map.get('team', '') + 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 team_name_map.get('organization', ''): + if not organization_name: # Settings field validation should prevent this. logger.error("organization name invalid for team {}".format(team_name)) continue - org = Organization.objects.get_or_create(name=team_name_map['organization'])[0] + + if organization_alias: + organization_name = organization_alias + org = Organization.objects.get_or_create(name=organization_name)[0] + + if team_alias: + team_name = team_alias team = Team.objects.get_or_create(name=team_name, organization=org)[0] team_ids.append(team.id) diff --git a/awx/sso/tests/functional/test_pipeline.py b/awx/sso/tests/functional/test_pipeline.py index 78a04a0481..06d5503db8 100644 --- a/awx/sso/tests/functional/test_pipeline.py +++ b/awx/sso/tests/functional/test_pipeline.py @@ -193,6 +193,10 @@ class TestSAMLAttr(): {'team': 'Red', 'organization': 'Default1'}, {'team': 'Green', 'organization': 'Default1'}, {'team': 'Green', 'organization': 'Default3'}, + { + 'team': 'Yellow', 'team_alias': 'Yellow_Alias', + 'organization': 'Default4', 'organization_alias': 'Default4_Alias' + }, ] } return MockSettings() @@ -285,3 +289,18 @@ class TestSAMLAttr(): assert Team.objects.get(name='Green', organization__name='Default1').member_role.members.count() == 3 assert Team.objects.get(name='Green', organization__name='Default3').member_role.members.count() == 3 + def test_update_user_teams_alias_by_saml_attr(self, orgs, users, kwargs, mock_settings): + with mock.patch('django.conf.settings', mock_settings): + u1 = users[0] + + # Test getting teams from attribute with team->org mapping + kwargs['response']['attributes']['groups'] = ['Yellow'] + + # Ensure team and org will be created + 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 + diff --git a/awx/sso/tests/unit/test_fields.py b/awx/sso/tests/unit/test_fields.py index c63e137776..6d7505e022 100644 --- a/awx/sso/tests/unit/test_fields.py +++ b/awx/sso/tests/unit/test_fields.py @@ -71,6 +71,14 @@ class TestSAMLTeamAttrField(): {'team': 'Engineering', 'organization': 'Ansible2'}, {'team': 'Engineering2', 'organization': 'Ansible'}, ]}, + {'remove': True, 'saml_attr': 'foobar', 'team_org_map': [ + { + 'team': 'Engineering', 'team_alias': 'Engineering Team', + 'organization': 'Ansible', 'organization_alias': 'Awesome Org' + }, + {'team': 'Engineering', 'organization': 'Ansible2'}, + {'team': 'Engineering2', 'organization': 'Ansible'}, + ]}, ]) def test_internal_value_valid(self, data): field = SAMLTeamAttrField()