feat: OIDC Migrator (#7026)

AAP-48486

Add implementation to the existing oidc_migrator
This commit is contained in:
Bruno Cesar Rocha
2025-07-28 18:53:10 +01:00
committed by thedoubl3j
parent b4ba7595c6
commit 052166df39

View File

@@ -4,6 +4,8 @@ Generic OIDC authenticator migrator.
This module handles the migration of generic OIDC authenticators from AWX to Gateway. This module handles the migration of generic OIDC authenticators from AWX to Gateway.
""" """
from django.conf import settings
from awx.main.utils.gateway_mapping import org_map_to_gateway_format, team_map_to_gateway_format
from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator
@@ -12,6 +14,9 @@ class OIDCMigrator(BaseAuthenticatorMigrator):
Handles the migration of generic OIDC authenticators from AWX to Gateway. Handles the migration of generic OIDC authenticators from AWX to Gateway.
""" """
CATEGORY = "OIDC"
AUTH_TYPE = "ansible_base.authentication.authenticator_plugins.oidc"
def get_authenticator_type(self): def get_authenticator_type(self):
"""Get the human-readable authenticator type name.""" """Get the human-readable authenticator type name."""
return "OIDC" return "OIDC"
@@ -19,33 +24,85 @@ class OIDCMigrator(BaseAuthenticatorMigrator):
def get_controller_config(self): def get_controller_config(self):
""" """
Export generic OIDC authenticators. An OIDC authenticator is only exported if both, Export generic OIDC authenticators. An OIDC authenticator is only exported if both,
id and secret, are defined. Otherwise it will be skipped. key and secret, are defined. Otherwise it will be skipped.
Returns: Returns:
list: List of configured OIDC authentication providers with their settings list: List of configured OIDC authentication providers with their settings
""" """
# TODO: Implement OIDC configuration retrieval key_value = getattr(settings, "SOCIAL_AUTH_OIDC_KEY", None)
# OIDC settings typically include: secret_value = getattr(settings, "SOCIAL_AUTH_OIDC_SECRET", None)
# - SOCIAL_AUTH_OIDC_KEY oidc_endpoint = getattr(settings, "SOCIAL_AUTH_OIDC_OIDC_ENDPOINT", None)
# - SOCIAL_AUTH_OIDC_SECRET
# - SOCIAL_AUTH_OIDC_SCOPE # Skip if required settings are not configured
# - SOCIAL_AUTH_OIDC_OIDC_ENDPOINT if not key_value or not secret_value or not oidc_endpoint:
# - SOCIAL_AUTH_OIDC_VERIFY_SSL return []
# - SOCIAL_AUTH_OIDC_ORGANIZATION_MAP
# - SOCIAL_AUTH_OIDC_TEAM_MAP # Get additional OIDC configuration
found_configs = [] verify_ssl = getattr(settings, "SOCIAL_AUTH_OIDC_VERIFY_SSL", True)
return found_configs
# Get organization and team mappings
org_map_value = self.get_social_org_map("SOCIAL_AUTH_OIDC_ORGANIZATION_MAP")
team_map_value = self.get_social_team_map("SOCIAL_AUTH_OIDC_TEAM_MAP")
# Convert org and team mappings from AWX to the Gateway format
# Start with order 1 and maintain sequence across both org and team mappers
org_mappers, next_order = org_map_to_gateway_format(org_map_value, start_order=1)
team_mappers, _ = team_map_to_gateway_format(team_map_value, start_order=next_order)
config_data = {
"name": "default",
"type": self.AUTH_TYPE,
"enabled": True,
"create_objects": True,
"remove_users": False,
"configuration": {
"OIDC_ENDPOINT": oidc_endpoint,
"KEY": key_value,
"SECRET": secret_value,
"VERIFY_SSL": verify_ssl,
},
}
return [
{
"category": self.CATEGORY,
"settings": config_data,
"org_mappers": org_mappers,
"team_mappers": team_mappers,
}
]
def create_gateway_authenticator(self, config): def create_gateway_authenticator(self, config):
"""Create a generic OIDC authenticator in Gateway.""" """Create a generic OIDC authenticator in Gateway."""
# TODO: Implement OIDC authenticator creation category = config["category"]
# When implementing, use this pattern for slug generation: config_settings = config["settings"]
# client_id = settings.get('SOCIAL_AUTH_OIDC_KEY', 'oidc') name = config_settings["name"]
# authenticator_slug = self._generate_authenticator_slug('oidc', category, client_id)
# OIDC requires: # Generate authenticator name and slug
# - Client ID and secret authenticator_name = f"AWX-{category.replace(' ', '_').title()}-{name}"
# - OIDC endpoint URL authenticator_slug = self._generate_authenticator_slug("oidc", category)
# - Proper scope configuration
# - SSL verification settings self._write_output(f"\n--- Processing {category} authenticator ---")
self._write_output('OIDC authenticator creation not yet implemented', 'warning') self._write_output(f"Name: {authenticator_name}")
return False self._write_output(f"Slug: {authenticator_slug}")
self._write_output(f"Type: {config_settings['type']}")
# Build Gateway authenticator configuration
gateway_config = {
"name": authenticator_name,
"slug": authenticator_slug,
"type": config_settings["type"],
"enabled": config_settings["enabled"],
"create_objects": config_settings["create_objects"],
"remove_users": config_settings["remove_users"],
"configuration": config_settings["configuration"],
}
# OIDC authenticators have auto-generated fields that should be ignored during comparison
# CALLBACK_URL - automatically created by Gateway
# SCOPE - defaults are set by Gateway plugin
# SECRET - the secret is encrypted in Gateway, we have no way of comparing the decrypted value
ignore_keys = ['CALLBACK_URL', 'SCOPE']
# Submit the authenticator (create or update as needed)
return self.submit_authenticator(gateway_config, ignore_keys, config)