mirror of
https://github.com/ansible/awx.git
synced 2026-01-20 22:18:01 -03:30
Aap 49570 (#7022)
* consider global org and team maps for github authenticator * consider global org and team maps for saml authenticator
This commit is contained in:
parent
c4a6b28b87
commit
e746589019
@ -3,7 +3,7 @@ Unit tests for base authenticator migrator functionality.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from unittest.mock import Mock
|
||||
from unittest.mock import Mock, patch
|
||||
from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator
|
||||
|
||||
|
||||
@ -684,3 +684,188 @@ def test_mappers_match_structurally_edge_cases(mapper1, mapper2, expected):
|
||||
|
||||
result = migrator._mappers_match_structurally(mapper1, mapper2)
|
||||
assert result == expected
|
||||
|
||||
|
||||
class TestSocialAuthMapFunctions:
|
||||
"""Test cases for social auth map functions."""
|
||||
|
||||
def setup_method(self):
|
||||
"""Set up test fixtures."""
|
||||
self.gateway_client = Mock()
|
||||
self.command_obj = Mock()
|
||||
self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command_obj)
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_org_map_with_authenticator_specific_setting(self, mock_settings):
|
||||
"""Test get_social_org_map returns authenticator-specific setting when available."""
|
||||
# Set up mock settings
|
||||
authenticator_map = {'org1': ['team1', 'team2']}
|
||||
global_map = {'global_org': ['global_team']}
|
||||
|
||||
mock_settings.SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP = authenticator_map
|
||||
mock_settings.SOCIAL_AUTH_ORGANIZATION_MAP = global_map
|
||||
|
||||
# Mock getattr to return the specific setting
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP': authenticator_map,
|
||||
'SOCIAL_AUTH_ORGANIZATION_MAP': global_map,
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_org_map('SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP')
|
||||
|
||||
assert result == authenticator_map
|
||||
# Verify it was called with the authenticator-specific setting first
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP', None)
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_org_map_fallback_to_global(self, mock_settings):
|
||||
"""Test get_social_org_map falls back to global setting when authenticator-specific is empty."""
|
||||
# Set up mock settings
|
||||
global_map = {'global_org': ['global_team']}
|
||||
|
||||
# Mock getattr to return None for authenticator-specific, global for fallback
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP': None,
|
||||
'SOCIAL_AUTH_ORGANIZATION_MAP': global_map,
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_org_map('SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP')
|
||||
|
||||
assert result == global_map
|
||||
# Verify both calls were made
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP', None)
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_ORGANIZATION_MAP', {})
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_org_map_empty_dict_fallback(self, mock_settings):
|
||||
"""Test get_social_org_map returns empty dict when neither setting exists."""
|
||||
# Mock getattr to return None for both settings
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP': None, 'SOCIAL_AUTH_ORGANIZATION_MAP': {}}.get(
|
||||
name, default
|
||||
)
|
||||
|
||||
result = self.migrator.get_social_org_map('SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP')
|
||||
|
||||
assert result == {}
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_team_map_with_authenticator_specific_setting(self, mock_settings):
|
||||
"""Test get_social_team_map returns authenticator-specific setting when available."""
|
||||
# Set up mock settings
|
||||
authenticator_map = {'team1': {'organization': 'org1'}}
|
||||
global_map = {'global_team': {'organization': 'global_org'}}
|
||||
|
||||
# Mock getattr to return the specific setting
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
'SOCIAL_AUTH_GITHUB_TEAM_MAP': authenticator_map,
|
||||
'SOCIAL_AUTH_TEAM_MAP': global_map,
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_team_map('SOCIAL_AUTH_GITHUB_TEAM_MAP')
|
||||
|
||||
assert result == authenticator_map
|
||||
# Verify it was called with the authenticator-specific setting first
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_GITHUB_TEAM_MAP', None)
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_team_map_fallback_to_global(self, mock_settings):
|
||||
"""Test get_social_team_map falls back to global setting when authenticator-specific is empty."""
|
||||
# Set up mock settings
|
||||
global_map = {'global_team': {'organization': 'global_org'}}
|
||||
|
||||
# Mock getattr to return None for authenticator-specific, global for fallback
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {'SOCIAL_AUTH_GITHUB_TEAM_MAP': None, 'SOCIAL_AUTH_TEAM_MAP': global_map}.get(
|
||||
name, default
|
||||
)
|
||||
|
||||
result = self.migrator.get_social_team_map('SOCIAL_AUTH_GITHUB_TEAM_MAP')
|
||||
|
||||
assert result == global_map
|
||||
# Verify both calls were made
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_GITHUB_TEAM_MAP', None)
|
||||
mock_getattr.assert_any_call(mock_settings, 'SOCIAL_AUTH_TEAM_MAP', {})
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_team_map_empty_dict_fallback(self, mock_settings):
|
||||
"""Test get_social_team_map returns empty dict when neither setting exists."""
|
||||
# Mock getattr to return None for both settings
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {'SOCIAL_AUTH_GITHUB_TEAM_MAP': None, 'SOCIAL_AUTH_TEAM_MAP': {}}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_team_map('SOCIAL_AUTH_GITHUB_TEAM_MAP')
|
||||
|
||||
assert result == {}
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_org_map_with_empty_string_fallback(self, mock_settings):
|
||||
"""Test get_social_org_map falls back to global when authenticator-specific is empty string."""
|
||||
# Set up mock settings
|
||||
global_map = {'global_org': ['global_team']}
|
||||
|
||||
# Mock getattr to return empty string for authenticator-specific
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP': '',
|
||||
'SOCIAL_AUTH_ORGANIZATION_MAP': global_map,
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_org_map('SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP')
|
||||
|
||||
assert result == global_map
|
||||
|
||||
@patch('awx.sso.utils.base_migrator.settings')
|
||||
def test_get_social_team_map_with_empty_dict_fallback(self, mock_settings):
|
||||
"""Test get_social_team_map falls back to global when authenticator-specific is empty dict."""
|
||||
# Set up mock settings
|
||||
global_map = {'global_team': {'organization': 'global_org'}}
|
||||
|
||||
# Mock getattr to return empty dict for authenticator-specific
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {'SOCIAL_AUTH_GITHUB_TEAM_MAP': {}, 'SOCIAL_AUTH_TEAM_MAP': global_map}.get(
|
||||
name, default
|
||||
)
|
||||
|
||||
result = self.migrator.get_social_team_map('SOCIAL_AUTH_GITHUB_TEAM_MAP')
|
||||
|
||||
# Empty dict is falsy, so it should fall back to global
|
||||
assert result == global_map
|
||||
|
||||
def test_get_social_org_map_different_authenticators(self):
|
||||
"""Test get_social_org_map works with different authenticator setting names."""
|
||||
test_cases = [
|
||||
'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP',
|
||||
'SOCIAL_AUTH_AZUREAD_OAUTH2_ORGANIZATION_MAP',
|
||||
'SOCIAL_AUTH_SAML_ORGANIZATION_MAP',
|
||||
'SOCIAL_AUTH_OIDC_ORGANIZATION_MAP',
|
||||
]
|
||||
|
||||
for setting_name in test_cases:
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
setting_name: {'test_org': ['test_team']},
|
||||
'SOCIAL_AUTH_ORGANIZATION_MAP': {'fallback_org': ['fallback_team']},
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_org_map(setting_name)
|
||||
|
||||
assert result == {'test_org': ['test_team']}
|
||||
|
||||
def test_get_social_team_map_different_authenticators(self):
|
||||
"""Test get_social_team_map works with different authenticator setting names."""
|
||||
test_cases = ['SOCIAL_AUTH_GITHUB_TEAM_MAP', 'SOCIAL_AUTH_AZUREAD_OAUTH2_TEAM_MAP', 'SOCIAL_AUTH_SAML_TEAM_MAP', 'SOCIAL_AUTH_OIDC_TEAM_MAP']
|
||||
|
||||
for setting_name in test_cases:
|
||||
with patch('awx.sso.utils.base_migrator.getattr') as mock_getattr:
|
||||
mock_getattr.side_effect = lambda obj, name, default=None: {
|
||||
setting_name: {'test_team': {'organization': 'test_org'}},
|
||||
'SOCIAL_AUTH_TEAM_MAP': {'fallback_team': {'organization': 'fallback_org'}},
|
||||
}.get(name, default)
|
||||
|
||||
result = self.migrator.get_social_team_map(setting_name)
|
||||
|
||||
assert result == {'test_team': {'organization': 'test_org'}}
|
||||
|
||||
@ -4,6 +4,7 @@ Base authenticator migrator class.
|
||||
This module defines the contract that all specific authenticator migrators must follow.
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
from awx.main.utils.gateway_client import GatewayAPIError
|
||||
|
||||
|
||||
@ -512,6 +513,46 @@ class BaseAuthenticatorMigrator:
|
||||
self._write_output(f' ✗ Unexpected error creating {mapper_type} mapper "{mapper_name}": {str(e)}', 'error')
|
||||
return False
|
||||
|
||||
def get_social_org_map(self, authenticator_setting_name):
|
||||
"""
|
||||
Get social auth organization map with fallback to global setting.
|
||||
|
||||
Args:
|
||||
authenticator_setting_name: Name of the authenticator-specific organization map setting
|
||||
(e.g., 'SOCIAL_AUTH_GITHUB_ORGANIZATION_MAP')
|
||||
|
||||
Returns:
|
||||
dict: Organization mapping configuration, with fallback to global setting
|
||||
"""
|
||||
# Try authenticator-specific setting first
|
||||
authenticator_map = getattr(settings, authenticator_setting_name, None)
|
||||
if authenticator_map:
|
||||
return authenticator_map
|
||||
|
||||
# Fall back to global setting
|
||||
global_map = getattr(settings, 'SOCIAL_AUTH_ORGANIZATION_MAP', {})
|
||||
return global_map
|
||||
|
||||
def get_social_team_map(self, authenticator_setting_name):
|
||||
"""
|
||||
Get social auth team map with fallback to global setting.
|
||||
|
||||
Args:
|
||||
authenticator_setting_name: Name of the authenticator-specific team map setting
|
||||
(e.g., 'SOCIAL_AUTH_GITHUB_TEAM_MAP')
|
||||
|
||||
Returns:
|
||||
dict: Team mapping configuration, with fallback to global setting
|
||||
"""
|
||||
# Try authenticator-specific setting first
|
||||
authenticator_map = getattr(settings, authenticator_setting_name, None)
|
||||
if authenticator_map:
|
||||
return authenticator_map
|
||||
|
||||
# Fall back to global setting
|
||||
global_map = getattr(settings, 'SOCIAL_AUTH_TEAM_MAP', {})
|
||||
return global_map
|
||||
|
||||
def _write_output(self, message, style=None):
|
||||
"""Write output message if command is available."""
|
||||
if self.command:
|
||||
|
||||
@ -66,8 +66,8 @@ class GitHubMigrator(BaseAuthenticatorMigrator):
|
||||
continue
|
||||
|
||||
# If we have both key and secret, collect all settings
|
||||
org_map_value = None
|
||||
team_map_value = None
|
||||
org_map_setting_name = None
|
||||
team_map_setting_name = None
|
||||
|
||||
for setting_name in category_settings:
|
||||
# Skip if setting_name is not a string (e.g., regex pattern)
|
||||
@ -76,11 +76,15 @@ class GitHubMigrator(BaseAuthenticatorMigrator):
|
||||
value = getattr(settings, setting_name, None)
|
||||
config_data[setting_name] = value
|
||||
|
||||
# Capture org and team map values for special processing
|
||||
# Capture org and team map setting names for special processing
|
||||
if setting_name.endswith('_ORGANIZATION_MAP'):
|
||||
org_map_value = value
|
||||
org_map_setting_name = setting_name
|
||||
elif setting_name.endswith('_TEAM_MAP'):
|
||||
team_map_value = value
|
||||
team_map_setting_name = setting_name
|
||||
|
||||
# Get org and team mappings using the new fallback functions
|
||||
org_map_value = self.get_social_org_map(org_map_setting_name) if org_map_setting_name else {}
|
||||
team_map_value = self.get_social_team_map(team_map_setting_name) if team_map_setting_name else {}
|
||||
|
||||
# Convert GitHub org and team mappings from AWX to the Gateway format
|
||||
# Start with order 1 and maintain sequence across both org and team mappers
|
||||
|
||||
@ -49,8 +49,9 @@ class SAMLMigrator(BaseAuthenticatorMigrator):
|
||||
idps = getattr(settings, "SOCIAL_AUTH_SAML_ENABLED_IDPS", {})
|
||||
security_config = getattr(settings, "SOCIAL_AUTH_SAML_SECURITY_CONFIG", {})
|
||||
|
||||
org_map_value = getattr(settings, "SOCIAL_AUTH_SAML_ORGANIZATION_MAP", None)
|
||||
team_map_value = getattr(settings, "SOCIAL_AUTH_SAML_TEAM_MAP", None)
|
||||
# Get org and team mappings using the new fallback functions
|
||||
org_map_value = self.get_social_org_map("SOCIAL_AUTH_SAML_ORGANIZATION_MAP")
|
||||
team_map_value = self.get_social_team_map("SOCIAL_AUTH_SAML_TEAM_MAP")
|
||||
extra_data = getattr(settings, "SOCIAL_AUTH_SAML_EXTRA_DATA", None)
|
||||
support_contact = getattr(settings, "SOCIAL_AUTH_SAML_SUPPORT_CONTACT", {})
|
||||
technical_contact = getattr(settings, "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT", {})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user