diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 30a393d72b..9a38bfe957 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -114,13 +114,6 @@ class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVi def _get_related_jobs(self): return UnifiedJob.objects.non_polymorphic().filter(organization=self) - def create_default_galaxy_credential(self): - from awx.main.models import Credential - - public_galaxy_credential = Credential.objects.filter(managed=True, name='Ansible Galaxy').first() - if public_galaxy_credential is not None and public_galaxy_credential not in self.galaxy_credentials.all(): - self.galaxy_credentials.add(public_galaxy_credential) - class OrganizationGalaxyCredentialMembership(models.Model): diff --git a/awx/sso/pipeline.py b/awx/sso/pipeline.py index 85bfd499fd..73d2edfce5 100644 --- a/awx/sso/pipeline.py +++ b/awx/sso/pipeline.py @@ -77,6 +77,21 @@ def _update_m2m_from_expression(user, related, expr, remove=True): related.remove(user) +def get_or_create_with_default_galaxy_cred(**kwargs): + from awx.main.models import Organization, Credential + + (org, org_created) = Organization.objects.get_or_create(**kwargs) + if org_created: + logger.debug("Created org {} (id {}) from {}".format(org.name, org.id, kwargs)) + public_galaxy_credential = Credential.objects.filter(managed=True, name='Ansible Galaxy').first() + if public_galaxy_credential is not None: + org.galaxy_credentials.add(public_galaxy_credential) + logger.debug("Added default Ansible Galaxy credential to org") + else: + logger.debug("Could not find default Ansible Galaxy credential to add to org") + return org + + 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 @@ -94,8 +109,7 @@ def _update_org_from_attr(user, related, attr, remove, remove_admins, remove_aud 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() + org = get_or_create_with_default_galaxy_cred(name=organization_name) else: org = Organization.objects.get(name=org_name) except ObjectDoesNotExist: @@ -121,7 +135,6 @@ def update_user_orgs(backend, details, user=None, *args, **kwargs): """ if not user: return - from awx.main.models import Organization org_map = backend.setting('ORGANIZATION_MAP') or {} for org_name, org_opts in org_map.items(): @@ -130,8 +143,7 @@ def update_user_orgs(backend, details, user=None, *args, **kwargs): organization_name = organization_alias else: organization_name = org_name - org = Organization.objects.get_or_create(name=organization_name)[0] - org.create_default_galaxy_credential() + org = get_or_create_with_default_galaxy_cred(name=organization_name) # Update org admins from expression(s). remove = bool(org_opts.get('remove', True)) @@ -152,15 +164,14 @@ def update_user_teams(backend, details, user=None, *args, **kwargs): """ if not user: return - from awx.main.models import Organization, Team + from awx.main.models import Team team_map = backend.setting('TEAM_MAP') or {} for team_name, team_opts in team_map.items(): # Get or create the org to update. if 'organization' not in team_opts: continue - org = Organization.objects.get_or_create(name=team_opts['organization'])[0] - org.create_default_galaxy_credential() + org = get_or_create_with_default_galaxy_cred(name=team_opts['organization']) # Update team members from expression(s). team = Team.objects.get_or_create(name=team_name, organization=org)[0] @@ -216,8 +227,7 @@ def update_user_teams_by_saml_attr(backend, details, user=None, *args, **kwargs) try: if settings.SAML_AUTO_CREATE_OBJECTS: - org = Organization.objects.get_or_create(name=organization_name)[0] - org.create_default_galaxy_credential() + org = get_or_create_with_default_galaxy_cred(name=organization_name) else: org = Organization.objects.get(name=organization_name) except ObjectDoesNotExist: diff --git a/awx/sso/tests/functional/test_pipeline.py b/awx/sso/tests/functional/test_pipeline.py index 7954ac11f3..f0d6427a34 100644 --- a/awx/sso/tests/functional/test_pipeline.py +++ b/awx/sso/tests/functional/test_pipeline.py @@ -4,8 +4,8 @@ from unittest import mock from django.utils.timezone import now +from awx.conf.registry import settings_registry from awx.sso.pipeline import update_user_orgs, update_user_teams, update_user_orgs_by_saml_attr, update_user_teams_by_saml_attr, _check_flag - from awx.main.models import User, Team, Organization, Credential, CredentialType @@ -92,8 +92,13 @@ class TestSAMLMap: 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' + if o.name == 'Default': + # The default org was already created and should not have a galaxy credential + assert o.galaxy_credentials.count() == 0 + else: + # The Default_Alias was created by SAML and should get the galaxy credential + assert o.galaxy_credentials.count() == 1 + assert o.galaxy_credentials.first().name == 'Ansible Galaxy' def test_update_user_teams(self, backend, users, galaxy_credential): u1, u2, u3 = users @@ -203,7 +208,13 @@ class TestSAMLAttr: ], } - return MockSettings() + mock_settings_obj = MockSettings() + for key in settings_registry.get_registered_settings(category_slug='logging'): + value = settings_registry.get_setting_field(key).get_default() + setattr(mock_settings_obj, key, value) + setattr(mock_settings_obj, 'DEBUG', True) + + return mock_settings_obj @pytest.fixture def backend(self): @@ -263,8 +274,13 @@ class TestSAMLAttr: 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' + if o.id in [o1.id, o2.id, o3.id]: + # o[123] were created without a default galaxy cred + assert o.galaxy_credentials.count() == 0 + else: + # anything else created should have a default galaxy cred + assert o.galaxy_credentials.count() == 1 + assert o.galaxy_credentials.first().name == 'Ansible Galaxy' def test_update_user_teams_by_saml_attr(self, orgs, users, galaxy_credential, kwargs, mock_settings): with mock.patch('django.conf.settings', mock_settings): @@ -322,8 +338,13 @@ class TestSAMLAttr: assert Team.objects.get(name='Green', organization__name='Default3').member_role.members.count() == 3 for o in Organization.objects.all(): - assert o.galaxy_credentials.count() == 1 - assert o.galaxy_credentials.first().name == 'Ansible Galaxy' + if o.id in [o1.id, o2.id, o3.id]: + # o[123] were created without a default galaxy cred + assert o.galaxy_credentials.count() == 0 + else: + # anything else created should have a default galaxy cred + assert o.galaxy_credentials.count() == 1 + assert o.galaxy_credentials.first().name == 'Ansible Galaxy' def test_update_user_teams_alias_by_saml_attr(self, orgs, users, galaxy_credential, kwargs, mock_settings): with mock.patch('django.conf.settings', mock_settings): @@ -396,6 +417,23 @@ class TestSAMLAttr: assert o.galaxy_credentials.count() == 1 assert o.galaxy_credentials.first().name == 'Ansible Galaxy' + def test_galaxy_credential_no_auto_assign(self, users, kwargs, galaxy_credential, mock_settings): + # A Galaxy credential should not be added to an existing org + o = Organization.objects.create(name='Default1') + o = Organization.objects.create(name='Default2') + o = Organization.objects.create(name='Default3') + o = Organization.objects.create(name='Default4') + kwargs['response']['attributes']['memberOf'] = ['Default1'] + kwargs['response']['attributes']['groups'] = ['Blue'] + with mock.patch('django.conf.settings', mock_settings): + for u in users: + update_user_orgs_by_saml_attr(None, None, u, **kwargs) + update_user_teams_by_saml_attr(None, None, u, **kwargs) + + assert Organization.objects.count() == 4 + for o in Organization.objects.all(): + assert o.galaxy_credentials.count() == 0 + @pytest.mark.django_db class TestSAMLUserFlags: