From 55a7591f89526bc498a67b8c39f4ea34f72f49c1 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Fri, 12 Sep 2025 12:10:50 -0400 Subject: [PATCH] Resolve actions conflicts and delete unwatned files Bump migrations and delete some files Resolve remaining conflicts Fix requirements Flake8 fixes Prefer devel changes for schema Use correct versions Remove sso connected stuff Update to modern actions and collection fixes Remove unwated alias Version problems in actions Fix more versioning problems Update warning string Messed it up again Shorten exception More removals Remove pbr license Remove tests deleted in devel Remove unexpected files Remove some content missed in the rebase Use sleep_task from devel Restore devel live conftest file Add in settings that got missed Prefer devel version of collection test Finish repairing .github path Remove unintended test file duplication Undo more unintended file additions --- .github/actions/awx_devel_image/action.yml | 22 - .github/actions/run_awx_devel/action.yml | 2 +- .github/workflows/ci.yml | 52 +- .github/workflows/devel_images.yml | 22 - .github/workflows/docs.yml | 4 - .github/workflows/label_pr.yml | 4 - .github/workflows/upload_schema.yml | 41 - Makefile | 4 +- awx/api/generics.py | 4 +- awx/api/views/__init__.py | 1 - awx/main/credential_plugins/aim.py | 140 -- awx/main/credential_plugins/azure_kv.py | 114 -- awx/main/credential_plugins/github_app.py | 176 -- .../commands/import_auth_config_to_gateway.py | 247 --- awx/main/migrations/0192_custom_roles.py | 2 +- ...eletions.py => 0204_squashed_deletions.py} | 2 +- awx/main/migrations/_dab_rbac.py | 31 - awx/main/models/credential/__init__.py | 1421 ----------------- awx/main/models/rbac.py | 75 - awx/main/tasks/jobs.py | 3 - awx/main/tasks/system.py | 26 - .../inventory/plugins/vmware_esxi/env.json | 6 - .../projects/host_query/meta/event_query.yml | 4 - awx/main/tests/data/sleep_task.py | 44 +- awx/main/tests/functional/github_app_test.py | 344 ---- .../functional/test_credential_plugins.py | 217 --- awx/main/tests/functional/test_ha.py | 45 - .../functional/test_jt_rename_migration.py | 56 - awx/main/tests/functional/test_migrations.py | 1 - awx/main/tests/functional/test_tasks.py | 96 -- awx/main/tests/live/tests/conftest.py | 55 +- .../test_import_auth_config_to_gateway.py | 581 ------- awx/main/tests/unit/test_tasks.py | 308 ---- .../tests/unit/utils/test_auth_migration.py | 1137 ------------- .../tests/unit/utils/test_base_migrator.py | 1243 -------------- .../tests/unit/utils/test_github_migrator.py | 124 -- .../tests/unit/utils/test_ldap_migrator.py | 1024 ------------ .../tests/unit/utils/test_role_mapping.py | 614 ------- awx/main/utils/gateway_client.py | 511 ------ awx/main/utils/gateway_client_svc_token.py | 77 - awx/main/utils/gateway_mapping.py | 361 ----- awx/settings/development_defaults.py | 1 + awx/settings/production_defaults.py | 5 + awx/sso/backends.py | 469 ------ awx/sso/middleware.py | 83 - awx/sso/tests/conftest.py | 150 -- .../tests/unit/test_google_oauth2_migrator.py | 104 -- awx/sso/tests/unit/test_radius_migrator.py | 17 - awx/sso/tests/unit/test_saml_migrator.py | 272 ---- awx/sso/tests/unit/test_settings_migrator.py | 384 ----- awx/sso/tests/unit/test_tacacs_migrator.py | 37 - awx/sso/utils/__init__.py | 17 - awx/sso/utils/azure_ad_migrator.py | 97 -- awx/sso/utils/base_migrator.py | 679 -------- awx/sso/utils/github_migrator.py | 217 --- awx/sso/utils/google_oauth2_migrator.py | 102 -- awx/sso/utils/ldap_migrator.py | 368 ----- awx/sso/utils/oidc_migrator.py | 113 -- awx/sso/utils/radius_migrator.py | 85 - awx/sso/utils/saml_migrator.py | 308 ---- awx/sso/utils/settings_migrator.py | 197 --- awx/sso/utils/tacacs_migrator.py | 93 -- awx_collection/README.md | 3 - awx_collection/meta/runtime.yml | 7 - awx_collection/plugins/doc_fragments/auth.py | 1 - .../plugins/doc_fragments/auth_plugin.py | 9 - .../plugins/lookup/schedule_rrule.py | 6 - .../plugins/lookup/schedule_rruleset.py | 14 - .../plugins/module_utils/controller_api.py | 21 - awx_collection/plugins/modules/application.py | 166 -- awx_collection/plugins/modules/schedule.py | 5 - awx_collection/test/awx/conftest.py | 3 - awx_collection/test/awx/test_organization.py | 9 - awx_collection/test/awx/test_token.py | 30 - .../targets/credential/tasks/main.yml | 27 - .../targets/schedule_rrule/tasks/main.yml | 17 - .../integration/targets/token/tasks/main.yml | 154 -- .../template_galaxy/templates/README.md.j2 | 4 - licenses/pbr.txt | 176 -- licenses/pygithub-2.6.0.tar.gz | Bin 3655590 -> 0 bytes pytest.ini | 2 +- requirements/requirements.txt | 13 +- requirements/requirements_git.txt | 6 - 83 files changed, 103 insertions(+), 13609 deletions(-) delete mode 100644 awx/main/credential_plugins/aim.py delete mode 100644 awx/main/credential_plugins/azure_kv.py delete mode 100644 awx/main/credential_plugins/github_app.py delete mode 100644 awx/main/management/commands/import_auth_config_to_gateway.py rename awx/main/migrations/{0202_squashed_deletions.py => 0204_squashed_deletions.py} (99%) delete mode 100644 awx/main/models/credential/__init__.py delete mode 100644 awx/main/tests/data/inventory/plugins/vmware_esxi/env.json delete mode 100644 awx/main/tests/data/projects/host_query/meta/event_query.yml delete mode 100644 awx/main/tests/functional/github_app_test.py delete mode 100644 awx/main/tests/functional/test_credential_plugins.py delete mode 100644 awx/main/tests/functional/test_ha.py delete mode 100644 awx/main/tests/functional/test_jt_rename_migration.py delete mode 100644 awx/main/tests/functional/test_tasks.py delete mode 100644 awx/main/tests/unit/commands/test_import_auth_config_to_gateway.py delete mode 100644 awx/main/tests/unit/utils/test_auth_migration.py delete mode 100644 awx/main/tests/unit/utils/test_base_migrator.py delete mode 100644 awx/main/tests/unit/utils/test_github_migrator.py delete mode 100644 awx/main/tests/unit/utils/test_ldap_migrator.py delete mode 100644 awx/main/tests/unit/utils/test_role_mapping.py delete mode 100644 awx/main/utils/gateway_client.py delete mode 100644 awx/main/utils/gateway_client_svc_token.py delete mode 100644 awx/main/utils/gateway_mapping.py delete mode 100644 awx/sso/backends.py delete mode 100644 awx/sso/middleware.py delete mode 100644 awx/sso/tests/conftest.py delete mode 100644 awx/sso/tests/unit/test_google_oauth2_migrator.py delete mode 100644 awx/sso/tests/unit/test_radius_migrator.py delete mode 100644 awx/sso/tests/unit/test_saml_migrator.py delete mode 100644 awx/sso/tests/unit/test_settings_migrator.py delete mode 100644 awx/sso/tests/unit/test_tacacs_migrator.py delete mode 100644 awx/sso/utils/__init__.py delete mode 100644 awx/sso/utils/azure_ad_migrator.py delete mode 100644 awx/sso/utils/base_migrator.py delete mode 100644 awx/sso/utils/github_migrator.py delete mode 100644 awx/sso/utils/google_oauth2_migrator.py delete mode 100644 awx/sso/utils/ldap_migrator.py delete mode 100644 awx/sso/utils/oidc_migrator.py delete mode 100644 awx/sso/utils/radius_migrator.py delete mode 100644 awx/sso/utils/saml_migrator.py delete mode 100644 awx/sso/utils/settings_migrator.py delete mode 100644 awx/sso/utils/tacacs_migrator.py delete mode 100644 awx_collection/plugins/modules/application.py delete mode 100644 awx_collection/test/awx/test_token.py delete mode 100644 awx_collection/tests/integration/targets/token/tasks/main.yml delete mode 100644 licenses/pbr.txt delete mode 100644 licenses/pygithub-2.6.0.tar.gz diff --git a/.github/actions/awx_devel_image/action.yml b/.github/actions/awx_devel_image/action.yml index 04ac1a2d1f..354279f2c3 100644 --- a/.github/actions/awx_devel_image/action.yml +++ b/.github/actions/awx_devel_image/action.yml @@ -24,31 +24,9 @@ runs: run: | echo "${{ inputs.github-token }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin -<<<<<<< HEAD - uses: ./.github/actions/setup-ssh-agent with: ssh-private-key: ${{ inputs.private-github-key }} -======= - - name: Generate placeholder SSH private key if SSH auth for private repos is not needed - id: generate_key - shell: bash - run: | - if [[ -z "${{ inputs.private-github-key }}" ]]; then - ssh-keygen -t ed25519 -C "github-actions" -N "" -f ~/.ssh/id_ed25519 - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - cat ~/.ssh/id_ed25519 >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - echo "${{ inputs.private-github-key }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - fi - - - name: Add private GitHub key to SSH agent - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ steps.generate_key.outputs.SSH_PRIVATE_KEY }} ->>>>>>> tower/test_stable-2.6 - name: Pre-pull latest devel image to warm cache shell: bash diff --git a/.github/actions/run_awx_devel/action.yml b/.github/actions/run_awx_devel/action.yml index 352bb95621..723e247783 100644 --- a/.github/actions/run_awx_devel/action.yml +++ b/.github/actions/run_awx_devel/action.yml @@ -36,7 +36,7 @@ runs: - name: Upgrade ansible-core shell: bash - run: python3 -m pip install --upgrade 'ansible-core<2.18.0' + run: python3 -m pip install --upgrade ansible-core - name: Install system deps shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 687715c1aa..8469141412 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,16 +39,12 @@ jobs: command: /start_tests.sh test_collection_all coverage-upload-name: "awx-collection" - name: api-schema -<<<<<<< HEAD command: >- /start_tests.sh detect-schema-change SCHEMA_DIFF_BASE_BRANCH=${{ github.event.pull_request.base.ref || github.ref_name }} coverage-upload-name: "" -======= - command: /start_tests.sh detect-schema-change SCHEMA_DIFF_BASE_BRANCH=${{ github.event.pull_request.base.ref }} ->>>>>>> tower/test_stable-2.6 steps: - uses: actions/checkout@v4 with: @@ -134,15 +130,9 @@ jobs: with: show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python with: python-version: '3.x' -======= - - uses: actions/setup-python@v5 - with: - python-version: '3.12' ->>>>>>> tower/test_stable-2.6 - uses: ./.github/actions/run_awx_devel id: awx @@ -153,14 +143,11 @@ jobs: - name: Run live dev env tests run: docker exec tools_awx_1 /bin/bash -c "make live_test" -<<<<<<< HEAD - uses: ./.github/actions/upload_awx_devel_logs if: always() with: log-filename: live-tests.log -======= ->>>>>>> tower/test_stable-2.6 awx-operator: runs-on: ubuntu-latest @@ -185,34 +172,15 @@ jobs: repository: ansible/awx-operator path: awx-operator - - uses: ./awx/.github/actions/setup-python + - name: Setup python, referencing action at awx relative path + uses: ./awx/.github/actions/setup-python with: - working-directory: awx + python-version: '3.x' - name: Install playbook dependencies run: | python3 -m pip install docker - - name: Generate placeholder SSH private key if SSH auth for private repos is not needed - id: generate_key - shell: bash - run: | - if [[ -z "${{ secrets.PRIVATE_GITHUB_KEY }}" ]]; then - ssh-keygen -t ed25519 -C "github-actions" -N "" -f ~/.ssh/id_ed25519 - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - cat ~/.ssh/id_ed25519 >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - echo "${{ secrets.PRIVATE_GITHUB_KEY }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - fi - - - name: Add private GitHub key to SSH agent - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ steps.generate_key.outputs.SSH_PRIVATE_KEY }} - - name: Build AWX image working-directory: awx run: | @@ -311,15 +279,9 @@ jobs: with: show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python with: python-version: '3.x' -======= - - uses: actions/setup-python@v5 - with: - python-version: '3.12' ->>>>>>> tower/test_stable-2.6 - uses: ./.github/actions/run_awx_devel id: awx @@ -395,18 +357,12 @@ jobs: persist-credentials: false show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python with: python-version: '3.x' -======= - - uses: actions/setup-python@v5 - with: - python-version: '3.12' ->>>>>>> tower/test_stable-2.6 - name: Upgrade ansible-core - run: python3 -m pip install --upgrade "ansible-core<2.19" + run: python3 -m pip install --upgrade ansible-core - name: Download coverage artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/devel_images.yml b/.github/workflows/devel_images.yml index 0f5a13c47b..213d90b8ec 100644 --- a/.github/workflows/devel_images.yml +++ b/.github/workflows/devel_images.yml @@ -70,31 +70,9 @@ jobs: make ui if: matrix.build-targets.image-name == 'awx' -<<<<<<< HEAD - uses: ./.github/actions/setup-ssh-agent with: ssh-private-key: ${{ secrets.PRIVATE_GITHUB_KEY }} -======= - - name: Generate placeholder SSH private key if SSH auth for private repos is not needed - id: generate_key - shell: bash - run: | - if [[ -z "${{ secrets.PRIVATE_GITHUB_KEY }}" ]]; then - ssh-keygen -t ed25519 -C "github-actions" -N "" -f ~/.ssh/id_ed25519 - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - cat ~/.ssh/id_ed25519 >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - echo "${{ secrets.PRIVATE_GITHUB_KEY }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - fi - - - name: Add private GitHub key to SSH agent - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ steps.generate_key.outputs.SSH_PRIVATE_KEY }} ->>>>>>> tower/test_stable-2.6 - name: Build and push AWX devel images run: | diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f075e4bf18..ec6c9f4a4f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,11 +12,7 @@ jobs: with: show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python -======= - - uses: actions/setup-python@v5 ->>>>>>> tower/test_stable-2.6 with: python-version: '3.x' diff --git a/.github/workflows/label_pr.yml b/.github/workflows/label_pr.yml index a3255c8d0b..43f1e3a291 100644 --- a/.github/workflows/label_pr.yml +++ b/.github/workflows/label_pr.yml @@ -33,11 +33,7 @@ jobs: with: show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python -======= - - uses: actions/setup-python@v5 ->>>>>>> tower/test_stable-2.6 with: python-version: '3.x' diff --git a/.github/workflows/upload_schema.yml b/.github/workflows/upload_schema.yml index 639c68034f..f2e1d109f9 100644 --- a/.github/workflows/upload_schema.yml +++ b/.github/workflows/upload_schema.yml @@ -24,64 +24,23 @@ jobs: with: show-progress: false -<<<<<<< HEAD - uses: ./.github/actions/setup-python -======= - - name: Set lower case owner name - shell: bash - run: echo "OWNER_LC=${OWNER,,}" >> $GITHUB_ENV - env: - OWNER: '${{ github.repository_owner }}' - - - name: Get python version from Makefile - run: echo py_version=`make PYTHON_VERSION` >> $GITHUB_ENV - - - name: Install python ${{ env.py_version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ env.py_version }} ->>>>>>> tower/test_stable-2.6 - name: Log in to registry run: | echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin -<<<<<<< HEAD - uses: ./.github/actions/setup-ssh-agent with: ssh-private-key: ${{ secrets.PRIVATE_GITHUB_KEY }} - name: Pre-pull image to warm build cache -======= - - name: Pre-pull latest devel image to warm cache - shell: bash ->>>>>>> tower/test_stable-2.6 run: | DEV_DOCKER_TAG_BASE=ghcr.io/${OWNER_LC} \ COMPOSE_TAG=${{ github.base_ref || github.ref_name }} \ docker pull -q `make print-DEVEL_IMAGE_NAME` continue-on-error: true - - name: Generate placeholder SSH private key if SSH auth for private repos is not needed - id: generate_key - shell: bash - run: | - if [[ -z "${{ secrets.PRIVATE_GITHUB_KEY }}" ]]; then - ssh-keygen -t ed25519 -C "github-actions" -N "" -f ~/.ssh/id_ed25519 - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - cat ~/.ssh/id_ed25519 >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - else - echo "SSH_PRIVATE_KEY<> $GITHUB_OUTPUT - echo "${{ secrets.PRIVATE_GITHUB_KEY }}" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - fi - - - name: Add private GitHub key to SSH agent - uses: webfactory/ssh-agent@v0.9.0 - with: - ssh-private-key: ${{ steps.generate_key.outputs.SSH_PRIVATE_KEY }} - - name: Build image run: | DEV_DOCKER_TAG_BASE=ghcr.io/${OWNER_LC} \ diff --git a/Makefile b/Makefile index aa01487ebc..3bc3f0adc5 100644 --- a/Makefile +++ b/Makefile @@ -378,7 +378,7 @@ test_collection: if [ "$(VENV_BASE)" ]; then \ . $(VENV_BASE)/awx/bin/activate; \ fi && \ - if ! [ -x "$(shell command -v ansible-playbook)" ]; then pip install "ansible-core<2.19"; fi + if ! [ -x "$(shell command -v ansible-playbook)" ]; then pip install ansible-core; fi ansible --version py.test $(COLLECTION_TEST_DIRS) $(COVERAGE_ARGS) -v @if [ "${GITHUB_ACTIONS}" = "true" ]; \ @@ -417,7 +417,7 @@ install_collection: build_collection test_collection_sanity: rm -rf awx_collection_build/ rm -rf $(COLLECTION_INSTALL) - if ! [ -x "$(shell command -v ansible-test)" ]; then pip install "ansible-core<2.19"; fi + if ! [ -x "$(shell command -v ansible-test)" ]; then pip install ansible-core; fi ansible --version COLLECTION_VERSION=1.0.0 $(MAKE) install_collection cd $(COLLECTION_INSTALL) && \ diff --git a/awx/api/generics.py b/awx/api/generics.py index 3a8815a306..bfb3da5774 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -162,9 +162,9 @@ def get_view_description(view, html=False): def get_default_schema(): if settings.DYNACONF.is_development_mode: - from awx.api.swagger import AutoSchema + from awx.api.swagger import schema_view - return AutoSchema() + return schema_view else: return views.APIView.schema diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 00b8311f43..64e4c87a5d 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -56,7 +56,6 @@ from wsgiref.util import FileWrapper # django-ansible-base from ansible_base.lib.utils.requests import get_remote_hosts from ansible_base.rbac.models import RoleEvaluation -from ansible_base.rbac import permission_registry # AWX from awx.main.tasks.system import send_notifications, update_inventory_computed_fields diff --git a/awx/main/credential_plugins/aim.py b/awx/main/credential_plugins/aim.py deleted file mode 100644 index 1e7af94e33..0000000000 --- a/awx/main/credential_plugins/aim.py +++ /dev/null @@ -1,140 +0,0 @@ -from .plugin import CredentialPlugin, CertFiles, raise_for_status - -from urllib.parse import quote, urlencode, urljoin - -from django.utils.translation import gettext_lazy as _ -import requests as requests - -aim_inputs = { - 'fields': [ - { - 'id': 'url', - 'label': _('CyberArk CCP URL'), - 'type': 'string', - 'format': 'url', - }, - { - 'id': 'webservice_id', - 'label': _('Web Service ID'), - 'type': 'string', - 'help_text': _('The CCP Web Service ID. Leave blank to default to AIMWebService.'), - }, - { - 'id': 'app_id', - 'label': _('Application ID'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'client_key', - 'label': _('Client Key'), - 'type': 'string', - 'secret': True, - 'multiline': True, - }, - { - 'id': 'client_cert', - 'label': _('Client Certificate'), - 'type': 'string', - 'secret': True, - 'multiline': True, - }, - { - 'id': 'verify', - 'label': _('Verify SSL Certificates'), - 'type': 'boolean', - 'default': True, - }, - ], - 'metadata': [ - { - 'id': 'object_query', - 'label': _('Object Query'), - 'type': 'string', - 'help_text': _('Lookup query for the object. Ex: Safe=TestSafe;Object=testAccountName123'), - }, - {'id': 'object_query_format', 'label': _('Object Query Format'), 'type': 'string', 'default': 'Exact', 'choices': ['Exact', 'Regexp']}, - { - 'id': 'object_property', - 'label': _('Object Property'), - 'type': 'string', - 'help_text': _('The property of the object to return. Available properties: Username, Password and Address.'), - }, - { - 'id': 'reason', - 'label': _('Reason'), - 'type': 'string', - 'help_text': _('Object request reason. This is only needed if it is required by the object\'s policy.'), - }, - ], - 'required': ['url', 'app_id', 'object_query'], -} - - -def aim_backend(**kwargs): - url = kwargs['url'] - client_cert = kwargs.get('client_cert', None) - client_key = kwargs.get('client_key', None) - verify = kwargs['verify'] - webservice_id = kwargs.get('webservice_id', '') - app_id = kwargs['app_id'] - object_query = kwargs['object_query'] - object_query_format = kwargs['object_query_format'] - object_property = kwargs.get('object_property', '') - reason = kwargs.get('reason', None) - if webservice_id == '': - webservice_id = 'AIMWebService' - - query_params = { - 'AppId': app_id, - 'Query': object_query, - 'QueryFormat': object_query_format, - } - if reason: - query_params['reason'] = reason - - request_qs = '?' + urlencode(query_params, quote_via=quote) - request_url = urljoin(url, '/'.join([webservice_id, 'api', 'Accounts'])) - - with CertFiles(client_cert, client_key) as cert: - res = requests.get( - request_url + request_qs, - timeout=30, - cert=cert, - verify=verify, - allow_redirects=False, - ) - sensitive_query_params = { - 'AppId': '****', - 'Query': '****', - 'QueryFormat': object_query_format, - } - if reason: - sensitive_query_params['reason'] = '****' - sensitive_request_qs = urlencode( - sensitive_query_params, - safe='*', - quote_via=quote, - ) - res.url = f'{request_url}?{sensitive_request_qs}' - - raise_for_status(res) - # CCP returns the property name capitalized, username is camel case - # so we need to handle that case - if object_property == '': - object_property = 'Content' - elif object_property.lower() == 'username': - object_property = 'UserName' - elif object_property.lower() == 'password': - object_property = 'Content' - elif object_property.lower() == 'address': - object_property = 'Address' - elif object_property not in res: - raise KeyError('Property {} not found in object, available properties: Username, Password and Address'.format(object_property)) - else: - object_property = object_property.capitalize() - - return res.json()[object_property] - - -aim_plugin = CredentialPlugin('CyberArk Central Credential Provider Lookup', inputs=aim_inputs, backend=aim_backend) diff --git a/awx/main/credential_plugins/azure_kv.py b/awx/main/credential_plugins/azure_kv.py deleted file mode 100644 index 58efe4a554..0000000000 --- a/awx/main/credential_plugins/azure_kv.py +++ /dev/null @@ -1,114 +0,0 @@ -from azure.keyvault.secrets import SecretClient -from azure.identity import ( - ClientSecretCredential, - CredentialUnavailableError, - ManagedIdentityCredential, -) -from azure.core.credentials import TokenCredential -from msrestazure import azure_cloud - -from .plugin import CredentialPlugin - -from django.utils.translation import gettext_lazy as _ - - -# https://github.com/Azure/msrestazure-for-python/blob/master/msrestazure/azure_cloud.py -clouds = [vars(azure_cloud)[n] for n in dir(azure_cloud) if n.startswith("AZURE_") and n.endswith("_CLOUD")] -default_cloud = vars(azure_cloud)["AZURE_PUBLIC_CLOUD"] - - -azure_keyvault_inputs = { - 'fields': [ - { - 'id': 'url', - 'label': _('Vault URL (DNS Name)'), - 'type': 'string', - 'format': 'url', - }, - {'id': 'client', 'label': _('Client ID'), 'type': 'string'}, - { - 'id': 'secret', - 'label': _('Client Secret'), - 'type': 'string', - 'secret': True, - }, - {'id': 'tenant', 'label': _('Tenant ID'), 'type': 'string'}, - { - 'id': 'cloud_name', - 'label': _('Cloud Environment'), - 'help_text': _('Specify which azure cloud environment to use.'), - 'choices': list(set([default_cloud.name] + [c.name for c in clouds])), - 'default': default_cloud.name, - }, - ], - 'metadata': [ - { - 'id': 'secret_field', - 'label': _('Secret Name'), - 'type': 'string', - 'help_text': _('The name of the secret to look up.'), - }, - { - 'id': 'secret_version', - 'label': _('Secret Version'), - 'type': 'string', - 'help_text': _('Used to specify a specific secret version (if left empty, the latest version will be used).'), - }, - ], - 'required': ['url', 'secret_field'], -} - - -def _initialize_credential( - tenant: str = '', - client: str = '', - secret: str = '', -) -> TokenCredential: - explicit_credentials_provided = all((tenant, client, secret)) - - if explicit_credentials_provided: - return ClientSecretCredential( - tenant_id=tenant, - client_id=client, - client_secret=secret, - ) - - return ManagedIdentityCredential() - - -def azure_keyvault_backend( - *, url: str, client: str = '', secret: str = '', tenant: str = '', secret_field: str, secret_version: str = '', **kwargs -) -> str | None: - """Get a credential and retrieve a secret from an Azure Key Vault. - - An empty string for an optional parameter counts as not provided. - - :param url: An Azure Key Vault URI. - :param client: The Client ID (optional). - :param secret: The Client Secret (optional). - :param tenant: The Tenant ID (optional). - :param secret_field: The name of the secret to retrieve from the - vault. - :param secret_version: The version of the secret to retrieve - (optional). - :returns: The secret from the Key Vault. - :raises RuntimeError: If the software is not being run on an Azure - VM. - """ - chosen_credential = _initialize_credential(tenant, client, secret) - keyvault = SecretClient(credential=chosen_credential, vault_url=url) - try: - keyvault_secret = keyvault.get_secret( - name=secret_field, - version=secret_version, - ) - except CredentialUnavailableError as secret_lookup_err: - raise RuntimeError( - 'You are not operating on an Azure VM, so the Managed Identity ' - 'feature is unavailable. Please provide the full Client ID, ' - 'Client Secret, and Tenant ID or run the software on an Azure VM.', - ) from secret_lookup_err - return keyvault_secret.value - - -azure_keyvault_plugin = CredentialPlugin('Microsoft Azure Key Vault', inputs=azure_keyvault_inputs, backend=azure_keyvault_backend) diff --git a/awx/main/credential_plugins/github_app.py b/awx/main/credential_plugins/github_app.py deleted file mode 100644 index df302e0162..0000000000 --- a/awx/main/credential_plugins/github_app.py +++ /dev/null @@ -1,176 +0,0 @@ -"""GitHub App Installation Access Token Credential Plugin. - -This module defines a credential plugin for making use of the -GitHub Apps mechanism, allowing authentication via GitHub App -installation-scoped access tokens. - -Functions: - -- :func:`extract_github_app_install_token`: Generates a GitHub App - Installation token. -- ``github_app_lookup``: Defines the credential plugin interface. -""" - -from github import Auth as Auth, Github -from github.Consts import DEFAULT_BASE_URL as PUBLIC_GH_API_URL -from github.GithubException import ( - BadAttributeException, - GithubException, - UnknownObjectException, -) - -from django.utils.translation import gettext_lazy as _ - -from .plugin import CredentialPlugin - -github_app_inputs = { - 'fields': [ - { - 'id': 'github_api_url', - 'label': _('GitHub API endpoint URL'), - 'type': 'string', - 'help_text': _( - 'Specify the GitHub API URL here. In the case of an Enterprise: ' - 'https://gh.your.org/api/v3 (self-hosted) ' - 'or https://api.SUBDOMAIN.ghe.com (cloud)', - ), - 'default': 'https://api.github.com', - }, - { - 'id': 'app_or_client_id', - 'label': _('GitHub App ID'), - 'type': 'string', - 'help_text': _( - 'The GitHub App ID created by the GitHub Admin. ' - 'Example App ID: 1121547 ' - 'found on https://github.com/settings/apps/ ' - 'required for creating a JWT token for authentication.', - ), - }, - { - 'id': 'install_id', - 'label': _('GitHub App Installation ID'), - 'type': 'string', - 'help_text': _( - 'The Installation ID from the GitHub App installation ' - 'generated by the GitHub Admin. ' - 'Example: 59980338 extracted from the installation link ' - 'https://github.com/settings/installations/59980338 ' - 'required for creating a limited GitHub app token.', - ), - }, - { - 'id': 'private_rsa_key', - 'label': _('RSA Private Key'), - 'type': 'string', - 'format': 'ssh_private_key', - 'secret': True, - 'multiline': True, - 'help_text': _( - 'Paste the contents of the PEM file that the GitHub Admin provided to you with the app and installation IDs.', - ), - }, - ], - 'metadata': [ - { - 'id': 'description', - 'label': _('Description (Optional)'), - 'type': 'string', - 'help_text': _('To be removed after UI is updated'), - }, - ], - 'required': ['app_or_client_id', 'install_id', 'private_rsa_key'], -} - -GH_CLIENT_ID_TRAILER_LENGTH = 16 -HEXADECIMAL_BASE = 16 - - -def _is_intish(app_id_candidate): - return isinstance(app_id_candidate, int) or app_id_candidate.isdigit() - - -def _is_client_id(client_id_candidate): - client_id_prefix = 'Iv1.' - if not client_id_candidate.startswith(client_id_prefix): - return False - - client_id_trailer = client_id_candidate[len(client_id_prefix) :] - - if len(client_id_trailer) != GH_CLIENT_ID_TRAILER_LENGTH: - return False - - try: - int(client_id_trailer, base=HEXADECIMAL_BASE) - except ValueError: - return False - - return True - - -def _is_app_or_client_id(app_or_client_id_candidate): - if _is_intish(app_or_client_id_candidate): - return True - return _is_client_id(app_or_client_id_candidate) - - -def _assert_ids_look_acceptable(app_or_client_id, install_id): - if not _is_app_or_client_id(app_or_client_id): - raise ValueError( - 'Expected GitHub App or Client ID to be an integer or a string ' - f'starting with `Iv1.` followed by 16 hexadecimal digits, ' - f'but got {app_or_client_id !r}', - ) - if isinstance(app_or_client_id, str) and _is_client_id(app_or_client_id): - raise ValueError( - 'Expected GitHub App ID must be an integer or a string ' - f'with an all-digit value, but got {app_or_client_id !r}. ' - 'Client IDs are currently unsupported.', - ) - if not _is_intish(install_id): - raise ValueError( - 'Expected GitHub App Installation ID to be an integer' f' but got {install_id !r}', - ) - - -def extract_github_app_install_token(github_api_url, app_or_client_id, private_rsa_key, install_id, **_discarded_kwargs): - """Generate a GH App Installation access token.""" - _assert_ids_look_acceptable(app_or_client_id, install_id) - - auth = Auth.AppAuth( - app_id=str(app_or_client_id), - private_key=private_rsa_key, - ).get_installation_auth(installation_id=int(install_id)) - - Github( - auth=auth, - base_url=github_api_url if github_api_url else PUBLIC_GH_API_URL, - ) - - doc_url = 'See https://docs.github.com/rest/reference/apps#create-an-installation-access-token-for-an-app' - app_install_context = f'app_or_client_id: {app_or_client_id}, install_id: {install_id}' - - try: - return auth.token - except UnknownObjectException as github_install_not_found_exc: - raise ValueError( - f'Failed to retrieve a GitHub installation token from {github_api_url} using {app_install_context}. Is the app installed? {doc_url}.' - f'\n\n{github_install_not_found_exc}', - ) from github_install_not_found_exc - except GithubException as pygithub_catchall_exc: - raise RuntimeError( - f'An unexpected error happened while talking to GitHub API @ {github_api_url} ({app_install_context}). ' - f'Is the app or client ID correct? And the private RSA key? {doc_url}.' - f'\n\n{pygithub_catchall_exc}', - ) from pygithub_catchall_exc - except BadAttributeException as github_broken_exc: - raise RuntimeError( - f'Broken GitHub @ {github_api_url} with {app_install_context}. It is a bug, please report it to the developers.\n\n{github_broken_exc}', - ) from github_broken_exc - - -github_app_lookup_plugin = CredentialPlugin( - 'GitHub App Installation Access Token Lookup', - inputs=github_app_inputs, - backend=extract_github_app_install_token, -) diff --git a/awx/main/management/commands/import_auth_config_to_gateway.py b/awx/main/management/commands/import_auth_config_to_gateway.py deleted file mode 100644 index f89ebf3496..0000000000 --- a/awx/main/management/commands/import_auth_config_to_gateway.py +++ /dev/null @@ -1,247 +0,0 @@ -import sys -import os - -from django.core.management.base import BaseCommand -from urllib.parse import urlparse, urlunparse -from awx.sso.utils.azure_ad_migrator import AzureADMigrator -from awx.sso.utils.github_migrator import GitHubMigrator -from awx.sso.utils.ldap_migrator import LDAPMigrator -from awx.sso.utils.oidc_migrator import OIDCMigrator -from awx.sso.utils.saml_migrator import SAMLMigrator -from awx.sso.utils.radius_migrator import RADIUSMigrator -from awx.sso.utils.settings_migrator import SettingsMigrator -from awx.sso.utils.tacacs_migrator import TACACSMigrator -from awx.sso.utils.google_oauth2_migrator import GoogleOAuth2Migrator -from awx.main.utils.gateway_client import GatewayClient, GatewayAPIError -from awx.main.utils.gateway_client_svc_token import GatewayClientSVCToken -from ansible_base.resource_registry.tasks.sync import create_api_client - - -class Command(BaseCommand): - help = 'Import existing auth provider configurations to AAP Gateway via API requests' - - def add_arguments(self, parser): - parser.add_argument('--basic-auth', action='store_true', help='Use HTTP Basic Authentication between Controller and Gateway') - parser.add_argument( - '--skip-all-authenticators', - action='store_true', - help='Skip importing all authenticators [GitHub, OIDC, SAML, Azure AD, LDAP, RADIUS, TACACS+, Google OAuth2]', - ) - parser.add_argument('--skip-oidc', action='store_true', help='Skip importing generic OIDC authenticators') - parser.add_argument('--skip-github', action='store_true', help='Skip importing GitHub authenticator') - parser.add_argument('--skip-ldap', action='store_true', help='Skip importing LDAP authenticators') - parser.add_argument('--skip-ad', action='store_true', help='Skip importing Azure AD authenticator') - parser.add_argument('--skip-saml', action='store_true', help='Skip importing SAML authenticator') - parser.add_argument('--skip-radius', action='store_true', help='Skip importing RADIUS authenticator') - parser.add_argument('--skip-tacacs', action='store_true', help='Skip importing TACACS+ authenticator') - parser.add_argument('--skip-google', action='store_true', help='Skip importing Google OAuth2 authenticator') - parser.add_argument('--skip-settings', action='store_true', help='Skip importing settings') - parser.add_argument( - '--force', - action='store_true', - help='Force migration even if configurations already exist. Does not apply to skipped authenticators nor skipped settings.', - ) - - def handle(self, *args, **options): - # Read Gateway connection parameters from environment variables - gateway_base_url = os.getenv('GATEWAY_BASE_URL') - gateway_user = os.getenv('GATEWAY_USER') - gateway_password = os.getenv('GATEWAY_PASSWORD') - gateway_skip_verify = os.getenv('GATEWAY_SKIP_VERIFY', '').lower() in ('true', '1', 'yes', 'on') - - skip_all_authenticators = options['skip_all_authenticators'] - skip_oidc = options['skip_oidc'] - skip_github = options['skip_github'] - skip_ldap = options['skip_ldap'] - skip_ad = options['skip_ad'] - skip_saml = options['skip_saml'] - skip_radius = options['skip_radius'] - skip_tacacs = options['skip_tacacs'] - skip_google = options['skip_google'] - skip_settings = options['skip_settings'] - force = options['force'] - basic_auth = options['basic_auth'] - - management_command_validation_errors = [] - - # If the management command isn't called with all parameters needed to talk to Gateway, consider - # it a dry-run and exit cleanly - if not gateway_base_url and basic_auth: - management_command_validation_errors.append('- GATEWAY_BASE_URL: Base URL of the AAP Gateway instance') - if (not gateway_user or not gateway_password) and basic_auth: - management_command_validation_errors.append('- GATEWAY_USER: Username for AAP Gateway authentication') - management_command_validation_errors.append('- GATEWAY_PASSWORD: Password for AAP Gateway authentication') - - if len(management_command_validation_errors) > 0: - self.stdout.write(self.style.WARNING('Missing required environment variables:')) - for validation_error in management_command_validation_errors: - self.stdout.write(self.style.WARNING(f"{validation_error}")) - self.stdout.write(self.style.WARNING('- GATEWAY_SKIP_VERIFY: Skip SSL certificate verification (optional)')) - sys.exit(0) - - resource_api_client = None - response = None - - if basic_auth: - self.stdout.write(self.style.SUCCESS('HTTP Basic Auth: true')) - self.stdout.write(self.style.SUCCESS(f'Gateway Base URL: {gateway_base_url}')) - self.stdout.write(self.style.SUCCESS(f'Gateway User: {gateway_user}')) - self.stdout.write(self.style.SUCCESS('Gateway Password: *******************')) - self.stdout.write(self.style.SUCCESS(f'Skip SSL Verification: {gateway_skip_verify}')) - - else: - resource_api_client = create_api_client() - resource_api_client.verify_https = not gateway_skip_verify - response = resource_api_client.get_service_metadata() - parsed_url = urlparse(resource_api_client.base_url) - resource_api_client.base_url = urlunparse((parsed_url.scheme, parsed_url.netloc, '/', '', '', '')) - - self.stdout.write(self.style.SUCCESS('Gateway Service Token: true')) - self.stdout.write(self.style.SUCCESS(f'Gateway Base URL: {resource_api_client.base_url}')) - self.stdout.write(self.style.SUCCESS(f'Gateway JWT User: {resource_api_client.jwt_user_id}')) - self.stdout.write(self.style.SUCCESS(f'Gateway JWT Expiration: {resource_api_client.jwt_expiration}')) - self.stdout.write(self.style.SUCCESS(f'Skip SSL Verification: {not resource_api_client.verify_https}')) - self.stdout.write(self.style.SUCCESS(f'Connection Validated: {response.status_code == 200}')) - - if response.status_code != 200: - self.stdout.write( - self.style.ERROR( - f'Gateway Service Token is unable to connect to Gateway via the base URL {resource_api_client.base_url}. Recieved HTTP response code {response.status_code}' - ) - ) - sys.exit(1) - - # Create Gateway client and run migrations - try: - self.stdout.write(self.style.SUCCESS('\n=== Connecting to Gateway ===')) - pre_gateway_client = None - if basic_auth: - self.stdout.write(self.style.SUCCESS('\n=== With Basic HTTP Auth ===')) - pre_gateway_client = GatewayClient( - base_url=gateway_base_url, username=gateway_user, password=gateway_password, skip_verify=gateway_skip_verify, command=self - ) - - else: - self.stdout.write(self.style.SUCCESS('\n=== With Service Token ===')) - pre_gateway_client = GatewayClientSVCToken(resource_api_client=resource_api_client, command=self) - - with pre_gateway_client as gateway_client: - self.stdout.write(self.style.SUCCESS('Successfully connected to Gateway')) - - # Initialize migrators - migrators = [] - if not skip_all_authenticators: - if not skip_oidc: - migrators.append(OIDCMigrator(gateway_client, self, force=force)) - - if not skip_github: - migrators.append(GitHubMigrator(gateway_client, self, force=force)) - - if not skip_saml: - migrators.append(SAMLMigrator(gateway_client, self, force=force)) - - if not skip_ad: - migrators.append(AzureADMigrator(gateway_client, self, force=force)) - - if not skip_ldap: - migrators.append(LDAPMigrator(gateway_client, self, force=force)) - - if not skip_radius: - migrators.append(RADIUSMigrator(gateway_client, self, force=force)) - - if not skip_tacacs: - migrators.append(TACACSMigrator(gateway_client, self, force=force)) - - if not skip_google: - migrators.append(GoogleOAuth2Migrator(gateway_client, self, force=force)) - - if not migrators: - self.stdout.write(self.style.WARNING('No authentication configurations found to migrate.')) - - if not skip_settings: - migrators.append(SettingsMigrator(gateway_client, self, force=force)) - else: - self.stdout.write(self.style.WARNING('Settings migration will not execute.')) - - # Run migrations - total_results = { - 'created': 0, - 'updated': 0, - 'unchanged': 0, - 'failed': 0, - 'mappers_created': 0, - 'mappers_updated': 0, - 'mappers_failed': 0, - 'settings_created': 0, - 'settings_updated': 0, - 'settings_unchanged': 0, - 'settings_failed': 0, - } - - if not migrators: - self.stdout.write(self.style.WARNING('NO MIGRATIONS WILL EXECUTE.')) - # Exit with success code since this is not an error condition - sys.exit(0) - else: - for migrator in migrators: - self.stdout.write(self.style.SUCCESS(f'\n=== Migrating {migrator.get_authenticator_type()} Configurations ===')) - result = migrator.migrate() - self._print_export_summary(migrator.get_authenticator_type(), result) - - # Accumulate results - handle missing keys gracefully - for key in total_results: - total_results[key] += result.get(key, 0) - - # Overall summary - self.stdout.write(self.style.SUCCESS('\n=== Migration Summary ===')) - self.stdout.write(f'Total authenticators created: {total_results["created"]}') - self.stdout.write(f'Total authenticators updated: {total_results["updated"]}') - self.stdout.write(f'Total authenticators unchanged: {total_results["unchanged"]}') - self.stdout.write(f'Total authenticators failed: {total_results["failed"]}') - self.stdout.write(f'Total mappers created: {total_results["mappers_created"]}') - self.stdout.write(f'Total mappers updated: {total_results["mappers_updated"]}') - self.stdout.write(f'Total mappers failed: {total_results["mappers_failed"]}') - self.stdout.write(f'Total settings created: {total_results["settings_created"]}') - self.stdout.write(f'Total settings updated: {total_results["settings_updated"]}') - self.stdout.write(f'Total settings unchanged: {total_results["settings_unchanged"]}') - self.stdout.write(f'Total settings failed: {total_results["settings_failed"]}') - - # Check for any failures and return appropriate status code - has_failures = total_results["failed"] > 0 or total_results["mappers_failed"] > 0 or total_results["settings_failed"] > 0 - - if has_failures: - self.stdout.write(self.style.ERROR('\nMigration completed with failures.')) - sys.exit(1) - else: - self.stdout.write(self.style.SUCCESS('\nMigration completed successfully.')) - sys.exit(0) - - except GatewayAPIError as e: - self.stdout.write(self.style.ERROR(f'Gateway API Error: {e.message}')) - if e.status_code: - self.stdout.write(self.style.ERROR(f'Status Code: {e.status_code}')) - if e.response_data: - self.stdout.write(self.style.ERROR(f'Response: {e.response_data}')) - sys.exit(1) - except Exception as e: - self.stdout.write(self.style.ERROR(f'Unexpected error during migration: {str(e)}')) - sys.exit(1) - - def _print_export_summary(self, config_type, result): - """Print a summary of the export results.""" - self.stdout.write(f'\n--- {config_type} Export Summary ---') - - if config_type in ['GitHub', 'OIDC', 'SAML', 'Azure AD', 'LDAP', 'RADIUS', 'TACACS+', 'Google OAuth2']: - self.stdout.write(f'Authenticators created: {result.get("created", 0)}') - self.stdout.write(f'Authenticators updated: {result.get("updated", 0)}') - self.stdout.write(f'Authenticators unchanged: {result.get("unchanged", 0)}') - self.stdout.write(f'Authenticators failed: {result.get("failed", 0)}') - self.stdout.write(f'Mappers created: {result.get("mappers_created", 0)}') - self.stdout.write(f'Mappers updated: {result.get("mappers_updated", 0)}') - self.stdout.write(f'Mappers failed: {result.get("mappers_failed", 0)}') - - if config_type == 'Settings': - self.stdout.write(f'Settings created: {result.get("settings_created", 0)}') - self.stdout.write(f'Settings updated: {result.get("settings_updated", 0)}') - self.stdout.write(f'Settings unchanged: {result.get("settings_unchanged", 0)}') - self.stdout.write(f'Settings failed: {result.get("settings_failed", 0)}') diff --git a/awx/main/migrations/0192_custom_roles.py b/awx/main/migrations/0192_custom_roles.py index ba75694c7f..c91823aa34 100644 --- a/awx/main/migrations/0192_custom_roles.py +++ b/awx/main/migrations/0192_custom_roles.py @@ -8,7 +8,7 @@ from awx.main.migrations._dab_rbac import migrate_to_new_rbac, create_permission class Migration(migrations.Migration): dependencies = [ ('main', '0191_add_django_permissions'), - ('dab_rbac', '0003_alter_dabpermission_codename_and_more'), + ('dab_rbac', '__first__'), ] operations = [ diff --git a/awx/main/migrations/0202_squashed_deletions.py b/awx/main/migrations/0204_squashed_deletions.py similarity index 99% rename from awx/main/migrations/0202_squashed_deletions.py rename to awx/main/migrations/0204_squashed_deletions.py index 836409dadf..a6c3c90abe 100644 --- a/awx/main/migrations/0202_squashed_deletions.py +++ b/awx/main/migrations/0204_squashed_deletions.py @@ -20,7 +20,7 @@ def update_github_app_kind(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('main', '0201_create_managed_creds'), + ('main', '0203_remove_team_of_teams'), ] operations = [ migrations.DeleteModel( diff --git a/awx/main/migrations/_dab_rbac.py b/awx/main/migrations/_dab_rbac.py index 4286be039b..cb37800463 100644 --- a/awx/main/migrations/_dab_rbac.py +++ b/awx/main/migrations/_dab_rbac.py @@ -336,16 +336,6 @@ def setup_managed_role_definitions(apps, schema_editor): to_create['object_admin'].format(cls=cls), f'Has all permissions to a single {cls._meta.verbose_name}', ct, indiv_perms, RoleDefinition ) ) - if cls_name == 'team': - managed_role_definitions.append( - get_or_create_managed( - 'Controller Team Admin', - f'Has all permissions to a single {cls._meta.verbose_name}', - ct, - indiv_perms, - RoleDefinition, - ) - ) if 'org_children' in to_create and (cls_name not in ('organization', 'instancegroup', 'team')): org_child_perms = object_perms.copy() @@ -386,18 +376,6 @@ def setup_managed_role_definitions(apps, schema_editor): RoleDefinition, ) ) - if action == 'member' and cls_name in ('organization', 'team'): - suffix = to_create['special'].format(cls=cls, action=action.title()) - rd_name = f'Controller {suffix}' - managed_role_definitions.append( - get_or_create_managed( - rd_name, - f'Has {action} permissions to a single {cls._meta.verbose_name}', - ct, - perm_list, - RoleDefinition, - ) - ) if 'org_admin' in to_create: managed_role_definitions.append( @@ -409,15 +387,6 @@ def setup_managed_role_definitions(apps, schema_editor): RoleDefinition, ) ) - managed_role_definitions.append( - get_or_create_managed( - 'Controller Organization Admin', - 'Has all permissions to a single organization and all objects inside of it', - org_ct, - org_perms, - RoleDefinition, - ) - ) # Special "organization action" roles audit_permissions = [perm for perm in org_perms if perm.codename.startswith('view_')] diff --git a/awx/main/models/credential/__init__.py b/awx/main/models/credential/__init__.py deleted file mode 100644 index c282fed86f..0000000000 --- a/awx/main/models/credential/__init__.py +++ /dev/null @@ -1,1421 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved. -import functools -import inspect -import logging -import os -from pkg_resources import iter_entry_points -import re -import stat -import tempfile -from types import SimpleNamespace - -# Jinja2 -from jinja2 import sandbox - -# Django -from django.db import models -from django.utils.translation import gettext_lazy as _, gettext_noop -from django.core.exceptions import ValidationError -from django.conf import settings -from django.utils.encoding import force_str -from django.utils.functional import cached_property -from django.utils.timezone import now -from django.contrib.auth.models import User - -# DRF -from rest_framework.serializers import ValidationError as DRFValidationError - -# AWX -from awx.api.versioning import reverse -from awx.main.fields import ( - ImplicitRoleField, - CredentialInputField, - CredentialTypeInputField, - CredentialTypeInjectorField, - DynamicCredentialInputField, -) -from awx.main.utils import decrypt_field, classproperty, set_environ -from awx.main.utils.safe_yaml import safe_dump -from awx.main.utils.execution_environments import to_container_path -from awx.main.validators import validate_ssh_private_key -from awx.main.models.base import CommonModelNameNotUnique, PasswordFieldsModel, PrimordialModel -from awx.main.models.mixins import ResourceMixin -from awx.main.models.rbac import ( - ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, - ROLE_SINGLETON_SYSTEM_AUDITOR, -) -from awx.main.models import Team, Organization -from awx.main.utils import encrypt_field -from . import injectors as builtin_injectors - -# DAB -from ansible_base.resource_registry.tasks.sync import get_resource_server_client -from ansible_base.resource_registry.utils.settings import resource_server_defined - - -__all__ = ['Credential', 'CredentialType', 'CredentialInputSource', 'build_safe_env'] - -logger = logging.getLogger('awx.main.models.credential') -credential_plugins = dict((ep.name, ep.load()) for ep in iter_entry_points('awx.credential_plugins')) - -HIDDEN_PASSWORD = '**********' - - -def build_safe_env(env): - """ - Build environment dictionary, hiding potentially sensitive information - such as passwords or keys. - """ - hidden_re = re.compile(r'API|TOKEN|KEY|SECRET|PASS', re.I) - urlpass_re = re.compile(r'^.*?://[^:]+:(.*?)@.*?$') - safe_env = dict(env) - for k, v in safe_env.items(): - if k == 'AWS_ACCESS_KEY_ID': - continue - elif k.startswith('ANSIBLE_') and not k.startswith('ANSIBLE_NET') and not k.startswith('ANSIBLE_GALAXY_SERVER'): - continue - elif hidden_re.search(k): - safe_env[k] = HIDDEN_PASSWORD - elif type(v) == str and urlpass_re.match(v): - safe_env[k] = urlpass_re.sub(HIDDEN_PASSWORD, v) - return safe_env - - -def check_resource_server_for_user_in_organization(user, organization, requesting_user): - if not resource_server_defined(): - return False - - if not requesting_user: - return False - - client = get_resource_server_client(settings.RESOURCE_SERVICE_PATH, jwt_user_id=str(requesting_user.resource.ansible_id), raise_if_bad_request=False) - # need to get the organization object_id in resource server, by querying with ansible_id - response = client._make_request(path=f'resources/?ansible_id={str(organization.resource.ansible_id)}', method='GET') - response_json = response.json() - if response.status_code != 200: - logger.error(f'Failed to get organization object_id in resource server: {response_json.get("detail", "")}') - return False - - if response_json.get('count', 0) == 0: - return False - org_id_in_resource_server = response_json['results'][0]['object_id'] - - client.base_url = client.base_url.replace('/api/gateway/v1/service-index/', '/api/gateway/v1/') - # find role assignments with: - # - roles Organization Member or Organization Admin - # - user ansible id - # - organization object id - - response = client._make_request( - path=f'role_user_assignments/?role_definition__name__in=Organization Member,Organization Admin&user__resource__ansible_id={str(user.resource.ansible_id)}&object_id={org_id_in_resource_server}', - method='GET', - ) - response_json = response.json() - if response.status_code != 200: - logger.error(f'Failed to get role user assignments in resource server: {response_json.get("detail", "")}') - return False - - if response_json.get('count', 0) > 0: - return True - - return False - - -class Credential(PasswordFieldsModel, CommonModelNameNotUnique, ResourceMixin): - """ - A credential contains information about how to talk to a remote resource - Usually this is a SSH key location, and possibly an unlock password. - If used with sudo, a sudo password should be set if required. - """ - - class Meta: - app_label = 'main' - ordering = ('name',) - unique_together = ('organization', 'name', 'credential_type') - permissions = [('use_credential', 'Can use credential in a job or related resource')] - - PASSWORD_FIELDS = ['inputs'] - FIELDS_TO_PRESERVE_AT_COPY = ['input_sources'] - - credential_type = models.ForeignKey( - 'CredentialType', - related_name='credentials', - null=False, - on_delete=models.CASCADE, - help_text=_('Specify the type of credential you want to create. Refer to the documentation for details on each type.'), - ) - managed = models.BooleanField(default=False, editable=False) - organization = models.ForeignKey( - 'Organization', - null=True, - default=None, - blank=True, - on_delete=models.CASCADE, - related_name='credentials', - ) - inputs = CredentialInputField( - blank=True, default=dict, help_text=_('Enter inputs using either JSON or YAML syntax. Refer to the documentation for example syntax.') - ) - admin_role = ImplicitRoleField( - parent_role=[ - 'singleton:' + ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, - 'organization.credential_admin_role', - ], - ) - use_role = ImplicitRoleField( - parent_role=[ - 'admin_role', - ] - ) - read_role = ImplicitRoleField( - parent_role=[ - 'singleton:' + ROLE_SINGLETON_SYSTEM_AUDITOR, - 'organization.auditor_role', - 'use_role', - 'admin_role', - ] - ) - - @property - def kind(self): - return self.credential_type.namespace - - @property - def cloud(self): - return self.credential_type.kind == 'cloud' - - @property - def kubernetes(self): - return self.credential_type.kind == 'kubernetes' - - def get_absolute_url(self, request=None): - return reverse('api:credential_detail', kwargs={'pk': self.pk}, request=request) - - # - # TODO: the SSH-related properties below are largely used for validation - # and for determining passwords necessary for job/ad-hoc launch - # - # These are SSH-specific; should we move them elsewhere? - # - @property - def needs_ssh_password(self): - return self.credential_type.kind == 'ssh' and self.inputs.get('password') == 'ASK' - - @property - def has_encrypted_ssh_key_data(self): - try: - ssh_key_data = self.get_input('ssh_key_data') - except AttributeError: - return False - - try: - pem_objects = validate_ssh_private_key(ssh_key_data) - for pem_object in pem_objects: - if pem_object.get('key_enc', False): - return True - except ValidationError: - pass - return False - - @property - def needs_ssh_key_unlock(self): - if self.credential_type.kind == 'ssh' and self.inputs.get('ssh_key_unlock') in ('ASK', ''): - return self.has_encrypted_ssh_key_data - return False - - @property - def needs_become_password(self): - return self.credential_type.kind == 'ssh' and self.inputs.get('become_password') == 'ASK' - - @property - def needs_vault_password(self): - return self.credential_type.kind == 'vault' and self.inputs.get('vault_password') == 'ASK' - - @property - def passwords_needed(self): - needed = [] - for field in ('ssh_password', 'become_password', 'ssh_key_unlock'): - if getattr(self, 'needs_%s' % field): - needed.append(field) - if self.needs_vault_password: - if self.inputs.get('vault_id'): - needed.append('vault_password.{}'.format(self.inputs.get('vault_id'))) - else: - needed.append('vault_password') - return needed - - @cached_property - def dynamic_input_fields(self): - # if the credential is not yet saved we can't access the input_sources - if not self.id: - return [] - return [obj.input_field_name for obj in self.input_sources.all()] - - def _password_field_allows_ask(self, field): - return field in self.credential_type.askable_fields - - def save(self, *args, **kwargs): - self.PASSWORD_FIELDS = self.credential_type.secret_fields - - if self.pk: - cred_before = Credential.objects.get(pk=self.pk) - inputs_before = cred_before.inputs - # Look up the currently persisted value so that we can replace - # $encrypted$ with the actual DB-backed value - for field in self.PASSWORD_FIELDS: - if self.inputs.get(field) == '$encrypted$': - self.inputs[field] = inputs_before[field] - - super(Credential, self).save(*args, **kwargs) - - def mark_field_for_save(self, update_fields, field): - if 'inputs' not in update_fields: - update_fields.append('inputs') - - def encrypt_field(self, field, ask): - if field not in self.inputs: - return None - encrypted = encrypt_field(self, field, ask=ask) - if encrypted: - self.inputs[field] = encrypted - elif field in self.inputs: - del self.inputs[field] - - def display_inputs(self): - field_val = self.inputs.copy() - for k, v in field_val.items(): - if force_str(v).startswith('$encrypted$'): - field_val[k] = '$encrypted$' - return field_val - - def unique_hash(self, display=False): - """ - Credential exclusivity is not defined solely by the related - credential type (due to vault), so this produces a hash - that can be used to evaluate exclusivity - """ - if display: - type_alias = self.credential_type.name - else: - type_alias = self.credential_type_id - if self.credential_type.kind == 'vault' and self.has_input('vault_id'): - if display: - fmt_str = '{} (id={})' - else: - fmt_str = '{}_{}' - return fmt_str.format(type_alias, self.get_input('vault_id')) - return str(type_alias) - - @staticmethod - def unique_dict(cred_qs): - ret = {} - for cred in cred_qs: - ret[cred.unique_hash()] = cred - return ret - - def get_input(self, field_name, **kwargs): - """ - Get an injectable and decrypted value for an input field. - - Retrieves the value for a given credential input field name. Return - values for secret input fields are decrypted. If the credential doesn't - have an input value defined for the given field name, an AttributeError - is raised unless a default value is provided. - - :param field_name(str): The name of the input field. - :param default(optional[str]): A default return value to use. - """ - if self.credential_type.kind != 'external' and field_name in self.dynamic_input_fields: - return self._get_dynamic_input(field_name) - if field_name in self.credential_type.secret_fields: - try: - return decrypt_field(self, field_name) - except AttributeError: - for field in self.credential_type.inputs.get('fields', []): - if field['id'] == field_name and 'default' in field: - return field['default'] - if 'default' in kwargs: - return kwargs['default'] - raise AttributeError(field_name) - if field_name in self.inputs: - return self.inputs[field_name] - if 'default' in kwargs: - return kwargs['default'] - for field in self.credential_type.inputs.get('fields', []): - if field['id'] == field_name and 'default' in field: - return field['default'] - raise AttributeError(field_name) - - def has_input(self, field_name): - if field_name in self.dynamic_input_fields: - return True - return field_name in self.inputs and self.inputs[field_name] not in ('', None) - - def has_inputs(self, field_names=()): - for name in field_names: - if not self.has_input(name): - raise ValueError('{} is not an input field'.format(name)) - return True - - def _get_dynamic_input(self, field_name): - for input_source in self.input_sources.all(): - if input_source.input_field_name == field_name: - return input_source.get_input_value() - else: - raise ValueError('{} is not a dynamic input field'.format(field_name)) - - def validate_role_assignment(self, actor, role_definition, **kwargs): - if self.organization: - if isinstance(actor, User): - if actor.is_superuser: - return - if Organization.access_qs(actor, 'member').filter(id=self.organization.id).exists(): - return - - requesting_user = kwargs.get('requesting_user', None) - if check_resource_server_for_user_in_organization(actor, self.organization, requesting_user): - return - if isinstance(actor, Team): - if actor.organization == self.organization: - return - raise DRFValidationError({'detail': _(f"You cannot grant credential access to a {actor._meta.object_name} not in the credentials' organization")}) - - -class CredentialType(CommonModelNameNotUnique): - """ - A reusable schema for a credential. - - Used to define a named credential type with fields (e.g., an API key) and - output injectors (i.e., an environment variable that uses the API key). - """ - - class Meta: - app_label = 'main' - ordering = ('kind', 'name') - unique_together = (('name', 'kind'),) - - KIND_CHOICES = ( - ('ssh', _('Machine')), - ('vault', _('Vault')), - ('net', _('Network')), - ('scm', _('Source Control')), - ('cloud', _('Cloud')), - ('registry', _('Container Registry')), - ('token', _('Personal Access Token')), - ('insights', _('Insights')), - ('external', _('External')), - ('kubernetes', _('Kubernetes')), - ('galaxy', _('Galaxy/Automation Hub')), - ('cryptography', _('Cryptography')), - ) - - kind = models.CharField(max_length=32, choices=KIND_CHOICES) - managed = models.BooleanField(default=False, editable=False) - namespace = models.CharField(max_length=1024, null=True, default=None, editable=False) - inputs = CredentialTypeInputField( - blank=True, default=dict, help_text=_('Enter inputs using either JSON or YAML syntax. Refer to the documentation for example syntax.') - ) - injectors = CredentialTypeInjectorField( - blank=True, - default=dict, - help_text=_('Enter injectors using either JSON or YAML syntax. Refer to the documentation for example syntax.'), - ) - - @classmethod - def from_db(cls, db, field_names, values): - instance = super(CredentialType, cls).from_db(db, field_names, values) - if instance.managed and instance.namespace: - native = ManagedCredentialType.registry[instance.namespace] - instance.inputs = native.inputs - instance.injectors = native.injectors - return instance - - def get_absolute_url(self, request=None): - return reverse('api:credential_type_detail', kwargs={'pk': self.pk}, request=request) - - @property - def defined_fields(self): - return [field.get('id') for field in self.inputs.get('fields', [])] - - @property - def secret_fields(self): - return [field['id'] for field in self.inputs.get('fields', []) if field.get('secret', False) is True] - - @property - def askable_fields(self): - return [field['id'] for field in self.inputs.get('fields', []) if field.get('ask_at_runtime', False) is True] - - @property - def plugin(self): - if self.kind != 'external': - raise AttributeError('plugin') - [plugin] = [plugin for ns, plugin in credential_plugins.items() if ns == self.namespace] - return plugin - - def default_for_field(self, field_id): - for field in self.inputs.get('fields', []): - if field['id'] == field_id: - if 'choices' in field: - return field['choices'][0] - return {'string': '', 'boolean': False}[field['type']] - - @classproperty - def defaults(cls): - return dict((k, functools.partial(v.create)) for k, v in ManagedCredentialType.registry.items()) - - @classmethod - def setup_tower_managed_defaults(cls, apps=None): - if apps is not None: - ct_class = apps.get_model('main', 'CredentialType') - else: - ct_class = CredentialType - for default in ManagedCredentialType.registry.values(): - existing = ct_class.objects.filter(name=default.name, kind=default.kind).first() - if existing is not None: - existing.namespace = default.namespace - existing.inputs = {} - existing.injectors = {} - existing.save() - continue - logger.debug(_("adding %s credential type" % default.name)) - params = default.get_creation_params() - if 'managed' not in [f.name for f in ct_class._meta.get_fields()]: - params['managed_by_tower'] = params.pop('managed') - params['created'] = params['modified'] = now() # CreatedModifiedModel service - created = ct_class(**params) - created.inputs = created.injectors = {} - created.save() - - @classmethod - def load_plugin(cls, ns, plugin): - ManagedCredentialType(namespace=ns, name=plugin.name, kind='external', inputs=plugin.inputs) - - def inject_credential(self, credential, env, safe_env, args, private_data_dir, container_root=None): - """ - Inject credential data into the environment variables and arguments - passed to `ansible-playbook` - - :param credential: a :class:`awx.main.models.Credential` instance - :param env: a dictionary of environment variables used in - the `ansible-playbook` call. This method adds - additional environment variables based on - custom `env` injectors defined on this - CredentialType. - :param safe_env: a dictionary of environment variables stored - in the database for the job run - (`UnifiedJob.job_env`); secret values should - be stripped - :param args: a list of arguments passed to - `ansible-playbook` in the style of - `subprocess.call(args)`. This method appends - additional arguments based on custom - `extra_vars` injectors defined on this - CredentialType. - :param private_data_dir: a temporary directory to store files generated - by `file` injectors (like config files or key - files) - - :param container_root: root directory inside of container to mount the - private data directory to - """ - if not self.injectors: - if self.managed and credential.credential_type.namespace in dir(builtin_injectors): - injected_env = {} - getattr(builtin_injectors, credential.credential_type.namespace)(credential, injected_env, private_data_dir) - env.update(injected_env) - safe_env.update(build_safe_env(injected_env)) - return - - class TowerNamespace: - pass - - tower_namespace = TowerNamespace() - - # maintain a normal namespace for building the ansible-playbook arguments (env and args) - namespace = {'tower': tower_namespace} - - # maintain a sanitized namespace for building the DB-stored arguments (safe_env) - safe_namespace = {'tower': tower_namespace} - - # build a normal namespace with secret values decrypted (for - # ansible-playbook) and a safe namespace with secret values hidden (for - # DB storage) - injectable_fields = list(credential.inputs.keys()) + credential.dynamic_input_fields - for field_name in list(set(injectable_fields)): - value = credential.get_input(field_name) - - if type(value) is bool: - # boolean values can't be secret/encrypted/external - safe_namespace[field_name] = namespace[field_name] = value - continue - - if field_name in self.secret_fields: - safe_namespace[field_name] = '**********' - elif len(value): - safe_namespace[field_name] = value - if len(value): - namespace[field_name] = value - - for field in self.inputs.get('fields', []): - # default missing boolean fields to False - if field['type'] == 'boolean' and field['id'] not in credential.inputs.keys(): - namespace[field['id']] = safe_namespace[field['id']] = False - # make sure private keys end with a \n - if field.get('format') == 'ssh_private_key': - if field['id'] in namespace and not namespace[field['id']].endswith('\n'): - namespace[field['id']] += '\n' - - file_tmpls = self.injectors.get('file', {}) - # If any file templates are provided, render the files and update the - # special `tower` template namespace so the filename can be - # referenced in other injectors - - sandbox_env = sandbox.ImmutableSandboxedEnvironment() - - for file_label, file_tmpl in file_tmpls.items(): - data = sandbox_env.from_string(file_tmpl).render(**namespace) - _, path = tempfile.mkstemp(dir=os.path.join(private_data_dir, 'env')) - with open(path, 'w') as f: - f.write(data) - os.chmod(path, stat.S_IRUSR | stat.S_IWUSR) - container_path = to_container_path(path, private_data_dir) - - # determine if filename indicates single file or many - if file_label.find('.') == -1: - tower_namespace.filename = container_path - else: - if not hasattr(tower_namespace, 'filename'): - tower_namespace.filename = TowerNamespace() - file_label = file_label.split('.')[1] - setattr(tower_namespace.filename, file_label, container_path) - - injector_field = self._meta.get_field('injectors') - for env_var, tmpl in self.injectors.get('env', {}).items(): - try: - injector_field.validate_env_var_allowed(env_var) - except ValidationError as e: - logger.error('Ignoring prohibited env var {}, reason: {}'.format(env_var, e)) - continue - env[env_var] = sandbox_env.from_string(tmpl).render(**namespace) - safe_env[env_var] = sandbox_env.from_string(tmpl).render(**safe_namespace) - - if 'INVENTORY_UPDATE_ID' not in env: - # awx-manage inventory_update does not support extra_vars via -e - def build_extra_vars(node): - if isinstance(node, dict): - return {build_extra_vars(k): build_extra_vars(v) for k, v in node.items()} - elif isinstance(node, list): - return [build_extra_vars(x) for x in node] - else: - return sandbox_env.from_string(node).render(**namespace) - - def build_extra_vars_file(vars, private_dir): - handle, path = tempfile.mkstemp(dir=os.path.join(private_dir, 'env')) - f = os.fdopen(handle, 'w') - f.write(safe_dump(vars)) - f.close() - os.chmod(path, stat.S_IRUSR) - return path - - extra_vars = build_extra_vars(self.injectors.get('extra_vars', {})) - if extra_vars: - path = build_extra_vars_file(extra_vars, private_data_dir) - container_path = to_container_path(path, private_data_dir, container_root=container_root) - args.extend(['-e', '@%s' % container_path]) - - -class ManagedCredentialType(SimpleNamespace): - registry = {} - - def __init__(self, namespace, **kwargs): - for k in ('inputs', 'injectors'): - if k not in kwargs: - kwargs[k] = {} - super(ManagedCredentialType, self).__init__(namespace=namespace, **kwargs) - if namespace in ManagedCredentialType.registry: - raise ValueError( - 'a ManagedCredentialType with namespace={} is already defined in {}'.format( - namespace, inspect.getsourcefile(ManagedCredentialType.registry[namespace].__class__) - ) - ) - ManagedCredentialType.registry[namespace] = self - - def get_creation_params(self): - return dict( - namespace=self.namespace, - kind=self.kind, - name=self.name, - managed=True, - inputs=self.inputs, - injectors=self.injectors, - ) - - def create(self): - return CredentialType(**self.get_creation_params()) - - -ManagedCredentialType( - namespace='ssh', - kind='ssh', - name=gettext_noop('Machine'), - inputs={ - 'fields': [ - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - {'id': 'password', 'label': gettext_noop('Password'), 'type': 'string', 'secret': True, 'ask_at_runtime': True}, - {'id': 'ssh_key_data', 'label': gettext_noop('SSH Private Key'), 'type': 'string', 'format': 'ssh_private_key', 'secret': True, 'multiline': True}, - { - 'id': 'ssh_public_key_data', - 'label': gettext_noop('Signed SSH Certificate'), - 'type': 'string', - 'multiline': True, - 'secret': True, - }, - {'id': 'ssh_key_unlock', 'label': gettext_noop('Private Key Passphrase'), 'type': 'string', 'secret': True, 'ask_at_runtime': True}, - { - 'id': 'become_method', - 'label': gettext_noop('Privilege Escalation Method'), - 'type': 'string', - 'help_text': gettext_noop('Specify a method for "become" operations. This is equivalent to specifying the --become-method Ansible parameter.'), - }, - { - 'id': 'become_username', - 'label': gettext_noop('Privilege Escalation Username'), - 'type': 'string', - }, - {'id': 'become_password', 'label': gettext_noop('Privilege Escalation Password'), 'type': 'string', 'secret': True, 'ask_at_runtime': True}, - ], - }, -) - -ManagedCredentialType( - namespace='scm', - kind='scm', - name=gettext_noop('Source Control'), - managed=True, - inputs={ - 'fields': [ - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - {'id': 'password', 'label': gettext_noop('Password'), 'type': 'string', 'secret': True}, - {'id': 'ssh_key_data', 'label': gettext_noop('SCM Private Key'), 'type': 'string', 'format': 'ssh_private_key', 'secret': True, 'multiline': True}, - {'id': 'ssh_key_unlock', 'label': gettext_noop('Private Key Passphrase'), 'type': 'string', 'secret': True}, - ], - }, -) - -ManagedCredentialType( - namespace='vault', - kind='vault', - name=gettext_noop('Vault'), - managed=True, - inputs={ - 'fields': [ - {'id': 'vault_password', 'label': gettext_noop('Vault Password'), 'type': 'string', 'secret': True, 'ask_at_runtime': True}, - { - 'id': 'vault_id', - 'label': gettext_noop('Vault Identifier'), - 'type': 'string', - 'format': 'vault_id', - 'help_text': gettext_noop( - 'Specify an (optional) Vault ID. This is ' - 'equivalent to specifying the --vault-id ' - 'Ansible parameter for providing multiple Vault ' - 'passwords. Note: this feature only works in ' - 'Ansible 2.4+.' - ), - }, - ], - 'required': ['vault_password'], - }, -) - -ManagedCredentialType( - namespace='net', - kind='net', - name=gettext_noop('Network'), - managed=True, - inputs={ - 'fields': [ - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - {'id': 'ssh_key_data', 'label': gettext_noop('SSH Private Key'), 'type': 'string', 'format': 'ssh_private_key', 'secret': True, 'multiline': True}, - { - 'id': 'ssh_key_unlock', - 'label': gettext_noop('Private Key Passphrase'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'authorize', - 'label': gettext_noop('Authorize'), - 'type': 'boolean', - }, - { - 'id': 'authorize_password', - 'label': gettext_noop('Authorize Password'), - 'type': 'string', - 'secret': True, - }, - ], - 'dependencies': { - 'authorize_password': ['authorize'], - }, - 'required': ['username'], - }, -) - -ManagedCredentialType( - namespace='aws', - kind='cloud', - name=gettext_noop('Amazon Web Services'), - managed=True, - inputs={ - 'fields': [ - {'id': 'username', 'label': gettext_noop('Access Key'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Secret Key'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'security_token', - 'label': gettext_noop('STS Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop( - 'Security Token Service (STS) is a web service ' - 'that enables you to request temporary, ' - 'limited-privilege credentials for AWS Identity ' - 'and Access Management (IAM) users.' - ), - }, - ], - 'required': ['username', 'password'], - }, -) - -ManagedCredentialType( - namespace='openstack', - kind='cloud', - name=gettext_noop('OpenStack'), - managed=True, - inputs={ - 'fields': [ - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password (API Key)'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'host', - 'label': gettext_noop('Host (Authentication URL)'), - 'type': 'string', - 'help_text': gettext_noop('The host to authenticate with. For example, https://openstack.business.com/v2.0/'), - }, - { - 'id': 'project', - 'label': gettext_noop('Project (Tenant Name)'), - 'type': 'string', - }, - { - 'id': 'project_domain_name', - 'label': gettext_noop('Project (Domain Name)'), - 'type': 'string', - }, - { - 'id': 'domain', - 'label': gettext_noop('Domain Name'), - 'type': 'string', - 'help_text': gettext_noop( - 'OpenStack domains define administrative boundaries. ' - 'It is only needed for Keystone v3 authentication ' - 'URLs. Refer to the documentation for ' - 'common scenarios.' - ), - }, - { - 'id': 'region', - 'label': gettext_noop('Region Name'), - 'type': 'string', - 'help_text': gettext_noop('For some cloud providers, like OVH, region must be specified'), - }, - { - 'id': 'verify_ssl', - 'label': gettext_noop('Verify SSL'), - 'type': 'boolean', - 'default': True, - }, - ], - 'required': ['username', 'password', 'host', 'project'], - }, -) - -ManagedCredentialType( - namespace='vmware', - kind='cloud', - name=gettext_noop('VMware vCenter'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'host', - 'label': gettext_noop('VCenter Host'), - 'type': 'string', - 'help_text': gettext_noop('Enter the hostname or IP address that corresponds to your VMware vCenter.'), - }, - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - ], - 'required': ['host', 'username', 'password'], - }, -) - -ManagedCredentialType( - namespace='satellite6', - kind='cloud', - name=gettext_noop('Red Hat Satellite 6'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'host', - 'label': gettext_noop('Satellite 6 URL'), - 'type': 'string', - 'help_text': gettext_noop('Enter the URL that corresponds to your Red Hat Satellite 6 server. For example, https://satellite.example.org'), - }, - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - ], - 'required': ['host', 'username', 'password'], - }, -) - -ManagedCredentialType( - namespace='gce', - kind='cloud', - name=gettext_noop('Google Compute Engine'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'username', - 'label': gettext_noop('Service Account Email Address'), - 'type': 'string', - 'help_text': gettext_noop('The email address assigned to the Google Compute Engine service account.'), - }, - { - 'id': 'project', - 'label': 'Project', - 'type': 'string', - 'help_text': gettext_noop( - 'The Project ID is the GCE assigned identification. ' - 'It is often constructed as three words or two words ' - 'followed by a three-digit number. Examples: project-id-000 ' - 'and another-project-id' - ), - }, - { - 'id': 'ssh_key_data', - 'label': gettext_noop('RSA Private Key'), - 'type': 'string', - 'format': 'ssh_private_key', - 'secret': True, - 'multiline': True, - 'help_text': gettext_noop('Paste the contents of the PEM file associated with the service account email.'), - }, - ], - 'required': ['username', 'ssh_key_data'], - }, -) - -ManagedCredentialType( - namespace='azure_rm', - kind='cloud', - name=gettext_noop('Microsoft Azure Resource Manager'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'subscription', - 'label': gettext_noop('Subscription ID'), - 'type': 'string', - 'help_text': gettext_noop('Subscription ID is an Azure construct, which is mapped to a username.'), - }, - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - {'id': 'client', 'label': gettext_noop('Client ID'), 'type': 'string'}, - { - 'id': 'secret', - 'label': gettext_noop('Client Secret'), - 'type': 'string', - 'secret': True, - }, - {'id': 'tenant', 'label': gettext_noop('Tenant ID'), 'type': 'string'}, - { - 'id': 'cloud_environment', - 'label': gettext_noop('Azure Cloud Environment'), - 'type': 'string', - 'help_text': gettext_noop('Environment variable AZURE_CLOUD_ENVIRONMENT when using Azure GovCloud or Azure stack.'), - }, - ], - 'required': ['subscription'], - }, -) - -ManagedCredentialType( - namespace='github_token', - kind='token', - name=gettext_noop('GitHub Personal Access Token'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'token', - 'label': gettext_noop('Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('This token needs to come from your profile settings in GitHub'), - } - ], - 'required': ['token'], - }, -) - -ManagedCredentialType( - namespace='gitlab_token', - kind='token', - name=gettext_noop('GitLab Personal Access Token'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'token', - 'label': gettext_noop('Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('This token needs to come from your profile settings in GitLab'), - } - ], - 'required': ['token'], - }, -) - -ManagedCredentialType( - namespace='bitbucket_dc_token', - kind='token', - name=gettext_noop('Bitbucket Data Center HTTP Access Token'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'token', - 'label': gettext_noop('Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('This token needs to come from your user settings in Bitbucket'), - } - ], - 'required': ['token'], - }, -) - -insights = ManagedCredentialType( - namespace='insights', - kind='insights', - name=gettext_noop('Insights'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'username', - 'label': gettext_noop('Username'), - 'type': 'string', - 'help_text': gettext_noop( - 'Username is required for basic authentication.', - ), - }, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop( - 'Password is required for basic authentication', - ), - }, - { - 'id': 'client_id', - 'label': gettext_noop('Client ID'), - 'type': 'string', - 'help_text': gettext_noop( - 'Enter client ID to create a service account credential.', - ), - }, - { - 'id': 'client_secret', - 'label': gettext_noop('Client Secret'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop( - 'Enter client secret to create a service account credential.', - ), - }, - ], - 'required': [], - }, - injectors={ - 'extra_vars': { - 'scm_username': '{{username}}', - 'scm_password': '{{password}}', - 'client_id': '{{client_id}}', - 'client_secret': '{{client_secret}}', - 'authentication': '{% if client_id %}service_account{% else %}basic{% endif %}', - }, - 'env': { - 'INSIGHTS_USER': '{{username}}', - 'INSIGHTS_PASSWORD': '{{password}}', - 'INSIGHTS_CLIENT_ID': '{{client_id}}', - 'INSIGHTS_CLIENT_SECRET': '{{client_secret}}', - }, - }, -) - - -ManagedCredentialType( - namespace='rhv', - kind='cloud', - name=gettext_noop('Red Hat Virtualization'), - managed=True, - inputs={ - 'fields': [ - {'id': 'host', 'label': gettext_noop('Host (Authentication URL)'), 'type': 'string', 'help_text': gettext_noop('The host to authenticate with.')}, - {'id': 'username', 'label': gettext_noop('Username'), 'type': 'string'}, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'ca_file', - 'label': gettext_noop('CA File'), - 'type': 'string', - 'help_text': gettext_noop('Absolute file path to the CA file to use (optional)'), - }, - ], - 'required': ['host', 'username', 'password'], - }, - injectors={ - # The duplication here is intentional; the ovirt4 inventory plugin - # writes a .ini file for authentication, while the ansible modules for - # ovirt4 use a separate authentication process that support - # environment variables; by injecting both, we support both - 'file': { - 'template': '\n'.join( - [ - '[ovirt]', - 'ovirt_url={{host}}', - 'ovirt_username={{username}}', - 'ovirt_password={{password}}', - '{% if ca_file %}ovirt_ca_file={{ca_file}}{% endif %}', - ] - ) - }, - 'env': {'OVIRT_INI_PATH': '{{tower.filename}}', 'OVIRT_URL': '{{host}}', 'OVIRT_USERNAME': '{{username}}', 'OVIRT_PASSWORD': '{{password}}'}, - }, -) - -ManagedCredentialType( - namespace='controller', - kind='cloud', - name=gettext_noop('Red Hat Ansible Automation Platform'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'host', - 'label': gettext_noop('Red Hat Ansible Automation Platform'), - 'type': 'string', - 'help_text': gettext_noop('Red Hat Ansible Automation Platform base URL to authenticate with.'), - }, - { - 'id': 'username', - 'label': gettext_noop('Username'), - 'type': 'string', - 'help_text': gettext_noop( - 'Red Hat Ansible Automation Platform username id to authenticate as.This should not be set if an OAuth token is being used.' - ), - }, - { - 'id': 'password', - 'label': gettext_noop('Password'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'oauth_token', - 'label': gettext_noop('OAuth Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('An OAuth token to use to authenticate with.This should not be set if username/password are being used.'), - }, - {'id': 'verify_ssl', 'label': gettext_noop('Verify SSL'), 'type': 'boolean', 'secret': False}, - ], - 'required': ['host'], - }, - injectors={ - 'env': { - 'TOWER_HOST': '{{host}}', - 'TOWER_USERNAME': '{{username}}', - 'TOWER_PASSWORD': '{{password}}', - 'TOWER_VERIFY_SSL': '{{verify_ssl}}', - 'TOWER_OAUTH_TOKEN': '{{oauth_token}}', - 'CONTROLLER_HOST': '{{host}}', - 'CONTROLLER_USERNAME': '{{username}}', - 'CONTROLLER_PASSWORD': '{{password}}', - 'CONTROLLER_VERIFY_SSL': '{{verify_ssl}}', - 'CONTROLLER_OAUTH_TOKEN': '{{oauth_token}}', - } - }, -) - -ManagedCredentialType( - namespace='kubernetes_bearer_token', - kind='kubernetes', - name=gettext_noop('OpenShift or Kubernetes API Bearer Token'), - inputs={ - 'fields': [ - { - 'id': 'host', - 'label': gettext_noop('OpenShift or Kubernetes API Endpoint'), - 'type': 'string', - 'help_text': gettext_noop('The OpenShift or Kubernetes API Endpoint to authenticate with.'), - }, - { - 'id': 'bearer_token', - 'label': gettext_noop('API authentication bearer token'), - 'type': 'string', - 'secret': True, - }, - { - 'id': 'verify_ssl', - 'label': gettext_noop('Verify SSL'), - 'type': 'boolean', - 'default': True, - }, - { - 'id': 'ssl_ca_cert', - 'label': gettext_noop('Certificate Authority data'), - 'type': 'string', - 'secret': True, - 'multiline': True, - }, - ], - 'required': ['host', 'bearer_token'], - }, -) - -ManagedCredentialType( - namespace='registry', - kind='registry', - name=gettext_noop('Container Registry'), - inputs={ - 'fields': [ - { - 'id': 'host', - 'label': gettext_noop('Authentication URL'), - 'type': 'string', - 'help_text': gettext_noop('Authentication endpoint for the container registry.'), - 'default': 'quay.io', - }, - { - 'id': 'username', - 'label': gettext_noop('Username'), - 'type': 'string', - }, - { - 'id': 'password', - 'label': gettext_noop('Password or Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('A password or token used to authenticate with'), - }, - { - 'id': 'verify_ssl', - 'label': gettext_noop('Verify SSL'), - 'type': 'boolean', - 'default': True, - }, - ], - 'required': ['host'], - }, -) - - -ManagedCredentialType( - namespace='galaxy_api_token', - kind='galaxy', - name=gettext_noop('Ansible Galaxy/Automation Hub API Token'), - inputs={ - 'fields': [ - { - 'id': 'url', - 'label': gettext_noop('Galaxy Server URL'), - 'type': 'string', - 'help_text': gettext_noop('The URL of the Galaxy instance to connect to.'), - }, - { - 'id': 'auth_url', - 'label': gettext_noop('Auth Server URL'), - 'type': 'string', - 'help_text': gettext_noop('The URL of a Keycloak server token_endpoint, if using SSO auth.'), - }, - { - 'id': 'token', - 'label': gettext_noop('API Token'), - 'type': 'string', - 'secret': True, - 'help_text': gettext_noop('A token to use for authentication against the Galaxy instance.'), - }, - ], - 'required': ['url'], - }, -) - -ManagedCredentialType( - namespace='gpg_public_key', - kind='cryptography', - name=gettext_noop('GPG Public Key'), - inputs={ - 'fields': [ - { - 'id': 'gpg_public_key', - 'label': gettext_noop('GPG Public Key'), - 'type': 'string', - 'secret': True, - 'multiline': True, - 'help_text': gettext_noop('GPG Public Key used to validate content signatures.'), - }, - ], - 'required': ['gpg_public_key'], - }, -) - -ManagedCredentialType( - namespace='terraform', - kind='cloud', - name=gettext_noop('Terraform backend configuration'), - managed=True, - inputs={ - 'fields': [ - { - 'id': 'configuration', - 'label': gettext_noop('Backend configuration'), - 'type': 'string', - 'secret': True, - 'multiline': True, - 'help_text': gettext_noop('Terraform backend config as Hashicorp configuration language.'), - }, - { - 'id': 'gce_credentials', - 'label': gettext_noop('Google Cloud Platform account credentials'), - 'type': 'string', - 'secret': True, - 'multiline': True, - 'help_text': gettext_noop('Google Cloud Platform account credentials in JSON format.'), - }, - ], - 'required': ['configuration'], - }, -) - - -class CredentialInputSource(PrimordialModel): - class Meta: - app_label = 'main' - unique_together = (('target_credential', 'input_field_name'),) - ordering = ( - 'target_credential', - 'source_credential', - 'input_field_name', - ) - - FIELDS_TO_PRESERVE_AT_COPY = ['source_credential', 'metadata', 'input_field_name'] - - target_credential = models.ForeignKey( - 'Credential', - related_name='input_sources', - on_delete=models.CASCADE, - null=True, - ) - source_credential = models.ForeignKey( - 'Credential', - related_name='target_input_sources', - on_delete=models.CASCADE, - null=True, - ) - input_field_name = models.CharField( - max_length=1024, - ) - metadata = DynamicCredentialInputField(blank=True, default=dict) - - def clean_target_credential(self): - if self.target_credential.credential_type.kind == 'external': - raise ValidationError(_('Target must be a non-external credential')) - return self.target_credential - - def clean_source_credential(self): - if self.source_credential.credential_type.kind != 'external': - raise ValidationError(_('Source must be an external credential')) - return self.source_credential - - def clean_input_field_name(self): - defined_fields = self.target_credential.credential_type.defined_fields - if self.input_field_name not in defined_fields: - raise ValidationError(_('Input field must be defined on target credential (options are {}).'.format(', '.join(sorted(defined_fields))))) - return self.input_field_name - - def get_input_value(self): - backend = self.source_credential.credential_type.plugin.backend - backend_kwargs = {} - for field_name, value in self.source_credential.inputs.items(): - if field_name in self.source_credential.credential_type.secret_fields: - backend_kwargs[field_name] = decrypt_field(self.source_credential, field_name) - else: - backend_kwargs[field_name] = value - - backend_kwargs.update(self.metadata) - - with set_environ(**settings.AWX_TASK_ENV): - return backend(**backend_kwargs) - - def get_absolute_url(self, request=None): - view_name = 'api:credential_input_source_detail' - return reverse(view_name, kwargs={'pk': self.pk}, request=request) - - -for ns, plugin in credential_plugins.items(): - CredentialType.load_plugin(ns, plugin) diff --git a/awx/main/models/rbac.py b/awx/main/models/rbac.py index 13a10152c1..9fd9e5de74 100644 --- a/awx/main/models/rbac.py +++ b/awx/main/models/rbac.py @@ -749,81 +749,6 @@ def sync_parents_to_new_rbac(instance, action, model, pk_set, reverse, **kwargs) maybe_reverse_sync_unassignment(rd, team, child_role.content_object) -ROLE_DEFINITION_TO_ROLE_FIELD = { - 'Organization Member': 'member_role', - 'WorkflowJobTemplate Admin': 'admin_role', - 'Organization WorkflowJobTemplate Admin': 'workflow_admin_role', - 'WorkflowJobTemplate Execute': 'execute_role', - 'WorkflowJobTemplate Approve': 'approval_role', - 'InstanceGroup Admin': 'admin_role', - 'InstanceGroup Use': 'use_role', - 'Organization ExecutionEnvironment Admin': 'execution_environment_admin_role', - 'Project Admin': 'admin_role', - 'Organization Project Admin': 'project_admin_role', - 'Project Use': 'use_role', - 'Project Update': 'update_role', - 'JobTemplate Admin': 'admin_role', - 'Organization JobTemplate Admin': 'job_template_admin_role', - 'JobTemplate Execute': 'execute_role', - 'Inventory Admin': 'admin_role', - 'Organization Inventory Admin': 'inventory_admin_role', - 'Inventory Use': 'use_role', - 'Inventory Adhoc': 'adhoc_role', - 'Inventory Update': 'update_role', - 'Organization NotificationTemplate Admin': 'notification_admin_role', - 'Credential Admin': 'admin_role', - 'Organization Credential Admin': 'credential_admin_role', - 'Credential Use': 'use_role', - 'Team Admin': 'admin_role', - 'Team Member': 'member_role', - 'Organization Admin': 'admin_role', - 'Organization Audit': 'auditor_role', - 'Organization Execute': 'execute_role', - 'Organization Approval': 'approval_role', -} - - -def _sync_assignments_to_old_rbac(instance, delete=True): - from awx.main.signals import disable_activity_stream - - with disable_activity_stream(): - with disable_rbac_sync(): - field_name = ROLE_DEFINITION_TO_ROLE_FIELD.get(instance.role_definition.name) - if not field_name: - return - try: - role = getattr(instance.object_role.content_object, field_name) - # in the case RoleUserAssignment is being cascade deleted, then - # object_role might not exist. In which case the object is about to be removed - # anyways so just return - except ObjectDoesNotExist: - return - if isinstance(instance.actor, get_user_model()): - # user - if delete: - role.members.remove(instance.actor) - else: - role.members.add(instance.actor) - else: - # team - if delete: - instance.team.member_role.children.remove(role) - else: - instance.team.member_role.children.add(role) - - -@receiver(post_delete, sender=RoleUserAssignment) -@receiver(post_delete, sender=RoleTeamAssignment) -def sync_assignments_to_old_rbac_delete(instance, **kwargs): - _sync_assignments_to_old_rbac(instance, delete=True) - - -@receiver(post_save, sender=RoleUserAssignment) -@receiver(post_save, sender=RoleTeamAssignment) -def sync_user_assignments_to_old_rbac_create(instance, **kwargs): - _sync_assignments_to_old_rbac(instance, delete=False) - - ROLE_DEFINITION_TO_ROLE_FIELD = { 'Organization Member': 'member_role', 'Controller Organization Member': 'member_role', diff --git a/awx/main/tasks/jobs.py b/awx/main/tasks/jobs.py index e59f30ad66..2b0a458dc8 100644 --- a/awx/main/tasks/jobs.py +++ b/awx/main/tasks/jobs.py @@ -93,9 +93,6 @@ from awx.main.utils.update_model import update_model # Django flags from flags.state import flag_enabled -# Django flags -from flags.state import flag_enabled - logger = logging.getLogger('awx.main.tasks.jobs') diff --git a/awx/main/tasks/system.py b/awx/main/tasks/system.py index 4164cd3b8c..d80bace63d 100644 --- a/awx/main/tasks/system.py +++ b/awx/main/tasks/system.py @@ -13,25 +13,6 @@ from datetime import datetime from distutils.version import LooseVersion as Version from io import StringIO -# Django -from django.conf import settings -from django.db import connection, transaction, DatabaseError, IntegrityError -from django.db.models.fields.related import ForeignKey -from django.utils.timezone import now, timedelta -from django.utils.encoding import smart_str -from django.contrib.auth.models import User -from django.utils.translation import gettext_lazy as _ -from django.utils.translation import gettext_noop -from django.core.cache import cache -from django.core.exceptions import ObjectDoesNotExist -from django.db.models.query import QuerySet - -# Django-CRUM -from crum import impersonate - -# Django flags -from flags.state import flag_enabled - # Runner import ansible_runner.cleanup import psycopg @@ -91,13 +72,6 @@ from awx.main.tasks.receptor import administrative_workunit_reaper, get_receptor from awx.main.utils.common import ignore_inventory_computed_fields, ignore_inventory_group_removal from awx.main.utils.reload import stop_local_services from dispatcherd.publish import task -from awx.main.tasks.receptor import get_receptor_ctl, worker_info, worker_cleanup, administrative_workunit_reaper, write_receptor_config -from awx.main.consumers import emit_channel_notification -from awx.main import analytics -from awx.conf import settings_registry -from awx.main.analytics.subsystem_metrics import DispatcherMetrics - -from rest_framework.exceptions import PermissionDenied logger = logging.getLogger('awx.main.tasks.system') diff --git a/awx/main/tests/data/inventory/plugins/vmware_esxi/env.json b/awx/main/tests/data/inventory/plugins/vmware_esxi/env.json deleted file mode 100644 index e2e8c5bd91..0000000000 --- a/awx/main/tests/data/inventory/plugins/vmware_esxi/env.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "VMWARE_HOST": "https://foo.invalid", - "VMWARE_PASSWORD": "fooo", - "VMWARE_USER": "fooo", - "VMWARE_VALIDATE_CERTS": "False" -} \ No newline at end of file diff --git a/awx/main/tests/data/projects/host_query/meta/event_query.yml b/awx/main/tests/data/projects/host_query/meta/event_query.yml deleted file mode 100644 index 0c9e398c66..0000000000 --- a/awx/main/tests/data/projects/host_query/meta/event_query.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -{ - "demo.query.example": "" -} diff --git a/awx/main/tests/data/sleep_task.py b/awx/main/tests/data/sleep_task.py index f9ff58b69a..59bc6254e2 100644 --- a/awx/main/tests/data/sleep_task.py +++ b/awx/main/tests/data/sleep_task.py @@ -1,17 +1,57 @@ import time import logging +from dispatcherd.publish import task + +from django.db import connection + from awx.main.dispatch import get_task_queuename -from awx.main.dispatch.publish import task +from awx.main.dispatch.publish import task as old_task + +from ansible_base.lib.utils.db import advisory_lock logger = logging.getLogger(__name__) -@task(queue=get_task_queuename) +@old_task(queue=get_task_queuename) def sleep_task(seconds=10, log=False): if log: logger.info('starting sleep_task') time.sleep(seconds) if log: logger.info('finished sleep_task') + + +@task() +def sleep_break_connection(seconds=0.2): + """ + Interact with the database in an intentionally breaking way. + After this finishes, queries made by this connection are expected to error + with "the connection is closed" + This is obviously a problem for any task that comes afterwards. + So this is used to break things so that the fixes may be demonstrated. + """ + with connection.cursor() as cursor: + cursor.execute(f"SET idle_session_timeout = '{seconds / 2}s';") + + logger.info(f'sleeping for {seconds}s > {seconds / 2}s session timeout') + time.sleep(seconds) + + for i in range(1, 3): + logger.info(f'\nRunning query number {i}') + try: + with connection.cursor() as cursor: + cursor.execute("SELECT 1;") + logger.info(' query worked, not expected') + except Exception as exc: + logger.info(f' query errored as expected\ntype: {type(exc)}\nstr: {str(exc)}') + + logger.info(f'Connection present: {bool(connection.connection)}, reports closed: {getattr(connection.connection, "closed", "not_found")}') + + +@task() +def advisory_lock_exception(): + time.sleep(0.2) # so it can fill up all the workers... hacky for now + with advisory_lock('advisory_lock_exception', lock_session_timeout_milliseconds=20): + raise RuntimeError('this is an intentional error') diff --git a/awx/main/tests/functional/github_app_test.py b/awx/main/tests/functional/github_app_test.py deleted file mode 100644 index 2341a03654..0000000000 --- a/awx/main/tests/functional/github_app_test.py +++ /dev/null @@ -1,344 +0,0 @@ -"""Tests for GitHub App Installation access token extraction plugin.""" - -from typing import TypedDict - -import pytest -from pytest_mock import MockerFixture - -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.asymmetric.rsa import ( - RSAPrivateKey, - RSAPublicKey, - generate_private_key, -) -from cryptography.hazmat.primitives.serialization import ( - Encoding, - NoEncryption, - PrivateFormat, - PublicFormat, -) -from github.Auth import AppInstallationAuth -from github.Consts import DEFAULT_JWT_ALGORITHM -from github.GithubException import ( - BadAttributeException, - GithubException, - UnknownObjectException, -) -from jwt import decode as decode_jwt - -from awx.main.credential_plugins import github_app - - -github_app_jwt_client_id_unsupported = pytest.mark.xfail( - raises=(AssertionError, ValueError), - reason='Client ID in JWT is not currently supported by ' 'PyGitHub and is disabled.\n\n' 'Ref: https://github.com/PyGithub/PyGithub/issues/3213', -) - - -RSA_PUBLIC_EXPONENT = 65_537 # noqa: WPS303 -MINIMUM_RSA_KEY_SIZE = 1024 # the lowest value chosen for performance in tests - - -@pytest.fixture(scope='module') -def rsa_private_key() -> RSAPrivateKey: - """Generate an RSA private key.""" - return generate_private_key( - public_exponent=RSA_PUBLIC_EXPONENT, - key_size=MINIMUM_RSA_KEY_SIZE, # would be 4096 or higher in production - backend=default_backend(), - ) - - -@pytest.fixture(scope='module') -def rsa_public_key(rsa_private_key: RSAPrivateKey) -> RSAPublicKey: - """Extract a public key out of the private one.""" - return rsa_private_key.public_key() - - -@pytest.fixture(scope='module') -def rsa_private_key_bytes(rsa_private_key: RSAPrivateKey) -> bytes: - r"""Generate an unencrypted PKCS#1 formatted RSA private key. - - Encoded as PEM-bytes. - - This is what the GitHub-downloaded PEM files contain. - - Ref: https://developer.github.com/apps/building-github-apps/\ - authenticating-with-github-apps/ - """ - return rsa_private_key.private_bytes( - encoding=Encoding.PEM, - format=PrivateFormat.TraditionalOpenSSL, # A.K.A. PKCS#1 - encryption_algorithm=NoEncryption(), - ) - - -@pytest.fixture(scope='module') -def rsa_private_key_str(rsa_private_key_bytes: bytes) -> str: - """Return private key as an instance of string.""" - return rsa_private_key_bytes.decode('utf-8') - - -@pytest.fixture(scope='module') -def rsa_public_key_bytes(rsa_public_key: RSAPublicKey) -> bytes: - """Return a PKCS#1 formatted RSA public key encoded as PEM.""" - return rsa_public_key.public_bytes( - encoding=Encoding.PEM, - format=PublicFormat.PKCS1, - ) - - -class AppInstallIds(TypedDict): - """Schema for augmented extractor function keyword args.""" - - app_or_client_id: str - install_id: str - - -@pytest.mark.parametrize( - ('extract_github_app_install_token_args', 'expected_error_msg'), - ( - pytest.param( - { - 'app_or_client_id': 'invalid', - 'install_id': '666', - }, - '^Expected GitHub App or Client ID to be an integer or a string ' r'starting with `Iv1\.` followed by 16 hexadecimal digits, but got' " 'invalid'$", - id='gh-app-id-broken-text', - ), - pytest.param( - { - 'app_or_client_id': 'Iv1.bbbbbbbbbbbbbbb', - 'install_id': '666', - }, - '^Expected GitHub App or Client ID to be an integer or a string ' - r'starting with `Iv1\.` followed by 16 hexadecimal digits, but got' - " 'Iv1.bbbbbbbbbbbbbbb'$", - id='gh-app-id-client-id-not-enough-chars', - ), - pytest.param( - { - 'app_or_client_id': 'Iv1.bbbbbbbbbbbbbbbx', - 'install_id': '666', - }, - '^Expected GitHub App or Client ID to be an integer or a string ' - r'starting with `Iv1\.` followed by 16 hexadecimal digits, but got' - " 'Iv1.bbbbbbbbbbbbbbbx'$", - id='gh-app-id-client-id-broken-hex', - ), - pytest.param( - { - 'app_or_client_id': 'Iv1.bbbbbbbbbbbbbbbbb', - 'install_id': '666', - }, - '^Expected GitHub App or Client ID to be an integer or a string ' - r'starting with `Iv1\.` followed by 16 hexadecimal digits, but got' - " 'Iv1.bbbbbbbbbbbbbbbbb'$", - id='gh-app-id-client-id-too-many-chars', - ), - pytest.param( - { - 'app_or_client_id': 999, - 'install_id': 'invalid', - }, - '^Expected GitHub App Installation ID to be an integer ' "but got 'invalid'$", - id='gh-app-invalid-install-id-with-int-app-id', - ), - pytest.param( - { - 'app_or_client_id': '999', - 'install_id': 'invalid', - }, - '^Expected GitHub App Installation ID to be an integer ' "but got 'invalid'$", - id='gh-app-invalid-install-id-with-str-digit-app-id', - ), - pytest.param( - { - 'app_or_client_id': 'Iv1.cccccccccccccccc', - 'install_id': 'invalid', - }, - '^Expected GitHub App Installation ID to be an integer ' "but got 'invalid'$", - id='gh-app-invalid-install-id-with-client-id', - marks=github_app_jwt_client_id_unsupported, - ), - ), -) -def test_github_app_invalid_args( - extract_github_app_install_token_args: AppInstallIds, - expected_error_msg: str, -) -> None: - """Test that invalid arguments make token extractor bail early.""" - with pytest.raises(ValueError, match=expected_error_msg): - github_app.extract_github_app_install_token( - github_api_url='https://github.com', - private_rsa_key='key', - **extract_github_app_install_token_args, - ) - - -@pytest.mark.parametrize( - ( - 'github_exception', - 'transformed_exception', - 'error_msg', - ), - ( - ( - BadAttributeException( - '', - {}, - Exception(), - ), - RuntimeError, - ( - r'^Broken GitHub @ https://github\.com with ' - r'app_or_client_id: 123, install_id: 456\. It is a bug, ' - 'please report it to the ' - r"developers\.\n\n\('', \{\}, Exception\(\)\)$" - ), - ), - ( - GithubException(-1), - RuntimeError, - ( - '^An unexpected error happened while talking to GitHub API ' - r'@ https://github\.com ' - r'\(app_or_client_id: 123, install_id: 456\)\. ' - r'Is the app or client ID correct\? ' - r'And the private RSA key\? ' - r'See https://docs\.github\.com/rest/reference/apps' - r'#create-an-installation-access-token-for-an-app\.' - r'\n\n-1$' - ), - ), - ( - UnknownObjectException(-1), - ValueError, - ( - '^Failed to retrieve a GitHub installation token from ' - r'https://github\.com using ' - r'app_or_client_id: 123, install_id: 456\. ' - r'Is the app installed\? See ' - r'https://docs\.github\.com/rest/reference/apps' - r'#create-an-installation-access-token-for-an-app\.' - r'\n\n-1$' - ), - ), - ), - ids=( - 'github-broken', - 'unexpected-error', - 'no-install', - ), -) -def test_github_app_api_errors( - mocker: MockerFixture, - github_exception: Exception, - transformed_exception: type[Exception], - error_msg: str, -) -> None: - """Test successful GitHub authentication.""" - application_id = 123 - installation_id = 456 - - mocker.patch.object( - github_app.Auth.AppInstallationAuth, - 'token', - new_callable=mocker.PropertyMock, - side_effect=github_exception, - ) - - with pytest.raises(transformed_exception, match=error_msg): - github_app.extract_github_app_install_token( - github_api_url='https://github.com', - app_or_client_id=application_id, - install_id=installation_id, - private_rsa_key='key', - ) - - -class _FakeAppInstallationAuth(AppInstallationAuth): - @property - def token(self: '_FakeAppInstallationAuth') -> str: - return 'token-sentinel' - - -@pytest.mark.parametrize( - 'application_id', - ( - 123, - '123', - pytest.param( - 'Iv1.aaaaaaaaaaaaaaaa', - marks=github_app_jwt_client_id_unsupported, - ), - ), - ids=('app-id-int', 'app-id-str', 'client-id'), -) -@pytest.mark.parametrize( - 'installation_id', - (456, '456'), - ids=('install-id-int', 'install-id-str'), -) -# pylint: disable-next=too-many-arguments,too-many-positional-arguments -def test_github_app_github_authentication( # noqa: WPS211 - application_id: int | str, - installation_id: int | str, - mocker: MockerFixture, - monkeypatch: pytest.MonkeyPatch, - rsa_private_key_str: str, - rsa_public_key_bytes: bytes, -) -> None: - """Test successful GitHub authentication.""" - monkeypatch.setattr( - github_app.Auth, - 'AppInstallationAuth', - _FakeAppInstallationAuth, - ) - - get_installation_auth_spy = mocker.spy( - github_app.Auth, - 'AppInstallationAuth', - ) - github_initializer_spy = mocker.spy(github_app, 'Github') - - token = github_app.extract_github_app_install_token( - github_api_url='https://github.com', - app_or_client_id=application_id, - install_id=installation_id, - private_rsa_key=rsa_private_key_str, - ) - - observed_pygithub_obj = github_initializer_spy.spy_return - observed_gh_install_auth_obj = get_installation_auth_spy.spy_return - # pylint: disable-next=protected-access - signed_jwt = observed_gh_install_auth_obj._app_auth.token # noqa: WPS437 - - assert token == 'token-sentinel' - - assert observed_pygithub_obj.requester.base_url == 'https://github.com' - - assert observed_gh_install_auth_obj.installation_id == int(installation_id) - assert isinstance(observed_gh_install_auth_obj, _FakeAppInstallationAuth) - - # NOTE: The `decode_jwt()` call asserts that no - # NOTE: `jwt.exceptions.InvalidSignatureError()` exception gets raised - # NOTE: which would indicate incorrect RSA key or corrupted payload if - # NOTE: that was to happen. This verifies that JWT is signed with the - # NOTE: private RSA key we passed by using its public counterpart. - decode_jwt( - signed_jwt, - key=rsa_public_key_bytes, - algorithms=[DEFAULT_JWT_ALGORITHM], - options={ - 'require': ['exp', 'iat', 'iss'], - 'strict_aud': False, - 'verify_aud': True, - 'verify_exp': True, - 'verify_signature': True, - 'verify_nbf': True, - }, - audience=None, # GH App JWT don't set the audience claim - issuer=str(application_id), - leeway=0.001, # noqa: WPS432 - ) diff --git a/awx/main/tests/functional/test_credential_plugins.py b/awx/main/tests/functional/test_credential_plugins.py deleted file mode 100644 index ecfb77c3b8..0000000000 --- a/awx/main/tests/functional/test_credential_plugins.py +++ /dev/null @@ -1,217 +0,0 @@ -import pytest -from unittest import mock -from awx.main.credential_plugins import hashivault, azure_kv - -from azure.keyvault.secrets import ( - KeyVaultSecret, - SecretClient, - SecretProperties, -) - - -def test_imported_azure_cloud_sdk_vars(): - from awx.main.credential_plugins import azure_kv - - assert len(azure_kv.clouds) > 0 - assert all([hasattr(c, 'name') for c in azure_kv.clouds]) - assert all([hasattr(c, 'suffixes') for c in azure_kv.clouds]) - assert all([hasattr(c.suffixes, 'keyvault_dns') for c in azure_kv.clouds]) - - -def test_hashivault_approle_auth(): - kwargs = { - 'role_id': 'the_role_id', - 'secret_id': 'the_secret_id', - } - expected_res = { - 'role_id': 'the_role_id', - 'secret_id': 'the_secret_id', - } - res = hashivault.approle_auth(**kwargs) - assert res == expected_res - - -def test_hashivault_kubernetes_auth(): - kwargs = { - 'kubernetes_role': 'the_kubernetes_role', - } - expected_res = { - 'role': 'the_kubernetes_role', - 'jwt': 'the_jwt', - } - with mock.patch('pathlib.Path') as path_mock: - mock.mock_open(path_mock.return_value.open, read_data='the_jwt') - res = hashivault.kubernetes_auth(**kwargs) - path_mock.assert_called_with('/var/run/secrets/kubernetes.io/serviceaccount/token') - assert res == expected_res - - -def test_hashivault_client_cert_auth_explicit_role(): - kwargs = { - 'client_cert_role': 'test-cert-1', - } - expected_res = { - 'name': 'test-cert-1', - } - res = hashivault.client_cert_auth(**kwargs) - assert res == expected_res - - -def test_hashivault_client_cert_auth_no_role(): - kwargs = {} - expected_res = { - 'name': None, - } - res = hashivault.client_cert_auth(**kwargs) - assert res == expected_res - - -def test_hashivault_userpass_auth(): - kwargs = {'username': 'the_username', 'password': 'the_password'} - expected_res = {'username': 'the_username', 'password': 'the_password'} - res = hashivault.userpass_auth(**kwargs) - assert res == expected_res - - -def test_hashivault_handle_auth_token(): - kwargs = { - 'token': 'the_token', - } - token = hashivault.handle_auth(**kwargs) - assert token == kwargs['token'] - - -def test_hashivault_handle_auth_approle(): - kwargs = { - 'role_id': 'the_role_id', - 'secret_id': 'the_secret_id', - } - with mock.patch.object(hashivault, 'method_auth') as method_mock: - method_mock.return_value = 'the_token' - token = hashivault.handle_auth(**kwargs) - method_mock.assert_called_with(**kwargs, auth_param=kwargs) - assert token == 'the_token' - - -def test_hashivault_handle_auth_kubernetes(): - kwargs = { - 'kubernetes_role': 'the_kubernetes_role', - } - with mock.patch.object(hashivault, 'method_auth') as method_mock: - with mock.patch('pathlib.Path') as path_mock: - mock.mock_open(path_mock.return_value.open, read_data='the_jwt') - method_mock.return_value = 'the_token' - token = hashivault.handle_auth(**kwargs) - method_mock.assert_called_with(**kwargs, auth_param={'role': 'the_kubernetes_role', 'jwt': 'the_jwt'}) - assert token == 'the_token' - - -def test_hashivault_handle_auth_client_cert(): - kwargs = { - 'client_cert_public': "foo", - 'client_cert_private': "bar", - 'client_cert_role': 'test-cert-1', - } - auth_params = { - 'name': 'test-cert-1', - } - with mock.patch.object(hashivault, 'method_auth') as method_mock: - method_mock.return_value = 'the_token' - token = hashivault.handle_auth(**kwargs) - method_mock.assert_called_with(**kwargs, auth_param=auth_params) - assert token == 'the_token' - - -def test_hashivault_handle_auth_not_enough_args(): - with pytest.raises(Exception): - hashivault.handle_auth() - - -class TestDelineaImports: - """ - These module have a try-except for ImportError which will allow using the older library - but we do not want the awx_devel image to have the older library, - so these tests are designed to fail if these wind up using the fallback import - """ - - def test_dsv_import(self): - from awx.main.credential_plugins.dsv import SecretsVault # noqa - - # assert this module as opposed to older thycotic.secrets.vault - assert SecretsVault.__module__ == 'delinea.secrets.vault' - - def test_tss_import(self): - from awx.main.credential_plugins.tss import DomainPasswordGrantAuthorizer, PasswordGrantAuthorizer, SecretServer, ServerSecret # noqa - - for cls in (DomainPasswordGrantAuthorizer, PasswordGrantAuthorizer, SecretServer, ServerSecret): - # assert this module as opposed to older thycotic.secrets.server - assert cls.__module__ == 'delinea.secrets.server' - - -class _FakeSecretClient(SecretClient): - def get_secret( - self: '_FakeSecretClient', - name: str, - version: str | None = None, - **kwargs: str, - ) -> KeyVaultSecret: - props = SecretProperties(None, None) - return KeyVaultSecret(properties=props, value='test-secret') - - -def test_azure_kv_invalid_env() -> None: - """Test running outside of Azure raises error.""" - error_msg = ( - 'You are not operating on an Azure VM, so the Managed Identity ' - 'feature is unavailable. Please provide the full Client ID, ' - 'Client Secret, and Tenant ID or run the software on an Azure VM.' - ) - - with pytest.raises( - RuntimeError, - match=error_msg, - ): - azure_kv.azure_keyvault_backend( - url='https://test.vault.azure.net', - client='', - secret='client-secret', - tenant='tenant-id', - secret_field='secret', - secret_version='', - ) - - -@pytest.mark.parametrize( - ('client', 'secret', 'tenant'), - ( - pytest.param('', '', '', id='managed-identity'), - pytest.param( - 'client-id', - 'client-secret', - 'tenant-id', - id='client-secret-credential', - ), - ), -) -def test_azure_kv_valid_auth( - monkeypatch: pytest.MonkeyPatch, - client: str, - secret: str, - tenant: str, -) -> None: - """Test successful Azure authentication via Managed Identity and credentials.""" - monkeypatch.setattr( - azure_kv, - 'SecretClient', - _FakeSecretClient, - ) - - keyvault_secret = azure_kv.azure_keyvault_backend( - url='https://test.vault.azure.net', - client=client, - secret=secret, - tenant=tenant, - secret_field='secret', - secret_version='', - ) - assert keyvault_secret == 'test-secret' diff --git a/awx/main/tests/functional/test_ha.py b/awx/main/tests/functional/test_ha.py deleted file mode 100644 index bf8c5309c7..0000000000 --- a/awx/main/tests/functional/test_ha.py +++ /dev/null @@ -1,45 +0,0 @@ -import pytest - -# AWX -from awx.main.ha import is_ha_environment -from awx.main.models.ha import Instance -from awx.main.dispatch.pool import get_auto_max_workers - -# Django -from django.test.utils import override_settings - - -@pytest.mark.django_db -def test_multiple_instances(): - for i in range(2): - Instance.objects.create(hostname=f'foo{i}', node_type='hybrid') - assert is_ha_environment() - - -@pytest.mark.django_db -def test_db_localhost(): - Instance.objects.create(hostname='foo', node_type='hybrid') - Instance.objects.create(hostname='bar', node_type='execution') - assert is_ha_environment() is False - - -@pytest.mark.django_db -@pytest.mark.parametrize( - 'settings', - [ - dict(SYSTEM_TASK_ABS_MEM='16Gi', SYSTEM_TASK_ABS_CPU='24', SYSTEM_TASK_FORKS_MEM=400, SYSTEM_TASK_FORKS_CPU=4), - dict(SYSTEM_TASK_ABS_MEM='124Gi', SYSTEM_TASK_ABS_CPU='2', SYSTEM_TASK_FORKS_MEM=None, SYSTEM_TASK_FORKS_CPU=None), - ], - ids=['cpu_dominated', 'memory_dominated'], -) -def test_dispatcher_max_workers_reserve(settings, fake_redis): - """This tests that the dispatcher max_workers matches instance capacity - - Assumes capacity_adjustment is 1, - plus reserve worker count - """ - with override_settings(**settings): - i = Instance.objects.create(hostname='test-1', node_type='hybrid') - i.local_health_check() - - assert get_auto_max_workers() == i.capacity + 7, (i.cpu, i.memory, i.cpu_capacity, i.mem_capacity) diff --git a/awx/main/tests/functional/test_jt_rename_migration.py b/awx/main/tests/functional/test_jt_rename_migration.py deleted file mode 100644 index 4d624c41be..0000000000 --- a/awx/main/tests/functional/test_jt_rename_migration.py +++ /dev/null @@ -1,56 +0,0 @@ -import pytest - -from awx.main.migrations._db_constraints import _rename_duplicates -from awx.main.models import JobTemplate - - -@pytest.mark.django_db -def test_rename_job_template_duplicates(organization, project): - ids = [] - for i in range(5): - jt = JobTemplate.objects.create(name=f'jt-{i}', organization=organization, project=project) - ids.append(jt.id) # saved in order of creation - - # Hack to first allow duplicate names of JT to test migration - JobTemplate.objects.filter(id__in=ids).update(org_unique=False) - - # Set all JTs to the same name - JobTemplate.objects.filter(id__in=ids).update(name='same_name_for_test') - - _rename_duplicates(JobTemplate) - - first_jt = JobTemplate.objects.get(id=ids[0]) - assert first_jt.name == 'same_name_for_test' - - for i, pk in enumerate(ids): - if i == 0: - continue - jt = JobTemplate.objects.get(id=pk) - # Name should be set based on creation order - assert jt.name == f'same_name_for_test_dup{i}' - - -@pytest.mark.django_db -def test_rename_job_template_name_too_long(organization, project): - ids = [] - for i in range(3): - jt = JobTemplate.objects.create(name=f'jt-{i}', organization=organization, project=project) - ids.append(jt.id) # saved in order of creation - - JobTemplate.objects.filter(id__in=ids).update(org_unique=False) - - chars = 512 - # Set all JTs to the same reaaaaaaly long name - JobTemplate.objects.filter(id__in=ids).update(name='A' * chars) - - _rename_duplicates(JobTemplate) - - first_jt = JobTemplate.objects.get(id=ids[0]) - assert first_jt.name == 'A' * chars - - for i, pk in enumerate(ids): - if i == 0: - continue - jt = JobTemplate.objects.get(id=pk) - assert jt.name.endswith(f'dup{i}') - assert len(jt.name) <= 512 diff --git a/awx/main/tests/functional/test_migrations.py b/awx/main/tests/functional/test_migrations.py index a3c188efd1..371b333e17 100644 --- a/awx/main/tests/functional/test_migrations.py +++ b/awx/main/tests/functional/test_migrations.py @@ -2,7 +2,6 @@ import pytest from django_test_migrations.plan import all_migrations, nodes_to_tuples from django.utils.timezone import now -from django.utils import timezone """ Most tests that live in here can probably be deleted at some point. They are mainly diff --git a/awx/main/tests/functional/test_tasks.py b/awx/main/tests/functional/test_tasks.py deleted file mode 100644 index 8e5305807f..0000000000 --- a/awx/main/tests/functional/test_tasks.py +++ /dev/null @@ -1,96 +0,0 @@ -import pytest -import os -import tempfile -import shutil - -from awx.main.tasks.jobs import RunJob -from awx.main.tasks.system import CleanupImagesAndFiles, execution_node_health_check -from awx.main.models import Instance, Job - - -@pytest.fixture -def scm_revision_file(tmpdir_factory): - # Returns path to temporary testing revision file - revision_file = tmpdir_factory.mktemp('revisions').join('revision.txt') - with open(str(revision_file), 'w') as f: - f.write('1234567890123456789012345678901234567890') - return os.path.join(revision_file.dirname, 'revision.txt') - - -@pytest.mark.django_db -@pytest.mark.parametrize('node_type', ('control. hybrid')) -def test_no_worker_info_on_AWX_nodes(node_type): - hostname = 'us-south-3-compute.invalid' - Instance.objects.create(hostname=hostname, node_type=node_type) - assert execution_node_health_check(hostname) is None - - -@pytest.fixture -def job_folder_factory(request): - def _rf(job_id='1234'): - pdd_path = tempfile.mkdtemp(prefix=f'awx_{job_id}_') - - def test_folder_cleanup(): - if os.path.exists(pdd_path): - shutil.rmtree(pdd_path) - - request.addfinalizer(test_folder_cleanup) - - return pdd_path - - return _rf - - -@pytest.fixture -def mock_job_folder(job_folder_factory): - return job_folder_factory() - - -@pytest.mark.django_db -def test_folder_cleanup_stale_file(mock_job_folder, mock_me): - CleanupImagesAndFiles.run() - assert os.path.exists(mock_job_folder) # grace period should protect folder from deletion - - CleanupImagesAndFiles.run(grace_period=0) - assert not os.path.exists(mock_job_folder) # should be deleted - - -@pytest.mark.django_db -def test_folder_cleanup_running_job(mock_job_folder, me_inst): - job = Job.objects.create(id=1234, controller_node=me_inst.hostname, status='running') - CleanupImagesAndFiles.run(grace_period=0) - assert os.path.exists(mock_job_folder) # running job should prevent folder from getting deleted - - job.status = 'failed' - job.save(update_fields=['status']) - CleanupImagesAndFiles.run(grace_period=0) - assert not os.path.exists(mock_job_folder) # job is finished and no grace period, should delete - - -@pytest.mark.django_db -def test_folder_cleanup_multiple_running_jobs(job_folder_factory, me_inst): - jobs = [] - dirs = [] - num_jobs = 3 - - for i in range(num_jobs): - job = Job.objects.create(controller_node=me_inst.hostname, status='running') - dirs.append(job_folder_factory(job.id)) - jobs.append(job) - - CleanupImagesAndFiles.run(grace_period=0) - - assert [os.path.exists(d) for d in dirs] == [True for i in range(num_jobs)] - - -@pytest.mark.django_db -def test_does_not_run_reaped_job(mocker, mock_me): - job = Job.objects.create(status='failed', job_explanation='This job has been reaped.') - mock_run = mocker.patch('awx.main.tasks.jobs.ansible_runner.interface.run') - try: - RunJob().run(job.id) - except Exception: - pass - job.refresh_from_db() - assert job.status == 'failed' - mock_run.assert_not_called() diff --git a/awx/main/tests/live/tests/conftest.py b/awx/main/tests/live/tests/conftest.py index 5842aa94c0..6c932d7b86 100644 --- a/awx/main/tests/live/tests/conftest.py +++ b/awx/main/tests/live/tests/conftest.py @@ -3,6 +3,7 @@ import time import os import shutil import tempfile +import logging import pytest @@ -13,11 +14,15 @@ from awx.api.versioning import reverse # These tests are invoked from the awx/main/tests/live/ subfolder # so any fixtures from higher-up conftest files must be explicitly included from awx.main.tests.functional.conftest import * # noqa +from awx.main.tests.conftest import load_all_credentials # noqa: F401; pylint: disable=unused-import from awx.main.tests import data from awx.main.models import Project, JobTemplate, Organization, Inventory +logger = logging.getLogger(__name__) + + PROJ_DATA = os.path.join(os.path.dirname(data.__file__), 'projects') @@ -133,30 +138,29 @@ def podman_image_generator(): @pytest.fixture -def run_job_from_playbook(default_org, demo_inv, post, admin): - def _rf(test_name, playbook, local_path=None, scm_url=None, jt_params=None): - project_name = f'{test_name} project' - jt_name = f'{test_name} JT: {playbook}' - - old_proj = Project.objects.filter(name=project_name).first() - if old_proj: - old_proj.delete() - - old_jt = JobTemplate.objects.filter(name=jt_name).first() - if old_jt: - old_jt.delete() - - proj_kwargs = {'name': project_name, 'organization': default_org.id} +def project_factory(post, default_org, admin): + def _rf(scm_url=None, local_path=None): + proj_kwargs = {} if local_path: # manual path + project_name = f'Manual roject {local_path}' proj_kwargs['scm_type'] = '' proj_kwargs['local_path'] = local_path elif scm_url: + project_name = f'Project {scm_url}' proj_kwargs['scm_type'] = 'git' proj_kwargs['scm_url'] = scm_url else: raise RuntimeError('Need to provide scm_url or local_path') + proj_kwargs['name'] = project_name + proj_kwargs['organization'] = default_org.id + + old_proj = Project.objects.filter(name=project_name).first() + if old_proj: + logger.info(f'Deleting existing project {project_name}') + old_proj.delete() + result = post( reverse('api:project_list'), proj_kwargs, @@ -164,6 +168,23 @@ def run_job_from_playbook(default_org, demo_inv, post, admin): expect=201, ) proj = Project.objects.get(id=result.data['id']) + return proj + + return _rf + + +@pytest.fixture +def run_job_from_playbook(demo_inv, post, admin, project_factory): + def _rf(test_name, playbook, local_path=None, scm_url=None, jt_params=None, proj=None, wait=True): + jt_name = f'{test_name} JT: {playbook}' + + if not proj: + proj = project_factory(scm_url=scm_url, local_path=local_path) + + old_jt = JobTemplate.objects.filter(name=jt_name).first() + if old_jt: + logger.info(f'Deleting existing JT {jt_name}') + old_jt.delete() if proj.current_job: wait_for_job(proj.current_job) @@ -185,7 +206,9 @@ def run_job_from_playbook(default_org, demo_inv, post, admin): job = jt.create_unified_job() job.signal_start() - wait_for_job(job) - assert job.status == 'successful' + if wait: + wait_for_job(job) + assert job.status == 'successful' + return {'job': job, 'job_template': jt, 'project': proj} return _rf diff --git a/awx/main/tests/unit/commands/test_import_auth_config_to_gateway.py b/awx/main/tests/unit/commands/test_import_auth_config_to_gateway.py deleted file mode 100644 index cfb7e64ac5..0000000000 --- a/awx/main/tests/unit/commands/test_import_auth_config_to_gateway.py +++ /dev/null @@ -1,581 +0,0 @@ -import os -import pytest -from unittest.mock import patch, Mock, call, DEFAULT -from io import StringIO -from unittest import TestCase - -from awx.main.management.commands.import_auth_config_to_gateway import Command -from awx.main.utils.gateway_client import GatewayAPIError - - -class TestImportAuthConfigToGatewayCommand(TestCase): - def setUp(self): - self.command = Command() - - def options_basic_auth_full_send(self): - return { - 'basic_auth': True, - 'skip_all_authenticators': False, - 'skip_oidc': False, - 'skip_github': False, - 'skip_ldap': False, - 'skip_ad': False, - 'skip_saml': False, - 'skip_radius': False, - 'skip_tacacs': False, - 'skip_google': False, - 'skip_settings': False, - 'force': False, - } - - def options_basic_auth_skip_all_individual(self): - return { - 'basic_auth': True, - 'skip_all_authenticators': False, - 'skip_oidc': True, - 'skip_github': True, - 'skip_ldap': True, - 'skip_ad': True, - 'skip_saml': True, - 'skip_radius': True, - 'skip_tacacs': True, - 'skip_google': True, - 'skip_settings': True, - 'force': False, - } - - def options_svc_token_full_send(self): - options = self.options_basic_auth_full_send() - options['basic_auth'] = False - return options - - def options_svc_token_skip_all(self): - options = self.options_basic_auth_skip_all_individual() - options['basic_auth'] = False - return options - - def create_mock_migrator( - self, - mock_migrator_class, - authenticator_type="TestAuth", - created=0, - updated=0, - unchanged=0, - failed=0, - mappers_created=0, - mappers_updated=0, - mappers_failed=0, - settings_created=0, - settings_updated=0, - settings_unchanged=0, - settings_failed=0, - ): - """Helper method to create a mock migrator with specified return values.""" - mock_migrator = Mock() - mock_migrator.get_authenticator_type.return_value = authenticator_type - mock_migrator.migrate.return_value = { - 'created': created, - 'updated': updated, - 'unchanged': unchanged, - 'failed': failed, - 'mappers_created': mappers_created, - 'mappers_updated': mappers_updated, - 'mappers_failed': mappers_failed, - } - mock_migrator_class.return_value = mock_migrator - return mock_migrator - - def test_add_arguments(self): - """Test that all expected arguments are properly added to the parser.""" - parser = Mock() - self.command.add_arguments(parser) - - expected_calls = [ - call('--basic-auth', action='store_true', help='Use HTTP Basic Authentication between Controller and Gateway'), - call( - '--skip-all-authenticators', - action='store_true', - help='Skip importing all authenticators [GitHub, OIDC, SAML, Azure AD, LDAP, RADIUS, TACACS+, Google OAuth2]', - ), - call('--skip-oidc', action='store_true', help='Skip importing generic OIDC authenticators'), - call('--skip-github', action='store_true', help='Skip importing GitHub authenticator'), - call('--skip-ldap', action='store_true', help='Skip importing LDAP authenticators'), - call('--skip-ad', action='store_true', help='Skip importing Azure AD authenticator'), - call('--skip-saml', action='store_true', help='Skip importing SAML authenticator'), - call('--skip-radius', action='store_true', help='Skip importing RADIUS authenticator'), - call('--skip-tacacs', action='store_true', help='Skip importing TACACS+ authenticator'), - call('--skip-google', action='store_true', help='Skip importing Google OAuth2 authenticator'), - call('--skip-settings', action='store_true', help='Skip importing settings'), - call( - '--force', - action='store_true', - help='Force migration even if configurations already exist. Does not apply to skipped authenticators nor skipped settings.', - ), - ] - - parser.add_argument.assert_has_calls(expected_calls, any_order=True) - - @patch.dict(os.environ, {}, clear=True) - @patch('sys.stdout', new_callable=StringIO) - def test_handle_missing_env_vars_basic_auth(self, mock_stdout): - """Test that missing environment variables cause clean exit when using basic auth.""" - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**self.options_basic_auth_full_send()) - # Should exit with code 0 for successful early validation - assert exc_info.value.code == 0 - - output = mock_stdout.getvalue() - self.assertIn('Missing required environment variables:', output) - self.assertIn('GATEWAY_BASE_URL', output) - self.assertIn('GATEWAY_USER', output) - self.assertIn('GATEWAY_PASSWORD', output) - - @patch.dict( - os.environ, - {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass', 'GATEWAY_SKIP_VERIFY': 'true'}, - ) - @patch('awx.main.management.commands.import_auth_config_to_gateway.SettingsMigrator') - @patch.multiple( - 'awx.main.management.commands.import_auth_config_to_gateway', - GitHubMigrator=DEFAULT, - OIDCMigrator=DEFAULT, - SAMLMigrator=DEFAULT, - AzureADMigrator=DEFAULT, - LDAPMigrator=DEFAULT, - RADIUSMigrator=DEFAULT, - TACACSMigrator=DEFAULT, - GoogleOAuth2Migrator=DEFAULT, - ) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('sys.stdout', new_callable=StringIO) - def test_handle_basic_auth_success(self, mock_stdout, mock_gateway_client, mock_settings_migrator, **mock_migrators): - """Test successful execution with basic auth.""" - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - for mock_migrator_class in mock_migrators.values(): - self.create_mock_migrator(mock_migrator_class, created=1, mappers_created=2) - - self.create_mock_migrator(mock_settings_migrator, settings_created=1, settings_updated=0, settings_unchanged=2, settings_failed=0) - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**self.options_basic_auth_full_send()) - # Should exit with code 0 for success - assert exc_info.value.code == 0 - - # Verify gateway client was created with correct parameters - mock_gateway_client.assert_called_once_with( - base_url='https://gateway.example.com', username='testuser', password='testpass', skip_verify=True, command=self.command - ) - - # Verify all migrators were created - for mock_migrator in mock_migrators.values(): - mock_migrator.assert_called_once_with(mock_client_instance, self.command, force=False) - - mock_settings_migrator.assert_called_once_with(mock_client_instance, self.command, force=False) - - # Verify output contains success messages - output = mock_stdout.getvalue() - - self.assertIn('HTTP Basic Auth: true', output) - self.assertIn('Successfully connected to Gateway', output) - self.assertIn('Migration Summary', output) - self.assertIn('authenticators', output) - self.assertIn('mappers', output) - self.assertIn('settings', output) - - @patch.dict(os.environ, {'GATEWAY_SKIP_VERIFY': 'false'}, clear=True) # Ensure verify_https=True - @patch('awx.main.management.commands.import_auth_config_to_gateway.create_api_client') - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClientSVCToken') - @patch('awx.main.management.commands.import_auth_config_to_gateway.urlparse') - @patch('awx.main.management.commands.import_auth_config_to_gateway.urlunparse') - @patch('sys.stdout', new_callable=StringIO) - def test_handle_service_token_success(self, mock_stdout, mock_urlunparse, mock_urlparse, mock_gateway_client_svc, mock_create_api_client): - """Test successful execution with service token.""" - # Mock resource API client - mock_resource_client = Mock() - mock_resource_client.base_url = 'https://gateway.example.com/api/v1' - mock_resource_client.jwt_user_id = 'test-user' - mock_resource_client.jwt_expiration = '2024-12-31' - mock_resource_client.verify_https = True - mock_response = Mock() - mock_response.status_code = 200 - mock_resource_client.get_service_metadata.return_value = mock_response - mock_create_api_client.return_value = mock_resource_client - - # Mock URL parsing - mock_parsed = Mock() - mock_parsed.scheme = 'https' - mock_parsed.netloc = 'gateway.example.com' - mock_urlparse.return_value = mock_parsed - mock_urlunparse.return_value = 'https://gateway.example.com/' - - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client_svc.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client_svc.return_value.__exit__.return_value = None - - with patch.object(self.command, 'stdout', mock_stdout): - with patch('sys.exit'): - self.command.handle(**self.options_svc_token_skip_all()) - # Should call sys.exit(0) for success, but may not due to test setup - # Just verify the command completed without raising an exception - - # Verify resource API client was created and configured - mock_create_api_client.assert_called_once() - self.assertTrue(mock_resource_client.verify_https) # Should be True when GATEWAY_SKIP_VERIFY='false' - mock_resource_client.get_service_metadata.assert_called_once() - - # Verify service token client was created - mock_gateway_client_svc.assert_called_once_with(resource_api_client=mock_resource_client, command=self.command) - - # Verify output contains service token messages - output = mock_stdout.getvalue() - self.assertIn('Gateway Service Token: true', output) - self.assertIn('Connection Validated: True', output) - self.assertIn('No authentication configurations found to migrate.', output) - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch.multiple( - 'awx.main.management.commands.import_auth_config_to_gateway', - GitHubMigrator=DEFAULT, - OIDCMigrator=DEFAULT, - SAMLMigrator=DEFAULT, - AzureADMigrator=DEFAULT, - LDAPMigrator=DEFAULT, - RADIUSMigrator=DEFAULT, - TACACSMigrator=DEFAULT, - GoogleOAuth2Migrator=DEFAULT, - SettingsMigrator=DEFAULT, - ) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('sys.stdout', new_callable=StringIO) - def test_skip_flags_prevent_authenticator_individual_and_settings_migration(self, mock_stdout, mock_gateway_client, **mock_migrators): - """Test that skip flags prevent corresponding migrators from being created.""" - - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - with patch.object(self.command, 'stdout', mock_stdout): - with patch('sys.exit'): - self.command.handle(**self.options_basic_auth_skip_all_individual()) - # Should call sys.exit(0) for success, but may not due to test setup - # Just verify the command completed without raising an exception - - # Verify no migrators were created - for mock_migrator in mock_migrators.values(): - mock_migrator.assert_not_called() - - # Verify warning message about no configurations - output = mock_stdout.getvalue() - self.assertIn('No authentication configurations found to migrate.', output) - self.assertIn('Settings migration will not execute.', output) - self.assertIn('NO MIGRATIONS WILL EXECUTE.', output) - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch.multiple( - 'awx.main.management.commands.import_auth_config_to_gateway', - GitHubMigrator=DEFAULT, - OIDCMigrator=DEFAULT, - SAMLMigrator=DEFAULT, - AzureADMigrator=DEFAULT, - LDAPMigrator=DEFAULT, - RADIUSMigrator=DEFAULT, - TACACSMigrator=DEFAULT, - GoogleOAuth2Migrator=DEFAULT, - ) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('sys.stdout', new_callable=StringIO) - def test_skip_flags_prevent_authenticator_migration(self, mock_stdout, mock_gateway_client, **mock_migrators): - """Test that skip flags prevent corresponding migrators from being created.""" - - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - options = self.options_basic_auth_full_send() - options['skip_all_authenticators'] = True - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**options) - # Should exit with code 0 for success (no failures) - assert exc_info.value.code == 0 - - # Verify no migrators were created - for mock_migrator in mock_migrators.values(): - mock_migrator.assert_not_called() - - # Verify warning message about no configurations - output = mock_stdout.getvalue() - self.assertIn('No authentication configurations found to migrate.', output) - self.assertNotIn('Settings migration will not execute.', output) - self.assertNotIn('NO MIGRATIONS WILL EXECUTE.', output) - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('sys.stdout', new_callable=StringIO) - def test_handle_gateway_api_error(self, mock_stdout, mock_gateway_client): - """Test handling of GatewayAPIError exceptions.""" - # Mock gateway client to raise GatewayAPIError - mock_gateway_client.side_effect = GatewayAPIError('Test error message', status_code=400, response_data={'error': 'Bad request'}) - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**self.options_basic_auth_full_send()) - # Should exit with code 1 for errors - assert exc_info.value.code == 1 - - # Verify error message output - output = mock_stdout.getvalue() - self.assertIn('Gateway API Error: Test error message', output) - self.assertIn('Status Code: 400', output) - self.assertIn("Response: {'error': 'Bad request'}", output) - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('sys.stdout', new_callable=StringIO) - def test_handle_unexpected_error(self, mock_stdout, mock_gateway_client): - """Test handling of unexpected exceptions.""" - # Mock gateway client to raise unexpected error - mock_gateway_client.side_effect = ValueError('Unexpected error') - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**self.options_basic_auth_full_send()) - # Should exit with code 1 for errors - assert exc_info.value.code == 1 - - # Verify error message output - output = mock_stdout.getvalue() - self.assertIn('Unexpected error during migration: Unexpected error', output) - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('awx.main.management.commands.import_auth_config_to_gateway.GitHubMigrator') - @patch('awx.main.management.commands.import_auth_config_to_gateway.SettingsMigrator') - @patch('sys.stdout', new_callable=StringIO) - def test_force_flag_passed_to_migrators(self, mock_stdout, mock_github, mock_settings_migrator, mock_gateway_client): - """Test that force flag is properly passed to migrators.""" - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - # Mock migrator - self.create_mock_migrator(mock_github, authenticator_type="GitHub", created=0, mappers_created=2) - self.create_mock_migrator( - mock_settings_migrator, authenticator_type="Settings", settings_created=0, settings_updated=2, settings_unchanged=0, settings_failed=0 - ) - - options = self.options_basic_auth_skip_all_individual() - options['force'] = True - options['skip_github'] = False - options['skip_settings'] = False - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**options) - # Should exit with code 0 for success - assert exc_info.value.code == 0 - - # Verify migrator was created with force=True - mock_github.assert_called_once_with(mock_client_instance, self.command, force=True) - - # Verify settings migrator was created with force=True - mock_settings_migrator.assert_called_once_with(mock_client_instance, self.command, force=True) - - @patch('sys.stdout', new_callable=StringIO) - def test_print_export_summary(self, mock_stdout): - """Test the _print_export_summary method.""" - result = { - 'created': 2, - 'updated': 1, - 'unchanged': 3, - 'failed': 0, - 'mappers_created': 5, - 'mappers_updated': 2, - 'mappers_failed': 1, - } - - with patch.object(self.command, 'stdout', mock_stdout): - self.command._print_export_summary('SAML', result) - - output = mock_stdout.getvalue() - self.assertIn('--- SAML Export Summary ---', output) - self.assertIn('Authenticators created: 2', output) - self.assertIn('Authenticators updated: 1', output) - self.assertIn('Authenticators unchanged: 3', output) - self.assertIn('Authenticators failed: 0', output) - self.assertIn('Mappers created: 5', output) - self.assertIn('Mappers updated: 2', output) - self.assertIn('Mappers failed: 1', output) - - @patch('sys.stdout', new_callable=StringIO) - def test_print_export_summary_settings(self, mock_stdout): - """Test the _print_export_summary method.""" - result = { - 'settings_created': 2, - 'settings_updated': 1, - 'settings_unchanged': 3, - 'settings_failed': 0, - } - - with patch.object(self.command, 'stdout', mock_stdout): - self.command._print_export_summary('Settings', result) - - output = mock_stdout.getvalue() - self.assertIn('--- Settings Export Summary ---', output) - self.assertIn('Settings created: 2', output) - self.assertIn('Settings updated: 1', output) - self.assertIn('Settings unchanged: 3', output) - self.assertIn('Settings failed: 0', output) - - @patch('sys.stdout', new_callable=StringIO) - def test_print_export_summary_missing_keys(self, mock_stdout): - """Test _print_export_summary handles missing keys gracefully.""" - result = { - 'created': 1, - 'updated': 2, - # Missing other keys - } - - with patch.object(self.command, 'stdout', mock_stdout): - self.command._print_export_summary('LDAP', result) - - output = mock_stdout.getvalue() - self.assertIn('--- LDAP Export Summary ---', output) - self.assertIn('Authenticators created: 1', output) - self.assertIn('Authenticators updated: 2', output) - self.assertIn('Authenticators unchanged: 0', output) # Default value - self.assertIn('Mappers created: 0', output) # Default value - - @patch.dict(os.environ, {'GATEWAY_BASE_URL': 'https://gateway.example.com', 'GATEWAY_USER': 'testuser', 'GATEWAY_PASSWORD': 'testpass'}) - @patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') - @patch('awx.main.management.commands.import_auth_config_to_gateway.GitHubMigrator') - @patch('awx.main.management.commands.import_auth_config_to_gateway.OIDCMigrator') - @patch('sys.stdout', new_callable=StringIO) - def test_total_results_accumulation(self, mock_stdout, mock_oidc, mock_github, mock_gateway_client): - """Test that results from multiple migrators are properly accumulated.""" - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - # Mock migrators with different results - self.create_mock_migrator(mock_github, authenticator_type="GitHub", created=1, mappers_created=2) - self.create_mock_migrator(mock_oidc, authenticator_type="OIDC", created=0, updated=1, unchanged=1, mappers_created=1, mappers_updated=1) - - options = self.options_basic_auth_skip_all_individual() - options['skip_oidc'] = False - options['skip_github'] = False - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**options) - # Should exit with code 0 for success - assert exc_info.value.code == 0 - - # Verify total results are accumulated correctly - output = mock_stdout.getvalue() - self.assertIn('Total authenticators created: 1', output) # 1 + 0 - self.assertIn('Total authenticators updated: 1', output) # 0 + 1 - self.assertIn('Total authenticators unchanged: 1', output) # 0 + 1 - self.assertIn('Total authenticators failed: 0', output) # 0 + 0 - self.assertIn('Total mappers created: 3', output) # 2 + 1 - self.assertIn('Total mappers updated: 1', output) # 0 + 1 - self.assertIn('Total mappers failed: 0', output) # 0 + 0 - - @patch('sys.stdout', new_callable=StringIO) - def test_environment_variable_parsing(self, mock_stdout): - """Test that environment variables are parsed correctly.""" - test_cases = [ - ('true', True), - ('1', True), - ('yes', True), - ('on', True), - ('TRUE', True), - ('false', False), - ('0', False), - ('no', False), - ('off', False), - ('', False), - ('random', False), - ] - - for env_value, expected in test_cases: - with patch.dict( - os.environ, - { - 'GATEWAY_BASE_URL': 'https://gateway.example.com', - 'GATEWAY_USER': 'testuser', - 'GATEWAY_PASSWORD': 'testpass', - 'GATEWAY_SKIP_VERIFY': env_value, - }, - ): - with patch('awx.main.management.commands.import_auth_config_to_gateway.GatewayClient') as mock_gateway_client: - # Mock gateway client context manager - mock_client_instance = Mock() - mock_gateway_client.return_value.__enter__.return_value = mock_client_instance - mock_gateway_client.return_value.__exit__.return_value = None - - with patch.object(self.command, 'stdout', mock_stdout): - with patch('sys.exit'): - self.command.handle(**self.options_basic_auth_skip_all_individual()) - - # Verify gateway client was called with correct skip_verify value - mock_gateway_client.assert_called_once_with( - base_url='https://gateway.example.com', username='testuser', password='testpass', skip_verify=expected, command=self.command - ) - - # Reset for next iteration - mock_gateway_client.reset_mock() - mock_stdout.seek(0) - mock_stdout.truncate(0) - - @patch.dict(os.environ, {'GATEWAY_SKIP_VERIFY': 'false'}) - @patch('awx.main.management.commands.import_auth_config_to_gateway.create_api_client') - @patch('awx.main.management.commands.import_auth_config_to_gateway.urlparse') - @patch('awx.main.management.commands.import_auth_config_to_gateway.urlunparse') - @patch('awx.main.management.commands.import_auth_config_to_gateway.SettingsMigrator') - @patch('sys.stdout', new_callable=StringIO) - def test_service_token_connection_validation_failure(self, mock_stdout, mock_settings_migrator, mock_urlunparse, mock_urlparse, mock_create_api_client): - """Test that non-200 response from get_service_metadata causes error exit.""" - # Mock resource API client with failing response - mock_resource_client = Mock() - mock_resource_client.base_url = 'https://gateway.example.com/api/v1' - mock_resource_client.jwt_user_id = 'test-user' - mock_resource_client.jwt_expiration = '2024-12-31' - mock_resource_client.verify_https = True - mock_response = Mock() - mock_response.status_code = 401 # Simulate unauthenticated error - mock_resource_client.get_service_metadata.return_value = mock_response - mock_create_api_client.return_value = mock_resource_client - - # Mock URL parsing (needed for the service token flow) - mock_parsed = Mock() - mock_parsed.scheme = 'https' - mock_parsed.netloc = 'gateway.example.com' - mock_urlparse.return_value = mock_parsed - mock_urlunparse.return_value = 'https://gateway.example.com/' - - with patch.object(self.command, 'stdout', mock_stdout): - with pytest.raises(SystemExit) as exc_info: - self.command.handle(**self.options_svc_token_skip_all()) - # Should exit with code 1 for connection failure - assert exc_info.value.code == 1 - - # Verify error message is displayed - output = mock_stdout.getvalue() - self.assertIn( - 'Gateway Service Token is unable to connect to Gateway via the base URL https://gateway.example.com/. Recieved HTTP response code 401', output - ) - self.assertIn('Connection Validated: False', output) diff --git a/awx/main/tests/unit/test_tasks.py b/awx/main/tests/unit/test_tasks.py index a2c527cb04..4ddbd5e5ce 100644 --- a/awx/main/tests/unit/test_tasks.py +++ b/awx/main/tests/unit/test_tasks.py @@ -871,314 +871,6 @@ class TestJobCredentials(TestJobExecution): assert f.read() == self.EXAMPLE_PRIVATE_KEY assert safe_env['ANSIBLE_NET_PASSWORD'] == HIDDEN_PASSWORD - def test_terraform_cloud_credentials(self, job, private_data_dir, mock_me): - terraform = CredentialType.defaults['terraform']() - hcl_config = ''' - backend "s3" { - bucket = "s3_sample_bucket" - key = "/tf_state/" - region = "us-east-1" - } - ''' - credential = Credential(pk=1, credential_type=terraform, inputs={'configuration': hcl_config}) - credential.inputs['configuration'] = encrypt_field(credential, 'configuration') - job.credentials.add(credential) - - env = {} - safe_env = {} - credential.credential_type.inject_credential(credential, env, safe_env, [], private_data_dir) - - local_path = to_host_path(env['TF_BACKEND_CONFIG_FILE'], private_data_dir) - config = open(local_path, 'r').read() - assert config == hcl_config - - def test_terraform_gcs_backend_credentials(self, job, private_data_dir, mock_me): - terraform = CredentialType.defaults['terraform']() - hcl_config = ''' - backend "gcs" { - bucket = "gce_storage" - } - ''' - gce_backend_credentials = ''' - { - "type": "service_account", - "project_id": "sample", - "private_key_id": "eeeeeeeeeeeeeeeeeeeeeeeeeee", - "private_key": "-----BEGIN PRIVATE KEY-----\naaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n-----END PRIVATE KEY-----\n", - "client_email": "sample@sample.iam.gserviceaccount.com", - "client_id": "0123456789", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cloud-content-robot%40sample.iam.gserviceaccount.com", - } - ''' - credential = Credential(pk=1, credential_type=terraform, inputs={'configuration': hcl_config, 'gce_credentials': gce_backend_credentials}) - credential.inputs['configuration'] = encrypt_field(credential, 'configuration') - credential.inputs['gce_credentials'] = encrypt_field(credential, 'gce_credentials') - job.credentials.add(credential) - - env = {} - safe_env = {} - credential.credential_type.inject_credential(credential, env, safe_env, [], private_data_dir) - - local_path = to_host_path(env['TF_BACKEND_CONFIG_FILE'], private_data_dir) - config = open(local_path, 'r').read() - assert config == hcl_config - - credentials_path = to_host_path(env['GOOGLE_BACKEND_CREDENTIALS'], private_data_dir) - credentials = open(credentials_path, 'r').read() - assert credentials == gce_backend_credentials - - def test_custom_environment_injectors_with_jinja_syntax_error(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'api_token', 'label': 'API Token', 'type': 'string'}]}, - injectors={'env': {'MY_CLOUD_API_TOKEN': '{{api_token.foo()}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'api_token': 'ABC123'}) - - with pytest.raises(jinja2.exceptions.UndefinedError): - credential.credential_type.inject_credential(credential, {}, {}, [], private_data_dir) - - def test_custom_environment_injectors(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'api_token', 'label': 'API Token', 'type': 'string'}]}, - injectors={'env': {'MY_CLOUD_API_TOKEN': '{{api_token}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'api_token': 'ABC123'}) - - env = {} - credential.credential_type.inject_credential(credential, env, {}, [], private_data_dir) - - assert env['MY_CLOUD_API_TOKEN'] == 'ABC123' - - def test_custom_environment_injectors_with_boolean_env_var(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'turbo_button', 'label': 'Turbo Button', 'type': 'boolean'}]}, - injectors={'env': {'TURBO_BUTTON': '{{turbo_button}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'turbo_button': True}) - - env = {} - credential.credential_type.inject_credential(credential, env, {}, [], private_data_dir) - - assert env['TURBO_BUTTON'] == str(True) - - def test_custom_environment_injectors_with_reserved_env_var(self, private_data_dir, job, mock_me): - task = jobs.RunJob() - task.instance = job - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'api_token', 'label': 'API Token', 'type': 'string'}]}, - injectors={'env': {'JOB_ID': 'reserved'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'api_token': 'ABC123'}) - job.credentials.add(credential) - - env = task.build_env(job, private_data_dir) - - assert env['JOB_ID'] == str(job.pk) - - def test_custom_environment_injectors_with_secret_field(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'password', 'label': 'Password', 'type': 'string', 'secret': True}]}, - injectors={'env': {'MY_CLOUD_PRIVATE_VAR': '{{password}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'password': 'SUPER-SECRET-123'}) - credential.inputs['password'] = encrypt_field(credential, 'password') - - env = {} - safe_env = {} - credential.credential_type.inject_credential(credential, env, safe_env, [], private_data_dir) - - assert env['MY_CLOUD_PRIVATE_VAR'] == 'SUPER-SECRET-123' - assert 'SUPER-SECRET-123' not in safe_env.values() - assert safe_env['MY_CLOUD_PRIVATE_VAR'] == HIDDEN_PASSWORD - - def test_custom_environment_injectors_with_extra_vars(self, private_data_dir, job, mock_me): - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'api_token', 'label': 'API Token', 'type': 'string'}]}, - injectors={'extra_vars': {'api_token': '{{api_token}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'api_token': 'ABC123'}) - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - extra_vars = parse_extra_vars(args, private_data_dir) - - assert extra_vars["api_token"] == "ABC123" - assert hasattr(extra_vars["api_token"], '__UNSAFE__') - - def test_custom_environment_injectors_with_boolean_extra_vars(self, job, private_data_dir, mock_me): - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'turbo_button', 'label': 'Turbo Button', 'type': 'boolean'}]}, - injectors={'extra_vars': {'turbo_button': '{{turbo_button}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'turbo_button': True}) - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - extra_vars = parse_extra_vars(args, private_data_dir) - - assert extra_vars["turbo_button"] == "True" - - def test_custom_environment_injectors_with_nested_extra_vars(self, private_data_dir, job, mock_me): - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'host', 'label': 'Host', 'type': 'string'}]}, - injectors={'extra_vars': {'auth': {'host': '{{host}}'}}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'host': 'example.com'}) - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - extra_vars = parse_extra_vars(args, private_data_dir) - - assert extra_vars["auth"]["host"] == "example.com" - - def test_custom_environment_injectors_with_templated_extra_vars_key(self, private_data_dir, job, mock_me): - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'environment', 'label': 'Environment', 'type': 'string'}, {'id': 'host', 'label': 'Host', 'type': 'string'}]}, - injectors={'extra_vars': {'{{environment}}_auth': {'host': '{{host}}'}}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'environment': 'test', 'host': 'example.com'}) - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - extra_vars = parse_extra_vars(args, private_data_dir) - - assert extra_vars["test_auth"]["host"] == "example.com" - - def test_custom_environment_injectors_with_complicated_boolean_template(self, job, private_data_dir, mock_me): - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'turbo_button', 'label': 'Turbo Button', 'type': 'boolean'}]}, - injectors={'extra_vars': {'turbo_button': '{% if turbo_button %}FAST!{% else %}SLOW!{% endif %}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'turbo_button': True}) - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - extra_vars = parse_extra_vars(args, private_data_dir) - - assert extra_vars["turbo_button"] == "FAST!" - - def test_custom_environment_injectors_with_secret_extra_vars(self, job, private_data_dir, mock_me): - """ - extra_vars that contain secret field values should be censored in the DB - """ - task = jobs.RunJob() - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'password', 'label': 'Password', 'type': 'string', 'secret': True}]}, - injectors={'extra_vars': {'password': '{{password}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'password': 'SUPER-SECRET-123'}) - credential.inputs['password'] = encrypt_field(credential, 'password') - job.credentials.add(credential) - - args = task.build_args(job, private_data_dir, {}) - credential.credential_type.inject_credential(credential, {}, {}, args, private_data_dir) - - extra_vars = parse_extra_vars(args, private_data_dir) - assert extra_vars["password"] == "SUPER-SECRET-123" - - def test_custom_environment_injectors_with_file(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'api_token', 'label': 'API Token', 'type': 'string'}]}, - injectors={'file': {'template': '[mycloud]\n{{api_token}}'}, 'env': {'MY_CLOUD_INI_FILE': '{{tower.filename}}'}}, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'api_token': 'ABC123'}) - - env = {} - credential.credential_type.inject_credential(credential, env, {}, [], private_data_dir) - - path = to_host_path(env['MY_CLOUD_INI_FILE'], private_data_dir) - assert open(path, 'r').read() == '[mycloud]\nABC123' - - def test_custom_environment_injectors_with_unicode_content(self, private_data_dir, mock_me): - value = 'Iñtërnâtiônàlizætiøn' - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': []}, - injectors={'file': {'template': value}, 'env': {'MY_CLOUD_INI_FILE': '{{tower.filename}}'}}, - ) - credential = Credential( - pk=1, - credential_type=some_cloud, - ) - - env = {} - credential.credential_type.inject_credential(credential, env, {}, [], private_data_dir) - - path = to_host_path(env['MY_CLOUD_INI_FILE'], private_data_dir) - assert open(path, 'r').read() == value - - def test_custom_environment_injectors_with_files(self, private_data_dir, mock_me): - some_cloud = CredentialType( - kind='cloud', - name='SomeCloud', - managed=False, - inputs={'fields': [{'id': 'cert', 'label': 'Certificate', 'type': 'string'}, {'id': 'key', 'label': 'Key', 'type': 'string'}]}, - injectors={ - 'file': {'template.cert': '[mycert]\n{{cert}}', 'template.key': '[mykey]\n{{key}}'}, - 'env': {'MY_CERT_INI_FILE': '{{tower.filename.cert}}', 'MY_KEY_INI_FILE': '{{tower.filename.key}}'}, - }, - ) - credential = Credential(pk=1, credential_type=some_cloud, inputs={'cert': 'CERT123', 'key': 'KEY123'}) - - env = {} - credential.credential_type.inject_credential(credential, env, {}, [], private_data_dir) - - cert_path = to_host_path(env['MY_CERT_INI_FILE'], private_data_dir) - key_path = to_host_path(env['MY_KEY_INI_FILE'], private_data_dir) - assert open(cert_path, 'r').read() == '[mycert]\nCERT123' - assert open(key_path, 'r').read() == '[mykey]\nKEY123' - def test_multi_cloud(self, private_data_dir, mock_me): gce = CredentialType.defaults['gce']() gce_credential = Credential(pk=1, credential_type=gce, inputs={'username': 'bob', 'project': 'some-project', 'ssh_key_data': self.EXAMPLE_PRIVATE_KEY}) diff --git a/awx/main/tests/unit/utils/test_auth_migration.py b/awx/main/tests/unit/utils/test_auth_migration.py deleted file mode 100644 index e00bdb839b..0000000000 --- a/awx/main/tests/unit/utils/test_auth_migration.py +++ /dev/null @@ -1,1137 +0,0 @@ -""" -Unit tests for auth migration utilities. -""" - -import pytest -import re -from awx.main.utils.gateway_mapping import ( - org_map_to_gateway_format, - team_map_to_gateway_format, - role_map_to_gateway_format, - process_sso_user_list, - process_ldap_user_list, -) - - -def get_org_mappers(org_map, start_order=1, auth_type='sso'): - """Helper function to get just the mappers from org_map_to_gateway_format.""" - result, _ = org_map_to_gateway_format(org_map, start_order, auth_type=auth_type) - return result - - -def get_team_mappers(team_map, start_order=1, auth_type='sso'): - """Helper function to get just the mappers from team_map_to_gateway_format.""" - result, _ = team_map_to_gateway_format(team_map, start_order, auth_type=auth_type) - return result - - -def get_role_mappers(role_map, start_order=1): - """Helper function to get just the mappers from role_map_to_gateway_format.""" - result, _ = role_map_to_gateway_format(role_map, start_order) - return result - - -class TestProcessSSOUserList: - """Tests for the process_sso_user_list function (consolidated version).""" - - def test_false_boolean(self): - """Test that False creates 'Never Allow' trigger.""" - result = process_sso_user_list(False) - - assert result["name"] == "Never Allow" - assert result["trigger"] == {"never": {}} - - def test_true_boolean(self): - """Test that True creates 'Always Allow' trigger.""" - result = process_sso_user_list(True) - - assert result["name"] == "Always Allow" - assert result["trigger"] == {"always": {}} - - def test_false_string_list(self): - """Test that ['false'] creates 'Never Allow' trigger.""" - result = process_sso_user_list(["false"]) - - assert result["name"] == "Never Allow" - assert result["trigger"] == {"never": {}} - - def test_true_string_list(self): - """Test that ['true'] creates 'Always Allow' trigger.""" - result = process_sso_user_list(["true"]) - - assert result["name"] == "Always Allow" - assert result["trigger"] == {"always": {}} - - def test_string_user_list(self): - """Test that regular string users are processed correctly.""" - result = process_sso_user_list(["testuser"]) - - assert result["name"] == "U:1" - assert result["trigger"]["attributes"]["username"]["equals"] == "testuser" - - def test_email_user_list(self): - """Test that email addresses are processed correctly.""" - result = process_sso_user_list(["test@example.com"]) - - assert result["name"] == "E:1" - assert result["trigger"]["attributes"]["email"]["equals"] == "test@example.com" - - def test_mixed_string_list(self): - """Test that mixed list with 'true', 'false', and regular users works correctly.""" - result = process_sso_user_list(["true", "testuser", "false"]) - - # Should consolidate all usernames and show count - assert result["name"] == "U:3" - assert result["trigger"]["attributes"]["username"]["in"] == ["true", "testuser", "false"] - - def test_custom_email_username_attrs(self): - """Test that custom email and username attributes work correctly.""" - result = process_sso_user_list(["test@example.com"], email_attr='custom_email', username_attr='custom_username') - - assert result["trigger"]["attributes"]["custom_email"]["equals"] == "test@example.com" - - def test_regex_pattern(self): - """Test that regex patterns create both username and email matches.""" - pattern = re.compile(r"^admin.*@example\.com$") - result = process_sso_user_list([pattern]) - - assert result["name"] == "UP:1 EP:1" - assert result["trigger"]["attributes"]["username"]["matches"] == "/^admin.*@example\\.com$/" - assert result["trigger"]["attributes"]["email"]["matches"] == "/^admin.*@example\\.com$/" - - def test_multiple_emails(self): - """Test that multiple emails use count-based names.""" - emails = [f"user{i}@example.com" for i in range(10)] - result = process_sso_user_list(emails) - - assert result["name"] == "E:10" - assert result["trigger"]["attributes"]["email"]["in"] == emails - - def test_multiple_usernames(self): - """Test that multiple usernames use count-based names.""" - usernames = [f"user{i}" for i in range(8)] - result = process_sso_user_list(usernames) - - assert result["name"] == "U:8" - assert result["trigger"]["attributes"]["username"]["in"] == usernames - - def test_mixed_emails_and_usernames(self): - """Test mixed emails and usernames use count-based names.""" - emails = ["user1@example.com", "user2@example.com"] - usernames = ["admin1", "admin2", "admin3"] - users = emails + usernames - result = process_sso_user_list(users) - - assert result["name"] == "E:2 U:3" - assert result["trigger"]["attributes"]["email"]["in"] == emails - assert result["trigger"]["attributes"]["username"]["in"] == usernames - - def test_multiple_regex_patterns(self): - """Test that multiple regex patterns use count-based names.""" - patterns = [re.compile(f"pattern{i}") for i in range(5)] - result = process_sso_user_list(patterns) - - assert result["name"] == "UP:5 EP:5" - - def test_empty_list(self): - """Test that empty list creates default trigger.""" - result = process_sso_user_list([]) - assert result["name"] == "Mixed Rules" - assert result["trigger"]["attributes"]["join_condition"] == "or" - - -class TestProcessLdapUserList: - """Tests for the process_ldap_user_list function.""" - - def test_none_input(self): - """Test that None creates no triggers (empty list).""" - result = process_ldap_user_list(None) - assert len(result) == 0 - - def test_none_in_list(self): - """Test that [None] creates no triggers (empty list).""" - result = process_ldap_user_list([None]) - assert len(result) == 0 - - def test_true_boolean(self): - """Test that True creates 'Always Allow' trigger.""" - result = process_ldap_user_list(True) - assert len(result) == 1 - assert result[0]["name"] == "Always Allow" - assert result[0]["trigger"] == {"always": {}} - - def test_true_boolean_in_list(self): - """Test that [True] creates 'Always Allow' trigger.""" - result = process_ldap_user_list([True]) - assert len(result) == 1 - assert result[0]["name"] == "Always Allow" - assert result[0]["trigger"] == {"always": {}} - - def test_false_boolean(self): - """Test that False creates 'Never Allow' trigger.""" - result = process_ldap_user_list(False) - assert len(result) == 1 - assert result[0]["name"] == "Never Allow" - assert result[0]["trigger"] == {"never": {}} - - def test_false_boolean_in_list(self): - """Test that [False] creates 'Never Allow' trigger.""" - result = process_ldap_user_list([False]) - assert len(result) == 1 - assert result[0]["name"] == "Never Allow" - assert result[0]["trigger"] == {"never": {}} - - def test_single_string_group(self): - """Test that a single string creates group match trigger.""" - result = process_ldap_user_list("admin_group") - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == ["admin_group"] - - def test_single_string_group_in_list(self): - """Test that a single string in list creates group match trigger.""" - result = process_ldap_user_list(["admin_group"]) - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == ["admin_group"] - - def test_multiple_groups(self): - """Test that multiple groups create single trigger with all groups.""" - result = process_ldap_user_list(["group1", "group2", "group3"]) - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == ["group1", "group2", "group3"] - - def test_mixed_types_with_none(self): - """Test that mixed types including None are handled correctly.""" - result = process_ldap_user_list(["group1", None, "group2"]) - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == ["group1", None, "group2"] - - def test_mixed_types_with_boolean_string(self): - """Test that boolean values mixed with strings are handled correctly.""" - result = process_ldap_user_list(["group1", False, "group2"]) - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == ["group1", False, "group2"] - - def test_empty_list(self): - """Test that empty list creates no triggers.""" - result = process_ldap_user_list([]) - assert len(result) == 0 - - def test_numeric_values(self): - """Test that numeric values are handled correctly.""" - result = process_ldap_user_list([123, "group1"]) - assert len(result) == 1 - assert result[0]["name"] == "Match User Groups" - assert result[0]["trigger"]["groups"]["has_or"] == [123, "group1"] - - -class TestOrgMapToGatewayFormat: - - def test_none_input(self): - """Test that None input returns empty list.""" - result, next_order = org_map_to_gateway_format(None) - assert result == [] - assert next_order == 1 # Default start_order - - def test_empty_dict(self): - """Test that empty dict returns empty list.""" - result, next_order = org_map_to_gateway_format({}) - assert result == [] - assert next_order == 1 - - def test_order_increments_correctly(self): - """Test that order values increment correctly.""" - org_map = {"myorg": {"admins": True, "users": True}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 2 - assert result[0]["order"] == 1 - assert result[1]["order"] == 2 - - def test_org_with_admin_true(self): - """Test organization with admin access set to True.""" - org_map = {"myorg": {"admins": True}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Admins Always Allow" - assert mapping["map_type"] == "organization" - assert mapping["organization"] == "myorg" - assert mapping["team"] is None - assert mapping["role"] == "Organization Admin" - assert mapping["revoke"] is False - assert mapping["order"] == 1 - assert mapping["triggers"] == {"always": {}} - - def test_org_with_admin_false(self): - """Test organization with admin access set to False.""" - org_map = {"myorg": {"admins": False}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Admins Never Allow" - assert mapping["triggers"] == {"never": {}} - assert mapping["role"] == "Organization Admin" - - def test_org_with_admin_false_string(self): - """Test organization with admin access set to ['false'].""" - org_map = {"myorg": {"admins": ["false"]}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Admins Never Allow" - assert mapping["triggers"] == {"never": {}} - assert mapping["role"] == "Organization Admin" - - def test_org_with_users_true_string(self): - """Test organization with users access set to ['true'].""" - org_map = {"myorg": {"users": ["true"]}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Users Always Allow" - assert mapping["triggers"] == {"always": {}} - assert mapping["role"] == "Organization Member" - - def test_org_with_users_true(self): - """Test organization with users access set to True.""" - org_map = {"myorg": {"users": True}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Users Always Allow" - assert mapping["triggers"] == {"always": {}} - assert mapping["role"] == "Organization Member" - - def test_org_with_admin_string(self): - """Test organization with admin access set to a specific group.""" - org_map = {"myorg": {"admins": "admin-username"}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Admins U:1" - assert mapping["triggers"] == {"attributes": {"join_condition": "or", "username": {"equals": "admin-username"}}} - assert mapping["role"] == "Organization Admin" - - def test_org_with_admin_list(self): - """Test organization with admin access set to multiple groups.""" - org_map = {"myorg": {"admins": ["admin-username1", "admin-username2"]}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Admins U:2" - assert mapping["triggers"]["attributes"]["username"]["in"] == ["admin-username1", "admin-username2"] - assert mapping["order"] == 1 - - def test_org_with_email_detection(self): - """Test that email addresses are correctly identified and handled.""" - org_map = {"myorg": {"users": ["user@example.com", "admin@test.org", "not-an-email"]}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - mapping = result[0] - - # Should consolidate emails and usernames in one mapper - assert mapping["name"] == "myorg - Users E:2 U:1" - - # Should have both email and username attributes - assert mapping["triggers"]["attributes"]["email"]["in"] == ["user@example.com", "admin@test.org"] - assert mapping["triggers"]["attributes"]["username"]["equals"] == "not-an-email" - assert mapping["triggers"]["attributes"]["join_condition"] == "or" - - def test_org_with_remove_flags(self): - """Test organization with remove flags.""" - org_map = {"myorg": {"admins": True, "users": ["user-group"], "remove_admins": True, "remove_users": True}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 2 - assert result[0]["revoke"] is True # admin mapping should have revoke=True - assert result[1]["revoke"] is True # user mapping should have revoke=True - - def test_org_with_custom_email_username_attrs(self): - """Test org mapping with custom email and username attributes.""" - org_map = {"myorg": {"admins": ["test@example.com"]}} - - result, _ = org_map_to_gateway_format(org_map, email_attr='custom_email', username_attr='custom_username') - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"]["attributes"]["custom_email"]["equals"] == "test@example.com" - - def test_org_with_regex_pattern_objects(self): - """Test org mapping with actual re.Pattern objects.""" - regex_str = "^admin.*@example\\.com$" - - org_map = {"myorg": {"users": [re.compile(regex_str)]}} - - result, _ = org_map_to_gateway_format(org_map) - - # Should create 1 consolidated mapping with both username and email matches - assert len(result) == 1, f"Expected 1 item but got: {result}" - - mapping = result[0] - assert mapping["name"] == "myorg - Users UP:1 EP:1" - assert mapping["triggers"]["attributes"]["username"]["matches"] == f"/{regex_str}/" - assert mapping["triggers"]["attributes"]["email"]["matches"] == f"/{regex_str}/" - - def test_org_with_none_values_skipped(self): - """Test that entries with None values are skipped.""" - org_map = {"myorg": {"admins": None, "users": True}} - - result, _ = org_map_to_gateway_format(org_map) - - assert len(result) == 1 - assert result[0]["role"] == "Organization Member" # Only users mapping should be present - - def test_org_with_start_order_parameter(self): - """Test that start_order parameter works correctly.""" - org_map = {"org1": {"admins": True}, "org2": {"users": ["username1", "username2"]}} - - result, next_order = org_map_to_gateway_format(org_map, start_order=10) - - # Should have 2 mappings total (1 for org1, 1 for org2) - assert len(result) == 2 - assert result[0]["order"] == 10 - assert result[1]["order"] == 11 - assert next_order == 12 - - def test_org_comprehensive_field_validation(self): - """Test comprehensive validation of all fields in org mappings.""" - org_map = {"test-org": {"admins": ["test-admin"], "remove_admins": False}} - - result, next_order = org_map_to_gateway_format(org_map, start_order=5) - - assert len(result) == 1 - mapping = result[0] - - # Validate all required fields and their types - assert isinstance(mapping["name"], str) - assert mapping["name"] == "test-org - Admins U:1" - - assert mapping["map_type"] == "organization" - assert mapping["order"] == 5 - assert mapping["authenticator"] == -1 - - assert isinstance(mapping["triggers"], dict) - assert "attributes" in mapping["triggers"] - - assert mapping["organization"] == "test-org" - assert mapping["team"] is None - assert mapping["role"] == "Organization Admin" - assert mapping["revoke"] is False - - # Validate next_order is incremented correctly - assert next_order == 6 - - def test_org_next_order_calculation(self): - """Test that next_order is calculated correctly in various scenarios.""" - # Test with no orgs - result, next_order = org_map_to_gateway_format({}) - assert next_order == 1 - - # Test with orgs that have no admins/users (should be skipped) - org_map = {"skipped": {"admins": None, "users": None}} - result, next_order = org_map_to_gateway_format(org_map) - assert len(result) == 0 - assert next_order == 1 - - # Test with single org - org_map = {"single": {"admins": True}} - result, next_order = org_map_to_gateway_format(org_map) - assert len(result) == 1 - assert next_order == 2 - - # Test with multiple mappings from single org - now consolidated into one - org_map = {"multi": {"users": ["user1", "user2"]}} - result, next_order = org_map_to_gateway_format(org_map) - assert len(result) == 1 - assert next_order == 2 - - def test_org_with_auth_type_sso(self): - """Test org mapping with auth_type='sso' (default behavior).""" - org_map = {"myorg": {"users": ["testuser"]}} - - result, _ = org_map_to_gateway_format(org_map, auth_type='sso') - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - Users U:1" - assert mapping["triggers"]["attributes"]["username"]["equals"] == "testuser" - - def test_org_with_auth_type_ldap(self): - """Test org mapping with auth_type='ldap'.""" - org_map = {"myorg": {"users": ["admin_group"]}} - - result, _ = org_map_to_gateway_format(org_map, auth_type='ldap') - - assert len(result) == 1 - mapping = result[0] - assert "Match User Groups" in mapping["name"] - assert mapping["triggers"]["groups"]["has_or"] == ["admin_group"] - - def test_org_with_auth_type_ldap_boolean(self): - """Test org mapping with auth_type='ldap' and boolean values.""" - org_map = {"myorg": {"users": True, "admins": False}} - - result, _ = org_map_to_gateway_format(org_map, auth_type='ldap') - - assert len(result) == 2 - user_mapping = next(m for m in result if "Users" in m["name"]) - admin_mapping = next(m for m in result if "Admins" in m["name"]) - - assert "Always Allow" in user_mapping["name"] - assert user_mapping["triggers"]["always"] == {} - - assert "Never Allow" in admin_mapping["name"] - assert admin_mapping["triggers"]["never"] == {} - - -class TestTeamMapToGatewayFormat: - """Tests for team_map_to_gateway_format function.""" - - def test_none_input(self): - """Test that None input returns empty list.""" - result, next_order = team_map_to_gateway_format(None) - assert result == [] - assert next_order == 1 # Default start_order - - def test_empty_dict(self): - """Test that empty dict returns empty list.""" - result, next_order = team_map_to_gateway_format({}) - assert result == [] - assert next_order == 1 - - def test_order_increments_correctly(self): - """Test that order values increment correctly for teams.""" - team_map = {"team1": {"organization": "myorg", "users": True}, "team2": {"organization": "myorg", "users": True}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 2 - assert result[0]["order"] == 1 - assert result[1]["order"] == 2 - - def test_team_with_email_detection(self): - """Test that email addresses are correctly identified and handled.""" - team_map = {"email-team": {"organization": "myorg", "users": ["user@example.com", "admin@test.org", "not-an-email"]}} - - result, _ = team_map_to_gateway_format(team_map) - - # Should have 1 consolidated mapping - assert len(result) == 1 - mapping = result[0] - - # Should consolidate emails and usernames in one mapper - assert mapping["name"] == "myorg - email-team E:2 U:1" - - # Should have both email and username attributes - assert mapping["triggers"]["attributes"]["email"]["in"] == ["user@example.com", "admin@test.org"] - assert mapping["triggers"]["attributes"]["username"]["equals"] == "not-an-email" - assert mapping["triggers"]["attributes"]["join_condition"] == "or" - - def test_team_with_custom_email_username_attrs(self): - """Test team mapping with custom email and username attributes.""" - team_map = {"custom-team": {"organization": "myorg", "users": ["test@example.com"]}} - - result, _ = team_map_to_gateway_format(team_map, email_attr='custom_email', username_attr='custom_username') - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"]["attributes"]["custom_email"]["equals"] == "test@example.com" - assert mapping["name"] == "myorg - custom-team E:1" - - def test_team_with_regex_pattern_objects(self): - """Test team mapping with actual re.Pattern objects.""" - regex_str = "^admin.*@example\\.com$" - - team_map = {"regex-team": {"organization": "myorg", "users": [re.compile(regex_str)]}} - - result, _ = team_map_to_gateway_format(team_map) - - # Should create 1 consolidated mapping with both username and email matches - assert len(result) == 1, f"Expected 1 item but got: {result}" - - mapping = result[0] - assert mapping["name"] == "myorg - regex-team UP:1 EP:1" - assert mapping["triggers"]["attributes"]["username"]["matches"] == f"/{regex_str}/" - assert mapping["triggers"]["attributes"]["email"]["matches"] == f"/{regex_str}/" - - def test_team_with_non_string_objects(self): - """Test team mapping with non-string objects that get converted.""" - - class CustomObject: - def __str__(self): - return "custom_object_string" - - custom_obj = CustomObject() - team_map = {"object-team": {"organization": "myorg", "users": [custom_obj, 12345]}} - - result, _ = team_map_to_gateway_format(team_map) - - # Should create 1 consolidated mapping with both username and email attributes - assert len(result) == 1 - - mapping = result[0] - # Both objects should be treated as usernames and emails - assert mapping["triggers"]["attributes"]["username"]["in"] == ["custom_object_string", "12345"] - assert mapping["triggers"]["attributes"]["email"]["in"] == ["custom_object_string", "12345"] - - def test_team_with_mixed_data_types(self): - """Test team mapping with mixed data types in users list.""" - regex_str = 'test.*' - - team_map = {"mixed-team": {"organization": "myorg", "users": ["string_user", "email@test.com", re.compile(regex_str), 999, True]}} - - result, _ = team_map_to_gateway_format(team_map) - - # Should create 1 consolidated mapping with all types handled - assert len(result) == 1 - - mapping = result[0] - # All types should be consolidated into one mapper name - assert mapping["name"] == "myorg - mixed-team E:3 U:3 UP:1 EP:1" - - # Verify trigger structure contains all the data types - triggers = mapping["triggers"]["attributes"] - assert "email" in triggers - assert "username" in triggers - - def test_team_with_start_order_parameter(self): - """Test that start_order parameter works correctly.""" - team_map = {"team1": {"organization": "org1", "users": True}, "team2": {"organization": "org2", "users": ["username1", "username2"]}} - - result, next_order = team_map_to_gateway_format(team_map, start_order=10) - - # First mapping should start at order 10 - assert result[0]["order"] == 10 - # Should increment properly - orders = [mapping["order"] for mapping in result] - assert orders == sorted(orders) # Should be in ascending order - assert min(orders) == 10 - # next_order should be one more than the last used order - assert next_order == max(orders) + 1 - - def test_team_with_empty_strings(self): - """Test team mapping with empty strings.""" - team_map = { - "": {"organization": "myorg", "users": [""]}, # Empty team name and user - "normal-team": {"organization": "", "users": True}, # Empty organization - } - - result, _ = team_map_to_gateway_format(team_map) - - # Should handle empty strings gracefully - assert len(result) == 2 - - # Check empty team name mapping - empty_team_mapping = [m for m in result if m["team"] == ""][0] - assert " - " in empty_team_mapping["name"] and "U:1" in empty_team_mapping["name"] - assert empty_team_mapping["team"] == "" - - # Check empty organization mapping - empty_org_mapping = [m for m in result if m["organization"] == ""][0] - assert empty_org_mapping["organization"] == "" - assert "Always Allow" in empty_org_mapping["name"] - - def test_team_with_special_characters(self): - """Test team mapping with special characters in names.""" - team_map = { - "team-with-special!@#$%^&*()_+chars": {"organization": "org with spaces & symbols!", "users": ["user@domain.com", "user-with-special!chars"]} - } - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - - # Verify special characters are preserved in names - mapping = result[0] - assert "team-with-special!@#$%^&*()_+chars" in mapping["name"] - assert "org with spaces & symbols!" in mapping["name"] - assert mapping["team"] == "team-with-special!@#$%^&*()_+chars" - assert mapping["organization"] == "org with spaces & symbols!" - - def test_team_with_unicode_characters(self): - """Test team mapping with unicode characters.""" - team_map = { - "チーム": { # Japanese for "team" - "organization": "組織", # Japanese for "organization" - "users": ["ユーザー@example.com", "用户"], # Mixed Japanese/Chinese - } - } - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - - # Verify unicode characters are handled correctly - mapping = result[0] - assert "チーム" in mapping["name"] - assert "組織" in mapping["name"] - assert mapping["team"] == "チーム" - assert mapping["organization"] == "組織" - - def test_team_next_order_calculation(self): - """Test that next_order is calculated correctly in various scenarios.""" - # Test with no teams - result, next_order = team_map_to_gateway_format({}) - assert next_order == 1 - - # Test with teams that have no users (should be skipped) - team_map = {"skipped": {"organization": "org", "users": None}} - result, next_order = team_map_to_gateway_format(team_map) - assert len(result) == 0 - assert next_order == 1 - - # Test with single team - team_map = {"single": {"organization": "org", "users": True}} - result, next_order = team_map_to_gateway_format(team_map) - assert len(result) == 1 - assert next_order == 2 - - # Test with multiple mappings from single team - now consolidated into one - team_map = {"multi": {"organization": "org", "users": ["user1", "user2"]}} - result, next_order = team_map_to_gateway_format(team_map) - assert len(result) == 1 - assert next_order == 2 - - def test_team_large_dataset_performance(self): - """Test team mapping with a large number of teams and users.""" - # Create a large team map - team_map = {} - for i in range(100): - team_map[f"team_{i}"] = { - "organization": f"org_{i % 10}", # 10 different orgs - "users": [f"user_{j}@org_{i % 10}.com" for j in range(5)], # 5 users per team - } - - result, next_order = team_map_to_gateway_format(team_map) - - # Should create 100 mappings (1 per team, with consolidated users) - assert len(result) == 100 - - # Verify orders are sequential - orders = [mapping["order"] for mapping in result] - assert orders == list(range(1, 101)) - assert next_order == 101 - - # Verify all teams are represented - teams = {mapping["team"] for mapping in result} - assert len(teams) == 100 - - def test_team_mapping_field_validation(self): - """Test that all required fields are present and have correct types.""" - team_map = {"validation-team": {"organization": "test-org", "users": ["test@example.com"], "remove": True}} - - result, _ = team_map_to_gateway_format(team_map) - - for mapping in result: - # Check required fields exist - required_fields = ["name", "map_type", "order", "authenticator", "triggers", "organization", "team", "role", "revoke"] - for field in required_fields: - assert field in mapping, f"Missing required field: {field}" - - # Check field types - assert isinstance(mapping["name"], str) - assert isinstance(mapping["map_type"], str) - assert isinstance(mapping["order"], int) - assert isinstance(mapping["authenticator"], int) - assert isinstance(mapping["triggers"], dict) - assert isinstance(mapping["organization"], str) - assert isinstance(mapping["team"], str) - assert isinstance(mapping["role"], str) - assert isinstance(mapping["revoke"], bool) - - # Check specific values - assert mapping["map_type"] == "team" - assert mapping["authenticator"] == -1 - assert mapping["role"] == "Team Member" - assert mapping["revoke"] == True # Because remove was set to True - - def test_team_trigger_structure_validation(self): - """Test that trigger structures are correctly formatted.""" - team_map = {"trigger-test": {"organization": "org", "users": ["test@example.com", "username"]}} - - result, _ = team_map_to_gateway_format(team_map) - - for mapping in result: - triggers = mapping["triggers"] - - if "always" in triggers: - assert triggers["always"] == {} - elif "never" in triggers: - assert triggers["never"] == {} - elif "attributes" in triggers: - attrs = triggers["attributes"] - assert "join_condition" in attrs - assert attrs["join_condition"] == "or" # Implementation uses 'or' - - # Should have either username or email attribute - assert ("username" in attrs) or ("email" in attrs) - - # The attribute should have either "equals", "matches", or "has_or" - for attr_name in ["username", "email"]: - if attr_name in attrs: - attr_value = attrs[attr_name] - assert ("equals" in attr_value) or ("matches" in attr_value) or ("has_or" in attr_value) - - def test_team_boolean_false_trigger(self): - """Test that False users value creates never trigger correctly.""" - team_map = {"never-team": {"organization": "org", "users": False}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"] == {"never": {}} - assert "Never Allow" in mapping["name"] - - def test_team_boolean_true_trigger(self): - """Test that True users value creates always trigger correctly.""" - team_map = {"always-team": {"organization": "org", "users": True}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"] == {"always": {}} - assert "Always Allow" in mapping["name"] - - def test_team_string_false_trigger(self): - """Test that ['false'] users value creates never trigger correctly.""" - team_map = {"never-team": {"organization": "org", "users": ["false"]}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"] == {"never": {}} - assert "Never Allow" in mapping["name"] - - def test_team_string_true_trigger(self): - """Test that ['true'] users value creates always trigger correctly.""" - team_map = {"always-team": {"organization": "org", "users": ["true"]}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - mapping = result[0] - assert mapping["triggers"] == {"always": {}} - assert "Always Allow" in mapping["name"] - - def test_team_with_join_condition_or(self): - """Test that all attribute-based triggers use 'or' join condition.""" - team_map = {"test-team": {"organization": "org", "users": ["user1", "user2"]}} - - result, _ = team_map_to_gateway_format(team_map) - - for mapping in result: - if "attributes" in mapping["triggers"]: - assert mapping["triggers"]["attributes"]["join_condition"] == "or" - - def test_team_with_default_organization_fallback(self): - """Test that teams without organization get 'Unknown' as default.""" - team_map = {"orphan-team": {"users": ["user1"]}} - - result, _ = team_map_to_gateway_format(team_map) - - assert len(result) == 1 - assert result[0]["organization"] == "Unknown" - assert "Unknown - orphan-team" in result[0]["name"] - - def test_team_with_regex_string_patterns(self): - """Test team mapping with regex patterns as strings (not compiled patterns).""" - team_map = {"regex-team": {"organization": "myorg", "users": ["/^admin.*@example\\.com$/"]}} - - result, _ = team_map_to_gateway_format(team_map) - - # String patterns should be treated as regular strings, not regex - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "myorg - regex-team U:1" - assert mapping["triggers"]["attributes"]["username"]["equals"] == "/^admin.*@example\\.com$/" - - def test_team_comprehensive_field_validation(self): - """Test comprehensive validation of all fields in team mappings.""" - team_map = {"comprehensive-team": {"organization": "test-org", "users": ["test-user"], "remove": False}} - - result, next_order = team_map_to_gateway_format(team_map, start_order=5) - - assert len(result) == 1 - mapping = result[0] - - # Validate all required fields and their types - assert isinstance(mapping["name"], str) - assert mapping["name"] == "test-org - comprehensive-team U:1" - - assert mapping["map_type"] == "team" - assert mapping["order"] == 5 - assert mapping["authenticator"] == -1 - - assert isinstance(mapping["triggers"], dict) - assert "attributes" in mapping["triggers"] - - assert mapping["organization"] == "test-org" - assert mapping["team"] == "comprehensive-team" - assert mapping["role"] == "Team Member" - assert mapping["revoke"] == False - - # Validate next_order is incremented correctly - assert next_order == 6 - - def test_team_with_none_and_remove_flag(self): - """Test that teams with None users are skipped even with remove flag.""" - team_map = { - "skipped-team": {"organization": "org", "users": None, "remove": True}, - "valid-team": {"organization": "org", "users": True, "remove": True}, - } - - result, _ = team_map_to_gateway_format(team_map) - - # Should only have one result (the valid team) - assert len(result) == 1 - assert result[0]["team"] == "valid-team" - assert result[0]["revoke"] == True - - def test_team_error_handling_edge_cases(self): - """Test various edge cases for error handling.""" - # Test with completely empty team config - team_map = {"empty-team": {}} - - try: - _, _ = team_map_to_gateway_format(team_map) - # Should not crash, but might skip the team due to missing 'users' key - except KeyError: - # This is expected if 'users' key is required - pass - - def test_team_ordering_with_mixed_types(self): - """Test that ordering works correctly with mixed user types.""" - team_map = { - "team1": {"organization": "org1", "users": True}, # 1 mapping - "team2": {"organization": "org2", "users": ["user1", "user2"]}, # 1 mapping (consolidated) - "team3": {"organization": "org3", "users": False}, # 1 mapping - } - - result, next_order = team_map_to_gateway_format(team_map, start_order=10) - - # Should have 3 total mappings (consolidated behavior) - assert len(result) == 3 - - # Orders should be sequential starting from 10 - orders = [mapping["order"] for mapping in result] - assert orders == [10, 11, 12] - assert next_order == 13 - - # Verify teams are represented correctly - teams = [mapping["team"] for mapping in result] - assert "team1" in teams - assert "team2" in teams - assert "team3" in teams - assert teams.count("team2") == 1 # team2 should appear once (consolidated) - - def test_team_with_auth_type_sso(self): - """Test team mapping with auth_type='sso' (default behavior).""" - team_map = {"testteam": {"organization": "testorg", "users": ["testuser"]}} - - result, _ = team_map_to_gateway_format(team_map, auth_type='sso') - - assert len(result) == 1 - mapping = result[0] - assert mapping["name"] == "testorg - testteam U:1" - assert mapping["triggers"]["attributes"]["username"]["equals"] == "testuser" - - def test_team_with_auth_type_ldap(self): - """Test team mapping with auth_type='ldap'.""" - team_map = {"testteam": {"organization": "testorg", "users": ["admin_group"]}} - - result, _ = team_map_to_gateway_format(team_map, auth_type='ldap') - - assert len(result) == 1 - mapping = result[0] - assert "Match User Groups" in mapping["name"] - assert mapping["triggers"]["groups"]["has_or"] == ["admin_group"] - - def test_team_with_auth_type_ldap_boolean(self): - """Test team mapping with auth_type='ldap' and boolean values.""" - team_map_true = {"testteam": {"organization": "testorg", "users": True}} - team_map_false = {"testteam": {"organization": "testorg", "users": False}} - - result_true, _ = team_map_to_gateway_format(team_map_true, auth_type='ldap') - result_false, _ = team_map_to_gateway_format(team_map_false, auth_type='ldap') - - assert len(result_true) == 1 - assert "Always Allow" in result_true[0]["name"] - assert result_true[0]["triggers"]["always"] == {} - - assert len(result_false) == 1 - assert "Never Allow" in result_false[0]["name"] - assert result_false[0]["triggers"]["never"] == {} - - -# Parametrized tests for edge cases -@pytest.mark.parametrize( - "org_map,expected_length", - [ - (None, 0), - ({}, 0), - ({"org1": {}}, 0), # Organization with no admin/user mappings - ({"org1": {"admins": True}}, 1), - ({"org1": {"users": True}}, 1), - ({"org1": {"admins": True, "users": True}}, 2), - ({"org1": {"admins": True}, "org2": {"users": True}}, 2), - ], -) -def test_org_map_result_lengths(org_map, expected_length): - """Test that org_map_to_gateway_format returns expected number of mappings.""" - result, _ = org_map_to_gateway_format(org_map) - assert len(result) == expected_length - - -# Test for Gateway format compliance -@pytest.mark.parametrize( - "org_map", - [ - {"org1": {"admins": True}}, - {"org1": {"users": ["username1"]}}, - {"org1": {"admins": False}}, - ], -) -def test_gateway_format_compliance(org_map): - """Test that all results comply with Gateway mapping format.""" - result, _ = org_map_to_gateway_format(org_map) - - for mapping in result: - # Required fields per Gateway spec - assert "name" in mapping - assert "authenticator" in mapping - assert "map_type" in mapping - assert "organization" in mapping - assert "team" in mapping - assert "triggers" in mapping - assert "role" in mapping - assert "revoke" in mapping - assert "order" in mapping - - # Field types - assert isinstance(mapping["name"], str) - assert isinstance(mapping["authenticator"], int) - assert mapping["map_type"] == "organization" # For org mappings - assert isinstance(mapping["organization"], str) - assert mapping["team"] is None # For org mappings, team should be None - assert isinstance(mapping["triggers"], dict) - assert isinstance(mapping["role"], str) - assert isinstance(mapping["revoke"], bool) - assert isinstance(mapping["order"], int) - - -# Parametrized tests for team mappings -@pytest.mark.parametrize( - "team_map,expected_length", - [ - (None, 0), - ({}, 0), - ({"team1": {"organization": "org1", "users": None}}, 0), # Team with None users should be skipped - ({"team1": {"organization": "org1", "users": True}}, 1), - ({"team1": {"organization": "org1", "users": ["username1"]}}, 1), - ({"team1": {"organization": "org1", "users": True}, "team2": {"organization": "org2", "users": False}}, 2), - ], -) -def test_team_map_result_lengths(team_map, expected_length): - """Test that team_map_to_gateway_format returns expected number of mappings.""" - result, _ = team_map_to_gateway_format(team_map) - assert len(result) == expected_length - - -# Test for Gateway format compliance for teams -@pytest.mark.parametrize( - "team_map", - [ - {"team1": {"organization": "org1", "users": True}}, - {"team1": {"organization": "org1", "users": ["username1"]}}, - {"team1": {"organization": "org1", "users": False}}, - ], -) -def test_team_gateway_format_compliance(team_map): - """Test that all team results comply with Gateway mapping format.""" - result, _ = team_map_to_gateway_format(team_map) - - for mapping in result: - # Required fields per Gateway spec - assert "name" in mapping - assert "authenticator" in mapping - assert "map_type" in mapping - assert "organization" in mapping - assert "team" in mapping - assert "triggers" in mapping - assert "role" in mapping - assert "revoke" in mapping - assert "order" in mapping - - # Field types - assert isinstance(mapping["name"], str) - assert isinstance(mapping["authenticator"], int) - assert mapping["map_type"] == "team" # For team mappings - assert isinstance(mapping["organization"], str) - assert isinstance(mapping["team"], str) - assert isinstance(mapping["triggers"], dict) - assert isinstance(mapping["role"], str) - assert isinstance(mapping["revoke"], bool) - assert isinstance(mapping["order"], int) - - -class TestAAP51531SpecificCase: - """Test case specifically for JIRA AAP-51531 requirements.""" - - def test_ldap_networking_org_mapping_aap_51531(self): - """Test the specific LDAP organization mapping case for JIRA AAP-51531.""" - # This case is added for JIRA AAP-51531 - org_map = {"Networking": {"admins": "cn=networkadmins,ou=groups,dc=example,dc=com", "users": True, "remove_admins": True, "remove_users": True}} - - result = get_org_mappers(org_map, auth_type='ldap') - - # Should create 2 mappers: one for admins, one for users - assert len(result) == 2 - - # Find admin and user mappers - admin_mapper = next((m for m in result if m['role'] == 'Organization Admin'), None) - user_mapper = next((m for m in result if m['role'] == 'Organization Member'), None) - - assert admin_mapper is not None - assert user_mapper is not None - - # Verify admin mapper details - assert admin_mapper['organization'] == 'Networking' - assert admin_mapper['revoke'] is True # remove_admins: true - assert 'Match User Groups' in admin_mapper['name'] - assert admin_mapper['triggers']['groups']['has_or'] == ['cn=networkadmins,ou=groups,dc=example,dc=com'] - - # Verify user mapper details - assert user_mapper['organization'] == 'Networking' - assert user_mapper['revoke'] is True # remove_users: true - assert 'Always Allow' in user_mapper['name'] - assert user_mapper['triggers']['always'] == {} - - # Verify both mappers have correct map_type - assert admin_mapper['map_type'] == 'organization' - assert user_mapper['map_type'] == 'organization' diff --git a/awx/main/tests/unit/utils/test_base_migrator.py b/awx/main/tests/unit/utils/test_base_migrator.py deleted file mode 100644 index 9319483156..0000000000 --- a/awx/main/tests/unit/utils/test_base_migrator.py +++ /dev/null @@ -1,1243 +0,0 @@ -""" -Unit tests for base authenticator migrator functionality. -""" - -import pytest -from unittest.mock import Mock, patch -from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator - - -class TestBaseAuthenticatorMigrator: - """Tests for BaseAuthenticatorMigrator class.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command) - - def test_generate_authenticator_slug(self): - """Test slug generation is deterministic.""" - slug1 = self.migrator._generate_authenticator_slug('github', 'github-org') - slug2 = self.migrator._generate_authenticator_slug('github', 'github-org') - - assert slug1 == slug2 - assert slug1 == 'aap-github-github-org' - - def test_generate_authenticator_slug_different_inputs(self): - """Test that different inputs generate different slugs.""" - slug1 = self.migrator._generate_authenticator_slug('github', 'github-org') - slug2 = self.migrator._generate_authenticator_slug('github', 'github-team') - slug3 = self.migrator._generate_authenticator_slug('ldap', 'ldap') - - assert slug1 != slug2 - assert slug1 != slug3 - assert slug2 != slug3 - assert slug1 == 'aap-github-github-org' - assert slug2 == 'aap-github-github-team' - assert slug3 == 'aap-ldap-ldap' - - def test_generate_authenticator_slug_ldap_variants(self): - """Test LDAP authenticator slug generation for all supported variants.""" - # Test all LDAP authenticator naming variants - ldap_base = self.migrator._generate_authenticator_slug('ldap', 'ldap') - ldap1 = self.migrator._generate_authenticator_slug('ldap', 'ldap1') - ldap2 = self.migrator._generate_authenticator_slug('ldap', 'ldap2') - ldap3 = self.migrator._generate_authenticator_slug('ldap', 'ldap3') - ldap4 = self.migrator._generate_authenticator_slug('ldap', 'ldap4') - ldap5 = self.migrator._generate_authenticator_slug('ldap', 'ldap5') - - # Verify correct slug format - assert ldap_base == 'aap-ldap-ldap' - assert ldap1 == 'aap-ldap-ldap1' - assert ldap2 == 'aap-ldap-ldap2' - assert ldap3 == 'aap-ldap-ldap3' - assert ldap4 == 'aap-ldap-ldap4' - assert ldap5 == 'aap-ldap-ldap5' - - # Verify all slugs are unique - all_slugs = [ldap_base, ldap1, ldap2, ldap3, ldap4, ldap5] - assert len(all_slugs) == len(set(all_slugs)) - - def test_generate_authenticator_slug_github_variants(self): - """Test GitHub authenticator slug generation for all supported variants.""" - # Test all GitHub authenticator naming variants - github_base = self.migrator._generate_authenticator_slug('github', 'github') - github_org = self.migrator._generate_authenticator_slug('github', 'github-org') - github_team = self.migrator._generate_authenticator_slug('github', 'github-team') - github_enterprise_org = self.migrator._generate_authenticator_slug('github', 'github-enterprise-org') - github_enterprise_team = self.migrator._generate_authenticator_slug('github', 'github-enterprise-team') - - # Verify correct slug format - assert github_base == 'aap-github-github' - assert github_org == 'aap-github-github-org' - assert github_team == 'aap-github-github-team' - assert github_enterprise_org == 'aap-github-github-enterprise-org' - assert github_enterprise_team == 'aap-github-github-enterprise-team' - - # Verify all slugs are unique - all_slugs = [github_base, github_org, github_team, github_enterprise_org, github_enterprise_team] - assert len(all_slugs) == len(set(all_slugs)) - - def test_get_mapper_ignore_keys_default(self): - """Test default mapper ignore keys.""" - ignore_keys = self.migrator._get_mapper_ignore_keys() - - expected_keys = ['id', 'authenticator', 'created', 'modified', 'summary_fields', 'modified_by', 'created_by', 'related', 'url'] - assert ignore_keys == expected_keys - - -class TestAuthenticatorConfigComparison: - """Tests for authenticator configuration comparison methods.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command) - - def test_authenticator_configs_match_identical(self): - """Test that identical configurations match.""" - existing_auth = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456'}, - } - - new_config = existing_auth.copy() - new_config['configuration'] = existing_auth['configuration'].copy() - - assert self.migrator._authenticator_configs_match(existing_auth, new_config) == (True, []) - - def test_authenticator_configs_match_with_ignore_keys(self): - """Test that configurations match when ignoring specified keys.""" - existing_auth = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456', 'CALLBACK_URL': 'https://gateway.example.com/callback'}, - } - - new_config = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456'}, - } - - # Should not match without ignore keys - assert self.migrator._authenticator_configs_match(existing_auth, new_config) == ( - False, - [' CALLBACK_URL: existing="https://gateway.example.com/callback" vs new='], - ) - - # Should match when ignoring CALLBACK_URL - ignore_keys = ['CALLBACK_URL'] - assert self.migrator._authenticator_configs_match(existing_auth, new_config, ignore_keys) == (True, []) - - def test_authenticator_configs_different_basic_fields(self): - """Test that configurations don't match when basic fields differ.""" - existing_auth = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456'}, - } - - # Test different name - new_config = existing_auth.copy() - new_config['name'] = 'Different GitHub Auth' - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'name:' in differences[0] - - # Test different type - new_config = existing_auth.copy() - new_config['type'] = 'ansible_base.authentication.authenticator_plugins.ldap' - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'type:' in differences[0] - - # Test different enabled - new_config = existing_auth.copy() - new_config['enabled'] = False - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'enabled:' in differences[0] - - def test_authenticator_configs_different_configuration(self): - """Test that configurations don't match when configuration section differs.""" - existing_auth = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456', 'SCOPE': 'read:org'}, - } - - # Test different KEY - new_config = existing_auth.copy() - new_config['configuration'] = {'KEY': 'client789', 'SECRET': 'secret456', 'SCOPE': 'read:org'} - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'KEY:' in differences[0] - assert 'existing="client123"' in differences[0] - assert 'new="client789"' in differences[0] - - # Test missing key in new config - new_config = existing_auth.copy() - new_config['configuration'] = {'KEY': 'client123', 'SECRET': 'secret456'} - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'SCOPE:' in differences[0] - assert 'vs new=' in differences[0] - - # Test extra key in new config - new_config = existing_auth.copy() - new_config['configuration'] = {'KEY': 'client123', 'SECRET': 'secret456', 'SCOPE': 'read:org', 'EXTRA_KEY': 'extra_value'} - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config) - assert match is False - assert len(differences) == 1 - assert 'EXTRA_KEY:' in differences[0] - assert 'existing=' in differences[0] - - def test_authenticator_configs_differences_details(self): - """Test that difference tracking provides detailed information.""" - existing_auth = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': {'KEY': 'client123', 'SECRET': 'secret456', 'SCOPE': 'read:org', 'CALLBACK_URL': 'https://gateway.example.com/callback'}, - } - - # Test multiple differences with ignore keys - new_config = { - 'name': 'GitHub Auth', - 'type': 'ansible_base.authentication.authenticator_plugins.github', - 'enabled': True, - 'create_objects': True, - 'remove_users': False, - 'configuration': { - 'KEY': 'client456', # Different value - 'SECRET': 'newsecret', # Different value - 'SCOPE': 'read:org', # Same value - # CALLBACK_URL missing (but ignored) - 'NEW_FIELD': 'new_value', # Extra field - }, - } - - ignore_keys = ['CALLBACK_URL'] - match, differences = self.migrator._authenticator_configs_match(existing_auth, new_config, ignore_keys) - - assert match is False - assert len(differences) == 2 # KEY, NEW_FIELD (SECRET shows up only if --force is used) - - # Check that all expected differences are captured - difference_text = ' '.join(differences) - assert 'KEY:' in difference_text - # assert 'SECRET:' in difference_text # SECRET shows up only if --force is used - assert 'NEW_FIELD:' in difference_text - assert 'CALLBACK_URL' not in difference_text # Should be ignored - - -class TestMapperComparison: - """Tests for mapper comparison methods.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command) - - def test_mappers_match_structurally_identical(self): - """Test that identical mappers match structurally.""" - mapper1 = {'name': 'myorg - engineering', 'organization': 'myorg', 'team': 'engineering', 'map_type': 'team', 'role': 'Team Member'} - - mapper2 = mapper1.copy() - - assert self.migrator._mappers_match_structurally(mapper1, mapper2) is True - - def test_mappers_match_structurally_different_fields(self): - """Test that mappers match structurally when only name is the same.""" - base_mapper = {'name': 'myorg - engineering', 'organization': 'myorg', 'team': 'engineering', 'map_type': 'team', 'role': 'Team Member'} - - # Test different organization but same name - should still match - mapper2 = base_mapper.copy() - mapper2['organization'] = 'otherorg' - assert self.migrator._mappers_match_structurally(base_mapper, mapper2) is True - - # Test different team but same name - should still match - mapper2 = base_mapper.copy() - mapper2['team'] = 'qa' - assert self.migrator._mappers_match_structurally(base_mapper, mapper2) is True - - # Test different map_type but same name - should still match - mapper2 = base_mapper.copy() - mapper2['map_type'] = 'organization' - assert self.migrator._mappers_match_structurally(base_mapper, mapper2) is True - - # Test different role but same name - should still match - mapper2 = base_mapper.copy() - mapper2['role'] = 'Organization Admin' - assert self.migrator._mappers_match_structurally(base_mapper, mapper2) is True - - # Test different name - should not match - mapper2 = base_mapper.copy() - mapper2['name'] = 'otherorg - qa' - assert self.migrator._mappers_match_structurally(base_mapper, mapper2) is False - - def test_mapper_configs_match_identical(self): - """Test that identical mapper configurations match.""" - mapper1 = { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - } - - mapper2 = mapper1.copy() - - assert self.migrator._mapper_configs_match(mapper1, mapper2) is True - - def test_mapper_configs_match_with_ignore_keys(self): - """Test that mapper configurations match when ignoring specified keys.""" - existing_mapper = { - 'id': 123, - 'authenticator': 456, - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - 'created': '2023-01-01T00:00:00Z', - 'modified': '2023-01-01T00:00:00Z', - } - - new_mapper = { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - } - - # Should not match without ignore keys - assert self.migrator._mapper_configs_match(existing_mapper, new_mapper) is False - - # Should match when ignoring auto-generated fields - ignore_keys = ['id', 'authenticator', 'created', 'modified'] - assert self.migrator._mapper_configs_match(existing_mapper, new_mapper, ignore_keys) is True - - def test_mapper_configs_different_values(self): - """Test that mapper configurations don't match when values differ.""" - mapper1 = { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - } - - # Test different name - mapper2 = mapper1.copy() - mapper2['name'] = 'myorg - qa' - assert self.migrator._mapper_configs_match(mapper1, mapper2) is False - - # Test different order - mapper2 = mapper1.copy() - mapper2['order'] = 2 - assert self.migrator._mapper_configs_match(mapper1, mapper2) is False - - # Test different triggers - mapper2 = mapper1.copy() - mapper2['triggers'] = {'groups': {'has_or': ['qa-team']}} - assert self.migrator._mapper_configs_match(mapper1, mapper2) is False - - # Test different revoke - mapper2 = mapper1.copy() - mapper2['revoke'] = True - assert self.migrator._mapper_configs_match(mapper1, mapper2) is False - - -class TestCompareMapperLists: - """Tests for _compare_mapper_lists method.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command) - - def test_compare_mapper_lists_empty(self): - """Test comparing empty mapper lists.""" - existing_mappers = [] - new_mappers = [] - - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers) - - assert mappers_to_update == [] - assert mappers_to_create == [] - - def test_compare_mapper_lists_all_new(self): - """Test when all new mappers need to be created.""" - existing_mappers = [] - new_mappers = [ - { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - }, - { - 'name': 'myorg - qa', - 'organization': 'myorg', - 'team': 'qa', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 2, - 'triggers': {'groups': {'has_or': ['qa-team']}}, - 'revoke': False, - }, - ] - - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers) - - assert mappers_to_update == [] - assert mappers_to_create == new_mappers - - def test_compare_mapper_lists_all_existing_match(self): - """Test when all existing mappers match exactly.""" - existing_mappers = [ - { - 'id': 123, - 'authenticator': 456, - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - 'created': '2023-01-01T00:00:00Z', - 'modified': '2023-01-01T00:00:00Z', - } - ] - - new_mappers = [ - { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - } - ] - - ignore_keys = ['id', 'authenticator', 'created', 'modified'] - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers, ignore_keys) - - assert mappers_to_update == [] - assert mappers_to_create == [] - - def test_compare_mapper_lists_needs_update(self): - """Test when existing mappers need updates.""" - existing_mappers = [ - { - 'id': 123, - 'authenticator': 456, - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['old-engineers']}}, - 'revoke': False, - 'created': '2023-01-01T00:00:00Z', - 'modified': '2023-01-01T00:00:00Z', - } - ] - - new_mappers = [ - { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['new-engineers']}}, - 'revoke': False, - } - ] - - ignore_keys = ['id', 'authenticator', 'created', 'modified'] - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers, ignore_keys) - - assert len(mappers_to_update) == 1 - assert mappers_to_update[0] == (existing_mappers[0], new_mappers[0]) - assert mappers_to_create == [] - - def test_compare_mapper_lists_mixed_operations(self): - """Test mix of updates and creates.""" - existing_mappers = [ - { - 'id': 123, - 'authenticator': 456, - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['old-engineers']}}, - 'revoke': False, - 'created': '2023-01-01T00:00:00Z', - 'modified': '2023-01-01T00:00:00Z', - } - ] - - new_mappers = [ - { - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['new-engineers']}}, - 'revoke': False, - }, - { - 'name': 'myorg - qa', - 'organization': 'myorg', - 'team': 'qa', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 2, - 'triggers': {'groups': {'has_or': ['qa-team']}}, - 'revoke': False, - }, - ] - - ignore_keys = ['id', 'authenticator', 'created', 'modified'] - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers, ignore_keys) - - assert len(mappers_to_update) == 1 - assert mappers_to_update[0] == (existing_mappers[0], new_mappers[0]) - assert len(mappers_to_create) == 1 - assert mappers_to_create[0] == new_mappers[1] - - def test_compare_mapper_lists_no_structural_match(self): - """Test when existing and new mappers don't match structurally.""" - existing_mappers = [ - { - 'id': 123, - 'authenticator': 456, - 'name': 'myorg - engineering', - 'organization': 'myorg', - 'team': 'engineering', - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['engineers']}}, - 'revoke': False, - } - ] - - new_mappers = [ - { - 'name': 'otherorg - qa', - 'organization': 'otherorg', # Different organization - 'team': 'qa', # Different team - 'map_type': 'team', - 'role': 'Team Member', - 'order': 1, - 'triggers': {'groups': {'has_or': ['qa-team']}}, - 'revoke': False, - } - ] - - mappers_to_update, mappers_to_create = self.migrator._compare_mapper_lists(existing_mappers, new_mappers) - - assert mappers_to_update == [] - assert mappers_to_create == new_mappers - - -# Parametrized tests for edge cases -@pytest.mark.parametrize( - "existing_auth,new_config,ignore_keys,expected_match,expected_differences_count", - [ - # Test with None values - ({'name': 'Test', 'configuration': {'KEY': None}}, {'name': 'Test', 'configuration': {'KEY': None}}, [], True, 0), - # Test with empty configuration - ({'name': 'Test', 'configuration': {}}, {'name': 'Test', 'configuration': {}}, [], True, 0), - # Test missing configuration section - ({'name': 'Test'}, {'name': 'Test'}, [], True, 0), - # Test with ignore keys matching - ( - {'name': 'Test', 'configuration': {'KEY': 'value', 'IGNORE_ME': 'old'}}, - {'name': 'Test', 'configuration': {'KEY': 'value', 'IGNORE_ME': 'new'}}, - ['IGNORE_ME'], - True, - 0, - ), - # Test with differences that are not ignored - ( - {'name': 'Test', 'configuration': {'KEY': 'value1'}}, - {'name': 'Test', 'configuration': {'KEY': 'value2'}}, - [], - False, - 1, - ), - ], -) -def test_authenticator_configs_match_edge_cases(existing_auth, new_config, ignore_keys, expected_match, expected_differences_count): - """Test edge cases for authenticator configuration matching.""" - gateway_client = Mock() - command = Mock() - migrator = BaseAuthenticatorMigrator(gateway_client, command) - - match, differences = migrator._authenticator_configs_match(existing_auth, new_config, ignore_keys) - assert match == expected_match - assert len(differences) == expected_differences_count - - -@pytest.mark.parametrize( - "mapper1,mapper2,expected", - [ - # Test with same name - ( - {'name': 'myorg - Organization Admins', 'organization': 'myorg', 'team': None, 'map_type': 'organization', 'role': 'Organization Admin'}, - {'name': 'myorg - Organization Admins', 'organization': 'myorg', 'team': None, 'map_type': 'organization', 'role': 'Organization Admin'}, - True, - ), - # Test with same name but different other fields - ( - {'name': 'myorg - eng', 'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member', 'id': 123}, - {'name': 'myorg - eng', 'organization': 'otherorg', 'team': 'qa', 'map_type': 'organization', 'role': 'Organization Admin', 'id': 456}, - True, - ), - # Test with different names - ( - {'name': 'myorg - eng', 'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member'}, - {'name': 'myorg - qa', 'organization': 'myorg', 'team': 'qa', 'map_type': 'team', 'role': 'Team Member'}, - False, - ), - # Test with missing name - ( - {'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member'}, - {'name': 'myorg - eng', 'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member'}, - False, - ), - # Test with both missing name - ( - {'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member'}, - {'organization': 'myorg', 'team': 'eng', 'map_type': 'team', 'role': 'Team Member'}, - True, - ), - ], -) -def test_mappers_match_structurally_edge_cases(mapper1, mapper2, expected): - """Test edge cases for mapper structural matching based on name.""" - gateway_client = Mock() - command = Mock() - migrator = BaseAuthenticatorMigrator(gateway_client, command) - - 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'}} - - -class TestHandleLoginOverride: - """Tests for handle_login_override method.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = BaseAuthenticatorMigrator(self.gateway_client, self.command) - - # Reset the class-level variables before each test - BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator = False - BaseAuthenticatorMigrator.login_redirect_override_new_url = None - - def test_handle_login_override_no_login_redirect_override(self): - """Test that method returns early when no login_redirect_override is provided.""" - config = {} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_empty_login_redirect_override(self): - """Test that method returns early when login_redirect_override is empty.""" - config = {'login_redirect_override': ''} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_no_url_match(self): - """Test that method returns early when login_redirect_override doesn't match valid URLs.""" - config = {'login_redirect_override': 'https://localhost:3000/sso/login/saml'} - valid_login_urls = ['/sso/login/github', '/sso/login/azuread-oauth2'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_no_gateway_authenticator(self): - """Test that method returns early when gateway_authenticator is missing.""" - config = {'login_redirect_override': 'https://localhost:3000/sso/login/github'} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_empty_gateway_authenticator(self): - """Test that method returns early when gateway_authenticator is empty.""" - config = {'login_redirect_override': 'https://localhost:3000/sso/login/github', 'gateway_authenticator': {}} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_no_sso_login_url(self): - """Test that method returns early when sso_login_url is missing.""" - config = {'login_redirect_override': 'https://localhost:3000/sso/login/github', 'gateway_authenticator': {'id': 123}} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_empty_sso_login_url(self): - """Test that method returns early when sso_login_url is empty.""" - config = {'login_redirect_override': 'https://localhost:3000/sso/login/github', 'gateway_authenticator': {'id': 123, 'sso_login_url': ''}} - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_successful_update(self): - """Test successful LOGIN_REDIRECT_OVERRIDE update.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/sso/auth/login/123/'}, - } - valid_login_urls = ['/sso/login/github'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.example.com' - self.migrator.handle_login_override(config, valid_login_urls) - - # Verify gateway client methods were called correctly - self.gateway_client.get_base_url.assert_called_once() - # update_gateway_setting should NOT be called - URL is stored in class variable instead - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.example.com/sso/auth/login/123/' - - def test_handle_login_override_multiple_valid_urls_first_matches(self): - """Test that first matching URL in valid_login_urls is used.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github-org', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/sso/auth/login/123/'}, - } - valid_login_urls = ['/sso/login/github-org', '/sso/login/github-team', '/sso/login/github'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.example.com' - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should still work since first URL matches - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.example.com/sso/auth/login/123/' - - def test_handle_login_override_multiple_valid_urls_last_matches(self): - """Test that last matching URL in valid_login_urls is used.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/sso/auth/login/123/'}, - } - valid_login_urls = ['/sso/login/github-org', '/sso/login/github-team', '/sso/login/github'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.example.com' - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should work since last URL matches - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.example.com/sso/auth/login/123/' - - def test_handle_login_override_partial_url_match(self): - """Test that partial URL matching works (using 'in' operator).""" - config = { - 'login_redirect_override': 'https://controller.example.com/sso/login/azuread-oauth2/?next=%2Fdashboard', - 'gateway_authenticator': {'id': 456, 'sso_login_url': '/auth/login/azuread/456/'}, - } - valid_login_urls = ['/sso/login/azuread-oauth2'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.example.com:8080' - self.migrator.handle_login_override(config, valid_login_urls) - - # Should work since valid URL is contained in login_redirect_override - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.example.com:8080/auth/login/azuread/456/?next=%2Fdashboard' - - def test_handle_login_override_saml_with_parameters(self): - """Test LOGIN_REDIRECT_OVERRIDE with SAML IDP parameters.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/saml/?idp=mycompany', - 'gateway_authenticator': {'id': 789, 'sso_login_url': '/auth/login/saml/789/'}, - } - valid_login_urls = ['/sso/login/saml/?idp=mycompany'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.local' - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should work with SAML parameter URLs - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.local/auth/login/saml/789/?idp=mycompany' - - def test_handle_login_override_github_with_trailing_slash(self): - """Test LOGIN_REDIRECT_OVERRIDE with trailing slash.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github-enterprise/', - 'gateway_authenticator': {'id': 999, 'sso_login_url': '/auth/login/github/999/'}, - } - valid_login_urls = ['/sso/login/github-enterprise', '/sso/login/github-enterprise/'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.internal' - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should work with trailing slash URLs - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.internal/auth/login/github/999/' - - def test_handle_login_override_empty_valid_urls_list(self): - """Test that method returns early when valid_login_urls is empty.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/sso/auth/login/123/'}, - } - valid_login_urls = [] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should not call any gateway client methods - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_already_handled_raises_error(self): - """Test that calling handle_login_override when already handled raises RuntimeError.""" - # Set flag to True initially - BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator = True - - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/sso/auth/login/123/'}, - } - valid_login_urls = ['/sso/login/github'] - - # Should raise RuntimeError when trying to call again - with pytest.raises(RuntimeError, match="LOGIN_REDIRECT_OVERRIDE has already been handled by another migrator"): - self.migrator.handle_login_override(config, valid_login_urls) - - def test_handle_login_override_writes_output_message(self): - """Test that method writes output message when updating.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/google-oauth2', - 'gateway_authenticator': {'id': 555, 'sso_login_url': '/auth/login/google/555/'}, - } - valid_login_urls = ['/sso/login/google-oauth2'] - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.test' - - # Mock _write_output method - with patch.object(self.migrator, '_write_output') as mock_write_output: - self.migrator.handle_login_override(config, valid_login_urls) - - # Verify output message was written - mock_write_output.assert_called_once_with('LOGIN_REDIRECT_OVERRIDE will be updated to: https://gateway.test/auth/login/google/555/') - # Verify class variables were set correctly - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.test/auth/login/google/555/' - - @pytest.mark.parametrize( - "login_redirect_override,valid_urls,expected_match", - [ - # Test Azure AD variations - ('https://localhost:3000/sso/login/azuread-oauth2', ['/sso/login/azuread-oauth2'], True), - ('https://localhost:3000/sso/login/azuread-oauth2/', ['/sso/login/azuread-oauth2'], True), - ('https://controller.example.com/sso/login/azuread-oauth2?next=/home', ['/sso/login/azuread-oauth2'], True), - # Test Google OAuth2 variations - ('https://localhost:3000/sso/login/google-oauth2', ['/sso/login/google-oauth2'], True), - ('https://localhost:3000/sso/login/google-oauth2/', ['/sso/login/google-oauth2'], True), - # Test GitHub variations - ('https://localhost:3000/sso/login/github', ['/sso/login/github'], True), - ('https://localhost:3000/sso/login/github-org', ['/sso/login/github-org'], True), - ('https://localhost:3000/sso/login/github-team', ['/sso/login/github-team'], True), - ('https://localhost:3000/sso/login/github-enterprise', ['/sso/login/github-enterprise'], True), - # Test SAML variations - ('https://localhost:3000/sso/login/saml/?idp=company', ['/sso/login/saml/?idp=company'], True), - ('https://localhost:3000/sso/login/saml/?idp=test-org', ['/sso/login/saml/?idp=test-org'], True), - # Test non-matching cases - ('https://localhost:3000/sso/login/ldap', ['/sso/login/github'], False), - ('https://localhost:3000/sso/login/azuread-oauth2', ['/sso/login/google-oauth2'], False), - ('https://localhost:3000/sso/login/saml/?idp=wrong', ['/sso/login/saml/?idp=company'], False), - # Test multiple valid URLs - ('https://localhost:3000/sso/login/github-org', ['/sso/login/github', '/sso/login/github-org'], True), - ('https://localhost:3000/sso/login/github', ['/sso/login/github-org', '/sso/login/github'], True), - # Test improved URL parsing scenarios - better boundary detection - ('https://localhost:3000/sso/login/github-enterprise', ['/sso/login/github'], False), # Should NOT match due to better parsing - ('https://localhost:3000/sso/login/saml/?idp=company&next=/home', ['/sso/login/saml/?idp=company'], True), - ('https://localhost:3000/sso/login/saml/?idp=company', ['/sso/login/saml/?idp=different'], False), - ('https://controller.example.com:8080/sso/login/azuread-oauth2/?next=/dashboard', ['/sso/login/azuread-oauth2'], True), - ('http://localhost/sso/login/github?state=abc123', ['/sso/login/github'], True), - # Test boundary detection edge cases - ('https://localhost:3000/sso/login/github/', ['/sso/login/github'], True), # Trailing slash should match - ('https://localhost:3000/sso/login/github#section', ['/sso/login/github'], True), # Fragment should match - ], - ) - def test_handle_login_override_url_matching_variations(self, login_redirect_override, valid_urls, expected_match): - """Test various URL matching scenarios parametrically.""" - config = {'login_redirect_override': login_redirect_override, 'gateway_authenticator': {'id': 123, 'sso_login_url': '/auth/login/test/123/'}} - - # Mock gateway client methods - self.gateway_client.get_base_url.return_value = 'https://gateway.test' - - self.migrator.handle_login_override(config, valid_urls) - - if expected_match: - # Should call get_base_url when URL matches but NOT update_gateway_setting - self.gateway_client.get_base_url.assert_called_once() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url is not None - else: - # Should not call gateway methods when URL doesn't match - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - assert BaseAuthenticatorMigrator.login_redirect_override_new_url is None - - def test_handle_login_override_improved_url_parsing(self): - """Test that improved URL parsing with proper path boundary detection prevents false positive matches.""" - # This test demonstrates the improvement over simple string matching - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/github-enterprise', - 'gateway_authenticator': {'id': 123, 'sso_login_url': '/auth/login/test/123/'}, - } - - # With the old simple string matching, this would incorrectly match - # because '/sso/login/github' is contained in '/sso/login/github-enterprise' - # But with proper URL parsing, it should NOT match - valid_login_urls = ['/sso/login/github'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should NOT match due to improved parsing - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False - - def test_handle_login_override_query_parameter_handling(self): - """Test that query parameters are properly handled in URL matching.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/saml/?idp=mycompany&next=%2Fdashboard', - 'gateway_authenticator': {'id': 456, 'sso_login_url': '/auth/login/saml/456/?idp=IdP'}, - } - - # Should match the SAML URL with the correct IDP parameter (boundary-aware matching) - valid_login_urls = ['/sso/login/saml/?idp=mycompany'] - - self.gateway_client.get_base_url.return_value = 'https://gateway.test' - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should match because the query parameter is properly contained with boundaries - self.gateway_client.get_base_url.assert_called_once() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is True - assert BaseAuthenticatorMigrator.login_redirect_override_new_url == 'https://gateway.test/auth/login/saml/456/?idp=IdP&next=%2Fdashboard' - - def test_handle_login_override_different_query_parameters(self): - """Test that different query parameters don't match.""" - config = { - 'login_redirect_override': 'https://localhost:3000/sso/login/saml/?idp=company-a', - 'gateway_authenticator': {'id': 456, 'sso_login_url': '/auth/login/saml/456/'}, - } - - # Should NOT match SAML URL with different IDP parameter - valid_login_urls = ['/sso/login/saml/?idp=company-b'] - - self.migrator.handle_login_override(config, valid_login_urls) - - # Should NOT match because the query parameters are different - self.gateway_client.get_base_url.assert_not_called() - self.gateway_client.update_gateway_setting.assert_not_called() - assert BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator is False diff --git a/awx/main/tests/unit/utils/test_github_migrator.py b/awx/main/tests/unit/utils/test_github_migrator.py deleted file mode 100644 index 8c585091fc..0000000000 --- a/awx/main/tests/unit/utils/test_github_migrator.py +++ /dev/null @@ -1,124 +0,0 @@ -""" -Unit tests for GitHub authenticator migrator functionality. -""" - -from unittest.mock import Mock, patch -from awx.sso.utils.github_migrator import GitHubMigrator - - -class TestGitHubMigrator: - """Tests for GitHubMigrator class.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = GitHubMigrator(self.gateway_client, self.command) - - def test_create_gateway_authenticator_returns_boolean_causes_crash(self): - """ - Test that verifies create_gateway_authenticator returns proper dictionary - structure instead of boolean when credentials are missing. - - This test verifies the fix for the bug. - """ - # Mock the get_controller_config to return a GitHub config with missing credentials - github_config_missing_creds = { - 'category': 'github', - 'settings': {'SOCIAL_AUTH_GITHUB_KEY': '', 'SOCIAL_AUTH_GITHUB_SECRET': 'test-secret'}, # Missing key - 'org_mappers': [], - 'team_mappers': [], - 'login_redirect_override': None, - } - - with patch.object(self.migrator, 'get_controller_config', return_value=[github_config_missing_creds]): - with patch.object(self.migrator, '_write_output'): # Mock output to avoid noise - # This should NOT crash now that the bug is fixed - result = self.migrator.migrate() - - # Verify the migration ran successfully without crashing - assert 'created' in result - assert 'failed' in result - # Should have failed=1 since the config has success=False (missing credentials) - assert result['failed'] == 1 - - def test_create_gateway_authenticator_returns_boolean_with_unknown_category(self): - """ - Test that verifies create_gateway_authenticator returns proper dictionary - structure instead of boolean when category is unknown. - - This test verifies the fix for the bug. - """ - # Mock the get_controller_config to return a GitHub config with unknown category - github_config_unknown_category = { - 'category': 'unknown-category', - 'settings': {'SOCIAL_AUTH_UNKNOWN_KEY': 'test-key', 'SOCIAL_AUTH_UNKNOWN_SECRET': 'test-secret'}, - 'org_mappers': [], - 'team_mappers': [], - 'login_redirect_override': None, - } - - with patch.object(self.migrator, 'get_controller_config', return_value=[github_config_unknown_category]): - with patch.object(self.migrator, '_write_output'): # Mock output to avoid noise - # This should NOT crash now that the bug is fixed - result = self.migrator.migrate() - - # Verify the migration ran successfully without crashing - assert 'created' in result - assert 'failed' in result - # Should have failed=1 since the config has success=False (unknown category) - assert result['failed'] == 1 - - def test_create_gateway_authenticator_direct_boolean_return_missing_creds(self): - """ - Test that directly calls create_gateway_authenticator and verifies it returns - proper dictionary structure instead of boolean for missing credentials. - """ - # Config with missing key (empty string) - config_missing_key = { - 'category': 'github', - 'settings': {'SOCIAL_AUTH_GITHUB_KEY': '', 'SOCIAL_AUTH_GITHUB_SECRET': 'test-secret'}, # Missing key - 'org_mappers': [], - 'team_mappers': [], - 'login_redirect_override': None, - } - - with patch.object(self.migrator, '_write_output'): # Mock output to avoid noise - result = self.migrator.create_gateway_authenticator(config_missing_key) - - # Now the method should return a proper dictionary structure - assert isinstance(result, dict), f"Expected dict, got {type(result)} with value: {result}" - assert 'success' in result, f"Expected 'success' key in result: {result}" - assert 'action' in result, f"Expected 'action' key in result: {result}" - assert 'error' in result, f"Expected 'error' key in result: {result}" - # Verify the expected values - assert result['success'] is False - assert result['action'] == 'skipped' - assert 'Missing OAuth2 credentials' in result['error'] - - def test_create_gateway_authenticator_direct_boolean_return_unknown_category(self): - """ - Test that directly calls create_gateway_authenticator and verifies it returns - proper dictionary structure instead of boolean for unknown category. - """ - # Config with unknown category - config_unknown_category = { - 'category': 'unknown-category', - 'settings': {'SOCIAL_AUTH_UNKNOWN_KEY': 'test-key', 'SOCIAL_AUTH_UNKNOWN_SECRET': 'test-secret'}, - 'org_mappers': [], - 'team_mappers': [], - 'login_redirect_override': None, - } - - with patch.object(self.migrator, '_write_output'): # Mock output to avoid noise - result = self.migrator.create_gateway_authenticator(config_unknown_category) - - # Now the method should return a proper dictionary structure - assert isinstance(result, dict), f"Expected dict, got {type(result)} with value: {result}" - assert 'success' in result, f"Expected 'success' key in result: {result}" - assert 'action' in result, f"Expected 'action' key in result: {result}" - assert 'error' in result, f"Expected 'error' key in result: {result}" - # Verify the expected values - assert result['success'] is False - assert result['action'] == 'skipped' - assert 'Unknown category unknown-category' in result['error'] diff --git a/awx/main/tests/unit/utils/test_ldap_migrator.py b/awx/main/tests/unit/utils/test_ldap_migrator.py deleted file mode 100644 index 975b82d2bc..0000000000 --- a/awx/main/tests/unit/utils/test_ldap_migrator.py +++ /dev/null @@ -1,1024 +0,0 @@ -""" -Unit tests for LDAP authenticator migrator. -""" - -import ldap -from unittest.mock import Mock, patch -from awx.sso.utils.ldap_migrator import LDAPMigrator - - -class TestLDAPMigrator: - """Tests for LDAPMigrator class.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = LDAPMigrator(self.gateway_client, self.command) - - def test_get_authenticator_type(self): - """Test that get_authenticator_type returns 'LDAP'.""" - assert self.migrator.get_authenticator_type() == "LDAP" - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_no_server_uri(self, mock_settings): - """Test that LDAP configs without SERVER_URI are skipped.""" - # Mock settings to return None for SERVER_URI - mock_settings.AUTH_LDAP_SERVER_URI = None - mock_settings.AUTH_LDAP_1_SERVER_URI = None - - # Mock all other required attributes to avoid AttributeError - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert result == [] - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_with_server_uri(self, mock_settings): - """Test that LDAP config with SERVER_URI is processed.""" - # Mock basic LDAP configuration - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_BIND_DN = "cn=admin,dc=example,dc=com" - mock_settings.AUTH_LDAP_BIND_PASSWORD = "password" - mock_settings.AUTH_LDAP_START_TLS = False - mock_settings.AUTH_LDAP_CONNECTION_OPTIONS = {} - mock_settings.AUTH_LDAP_USER_SEARCH = None - mock_settings.AUTH_LDAP_USER_DN_TEMPLATE = None - mock_settings.AUTH_LDAP_USER_ATTR_MAP = {} - mock_settings.AUTH_LDAP_GROUP_SEARCH = None - mock_settings.AUTH_LDAP_GROUP_TYPE = None - mock_settings.AUTH_LDAP_GROUP_TYPE_PARAMS = {} - mock_settings.AUTH_LDAP_REQUIRE_GROUP = None - mock_settings.AUTH_LDAP_DENY_GROUP = None - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = {} - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = {} - mock_settings.AUTH_LDAP_TEAM_MAP = {} - - # Mock all other instances to return None for SERVER_URI - for i in [1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" - setattr(mock_settings, f"{prefix}SERVER_URI", None) - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - - assert len(result) == 1 - config = result[0] - assert config['category'] == 'ldap' - assert config['settings']['SERVER_URI'] == ['ldap://ldap.example.com'] - assert config['settings']['BIND_DN'] == "cn=admin,dc=example,dc=com" - assert 'org_mappers' in config - assert 'team_mappers' in config - assert 'role_mappers' in config - assert 'allow_mappers' in config - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_multiple_instances(self, mock_settings): - """Test processing multiple LDAP instances.""" - # Mock two LDAP instances - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap1.example.com" - mock_settings.AUTH_LDAP_1_SERVER_URI = "ldap://ldap2.example.com" - - # Mock all required attributes for both instances - for prefix in ["AUTH_LDAP_", "AUTH_LDAP_1_"]: - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - # Mock remaining instances to return None - for i in [2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" - setattr(mock_settings, f"{prefix}SERVER_URI", None) - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - - assert len(result) == 2 - assert result[0]['category'] == 'ldap' - assert result[1]['category'] == 'ldap' - assert result[0]['settings']['SERVER_URI'] == ['ldap://ldap1.example.com'] - assert result[1]['settings']['SERVER_URI'] == ['ldap://ldap2.example.com'] - - def test_get_ldap_instance_config_basic(self): - """Test _get_ldap_instance_config with basic settings.""" - with patch('awx.sso.utils.ldap_migrator.settings') as mock_settings: - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_BIND_DN = "cn=admin,dc=example,dc=com" - mock_settings.AUTH_LDAP_BIND_PASSWORD = "password" - mock_settings.AUTH_LDAP_START_TLS = True - - # Mock all other settings to None - for key in [ - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - result = self.migrator._get_ldap_instance_config("AUTH_LDAP_") - - assert result['SERVER_URI'] == ['ldap://ldap.example.com'] - assert result['BIND_DN'] == "cn=admin,dc=example,dc=com" - assert result['BIND_PASSWORD'] == "password" - assert result['START_TLS'] is True - - def test_get_ldap_instance_config_server_uri_list(self): - """Test SERVER_URI conversion from comma-separated string to list.""" - with patch('awx.sso.utils.ldap_migrator.settings') as mock_settings: - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap1.example.com, ldap://ldap2.example.com" - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - result = self.migrator._get_ldap_instance_config("AUTH_LDAP_") - - assert result['SERVER_URI'] == ['ldap://ldap1.example.com', 'ldap://ldap2.example.com'] - - def test_get_ldap_instance_config_user_search(self): - """Test USER_SEARCH conversion from LDAPSearch object.""" - with patch('awx.sso.utils.ldap_migrator.settings') as mock_settings: - # Mock LDAPSearch object - mock_search = Mock() - mock_search.base_dn = "ou=users,dc=example,dc=com" - mock_search.filterstr = "(uid=%(user)s)" - mock_search.scope = ldap.SCOPE_SUBTREE - - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_USER_SEARCH = mock_search - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - result = self.migrator._get_ldap_instance_config("AUTH_LDAP_") - - assert result['USER_SEARCH'] == ["ou=users,dc=example,dc=com", "SCOPE_SUBTREE", "(uid=%(user)s)"] - - def test_get_ldap_instance_config_group_type(self): - """Test GROUP_TYPE conversion from class to string.""" - with patch('awx.sso.utils.ldap_migrator.settings') as mock_settings: - # Mock group type class with proper __name__ attribute - mock_group_type = Mock() - # Use type() to create a proper class name - mock_group_type.__name__ = "PosixGroupType" - type(mock_group_type).__name__ = "PosixGroupType" - - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_GROUP_TYPE = mock_group_type - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - result = self.migrator._get_ldap_instance_config("AUTH_LDAP_") - - assert result['GROUP_TYPE'] == "PosixGroupType" - - def test_build_ldap_configuration(self): - """Test _build_ldap_configuration method.""" - settings = { - 'SERVER_URI': ['ldap://ldap.example.com'], - 'BIND_DN': 'cn=admin,dc=example,dc=com', - 'BIND_PASSWORD': 'password', - 'START_TLS': True, - 'USER_SEARCH': ['ou=users,dc=example,dc=com', 'SCOPE_SUBTREE', '(uid=%(user)s)'], - 'USER_ATTR_MAP': {'first_name': 'givenName', 'last_name': 'sn', 'email': 'mail'}, - 'GROUP_SEARCH': ['ou=groups,dc=example,dc=com', 'SCOPE_SUBTREE', '(objectClass=posixGroup)'], - 'GROUP_TYPE': 'PosixGroupType', - 'GROUP_TYPE_PARAMS': {'name_attr': 'cn'}, - 'USER_DN_TEMPLATE': 'uid=%(user)s,ou=users,dc=example,dc=com', - 'CONNECTION_OPTIONS': {ldap.OPT_REFERRALS: 0}, - } - - result = self.migrator._build_ldap_configuration(settings) - - assert result['SERVER_URI'] == ['ldap://ldap.example.com'] - assert result['BIND_DN'] == 'cn=admin,dc=example,dc=com' - assert result['BIND_PASSWORD'] == 'password' - assert result['START_TLS'] is True - assert result['USER_SEARCH'] == ['ou=users,dc=example,dc=com', 'SCOPE_SUBTREE', '(uid=%(user)s)'] - assert result['USER_ATTR_MAP'] == {'first_name': 'givenName', 'last_name': 'sn', 'email': 'mail'} - assert result['GROUP_SEARCH'] == ['ou=groups,dc=example,dc=com', 'SCOPE_SUBTREE', '(objectClass=posixGroup)'] - assert result['GROUP_TYPE'] == 'PosixGroupType' - assert result['GROUP_TYPE_PARAMS'] == {'name_attr': 'cn'} - assert result['USER_DN_TEMPLATE'] == 'uid=%(user)s,ou=users,dc=example,dc=com' - assert 'CONNECTION_OPTIONS' in result - - def test_build_ldap_configuration_minimal(self): - """Test _build_ldap_configuration with minimal settings.""" - settings = {'SERVER_URI': ['ldap://ldap.example.com']} - - result = self.migrator._build_ldap_configuration(settings) - - assert result == {'SERVER_URI': ['ldap://ldap.example.com']} - - def test_convert_ldap_connection_options(self): - """Test _convert_ldap_connection_options method.""" - connection_options = { - ldap.OPT_REFERRALS: 0, - ldap.OPT_PROTOCOL_VERSION: 3, - ldap.OPT_NETWORK_TIMEOUT: 30, - ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER, - } - - result = self.migrator._convert_ldap_connection_options(connection_options) - - assert result['OPT_REFERRALS'] == 0 - assert result['OPT_PROTOCOL_VERSION'] == 3 - assert result['OPT_NETWORK_TIMEOUT'] == 30 - assert result['OPT_X_TLS_REQUIRE_CERT'] == ldap.OPT_X_TLS_NEVER - - def test_convert_ldap_connection_options_unknown_option(self): - """Test _convert_ldap_connection_options with unknown option.""" - connection_options = {999999: 'unknown_value', ldap.OPT_REFERRALS: 0} # Unknown LDAP option - - result = self.migrator._convert_ldap_connection_options(connection_options) - - # Unknown option should be ignored - assert 'OPT_REFERRALS' in result - assert len(result) == 1 - - def test_ldap_group_allow_to_gateway_format_none(self): - """Test _ldap_group_allow_to_gateway_format with None group.""" - result = [] - output_result, next_order = self.migrator._ldap_group_allow_to_gateway_format(result, None, deny=False, start_order=1) - - assert output_result == [] - assert next_order == 1 - - def test_ldap_group_allow_to_gateway_format_require_group(self): - """Test _ldap_group_allow_to_gateway_format for require group.""" - result = [] - ldap_group = "cn=allowed_users,dc=example,dc=com" - - output_result, next_order = self.migrator._ldap_group_allow_to_gateway_format(result, ldap_group, deny=False, start_order=1) - - expected = [ - { - "name": "LDAP-RequireGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": False, - "triggers": {"groups": {"has_and": ["cn=allowed_users,dc=example,dc=com"]}}, - "order": 1, - } - ] - - assert output_result == expected - assert next_order == 2 - - def test_ldap_group_allow_to_gateway_format_deny_group(self): - """Test _ldap_group_allow_to_gateway_format for deny group.""" - result = [] - ldap_group = "cn=blocked_users,dc=example,dc=com" - - output_result, next_order = self.migrator._ldap_group_allow_to_gateway_format(result, ldap_group, deny=True, start_order=5) - - expected = [ - { - "name": "LDAP-DenyGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": True, - "triggers": {"groups": {"has_or": ["cn=blocked_users,dc=example,dc=com"]}}, - "order": 5, - } - ] - - assert output_result == expected - assert next_order == 6 - - def test_create_gateway_authenticator(self): - """Test create_gateway_authenticator method.""" - config = { - 'category': 'ldap', - 'settings': {'SERVER_URI': ['ldap://ldap.example.com'], 'BIND_DN': 'cn=admin,dc=example,dc=com', 'BIND_PASSWORD': 'password'}, - 'org_mappers': [], - 'team_mappers': [], - 'role_mappers': [], - 'allow_mappers': [], - } - - with patch.object(self.migrator, 'submit_authenticator') as mock_submit: - mock_submit.return_value = {'id': 123, 'name': 'ldap'} - - result = self.migrator.create_gateway_authenticator(config) - - # Verify submit_authenticator was called - mock_submit.assert_called_once() - call_args = mock_submit.call_args - gateway_config = call_args[0][0] - - assert gateway_config['name'] == 'ldap' - assert gateway_config['type'] == 'ansible_base.authentication.authenticator_plugins.ldap' - assert gateway_config['create_objects'] is True - assert gateway_config['remove_users'] is False - assert gateway_config['enabled'] is True - assert 'configuration' in gateway_config - - assert result == {'id': 123, 'name': 'ldap'} - - def test_create_gateway_authenticator_slug_generation(self): - """Test that create_gateway_authenticator generates correct slug.""" - config = { - 'category': 'ldap', - 'settings': {'SERVER_URI': ['ldap://ldap.example.com']}, - 'org_mappers': [], - 'team_mappers': [], - 'role_mappers': [], - 'allow_mappers': [], - } - - with patch.object(self.migrator, 'submit_authenticator') as mock_submit: - with patch.object(self.migrator, '_generate_authenticator_slug', return_value='aap-ldap-ldap') as mock_slug: - mock_submit.return_value = {'id': 123, 'name': 'ldap'} - - self.migrator.create_gateway_authenticator(config) - - mock_slug.assert_called_once_with('ldap', 'ldap') - call_args = mock_submit.call_args - gateway_config = call_args[0][0] - assert gateway_config['slug'] == 'aap-ldap-ldap' - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_with_mappings(self, mock_settings): - """Test get_controller_config with organization and team mappings.""" - # Mock LDAP configuration with mappings - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = {"TestOrg": {"users": ["admin_group"], "admins": ["super_admin_group"]}} - mock_settings.AUTH_LDAP_TEAM_MAP = {"TestTeam": {"organization": "TestOrg", "users": ["team_group"]}} - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = {"is_superuser": ["super_group"]} - mock_settings.AUTH_LDAP_REQUIRE_GROUP = "cn=allowed,dc=example,dc=com" - mock_settings.AUTH_LDAP_DENY_GROUP = "cn=blocked,dc=example,dc=com" - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - # Mock all other instances to return None - for i in [1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" - setattr(mock_settings, f"{prefix}SERVER_URI", None) - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - - assert len(result) == 1 - config = result[0] - - # Check that mappers were generated - assert len(config['org_mappers']) > 0 - assert len(config['team_mappers']) > 0 - assert len(config['role_mappers']) > 0 - assert len(config['allow_mappers']) > 0 # Should have deny and require group mappers - - # Verify allow mappers contain deny and require groups - allow_mapper_names = [mapper['name'] for mapper in config['allow_mappers']] - assert 'LDAP-DenyGroup' in allow_mapper_names - assert 'LDAP-RequireGroup' in allow_mapper_names - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_with_specific_org_mapping(self, mock_settings): - """Test get_controller_config with specific organization mapping including remove flags.""" - # Mock LDAP configuration with the exact mapping from the user request - # This case is added for AAP-51531 - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = { - "Networking": {"admins": "cn=networkadmins,ou=groups,dc=example,dc=com", "users": True, "remove_admins": True, "remove_users": True} - } - mock_settings.AUTH_LDAP_TEAM_MAP = {} - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = {} - mock_settings.AUTH_LDAP_REQUIRE_GROUP = None - mock_settings.AUTH_LDAP_DENY_GROUP = None - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - # Mock all other instances to return None - for i in [1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" - setattr(mock_settings, f"{prefix}SERVER_URI", None) - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - - assert len(result) == 1 - config = result[0] - - # Should have 2 organization mappers: 1 for admins, 1 for users - assert len(config['org_mappers']) == 2 - - # Find the admin and user mappers - admin_mapper = next((m for m in config['org_mappers'] if 'Admins' in m['name']), None) - user_mapper = next((m for m in config['org_mappers'] if 'Users' in m['name']), None) - - assert admin_mapper is not None - assert user_mapper is not None - - # Verify admin mapper details - assert admin_mapper['organization'] == 'Networking' - assert admin_mapper['role'] == 'Organization Admin' - assert admin_mapper['revoke'] is True # remove_admins: true - assert 'Match User Groups' in admin_mapper['name'] - assert admin_mapper['triggers']['groups']['has_or'] == ['cn=networkadmins,ou=groups,dc=example,dc=com'] - - # Verify user mapper details - assert user_mapper['organization'] == 'Networking' - assert user_mapper['role'] == 'Organization Member' - assert user_mapper['revoke'] is True # remove_users: true - assert 'Always Allow' in user_mapper['name'] - assert user_mapper['triggers']['always'] == {} - - # Verify ordering (admin mapper should come before user mapper) - admin_order = admin_mapper['order'] - user_order = user_mapper['order'] - assert admin_order < user_order - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_get_controller_config_with_complex_org_mapping(self, mock_settings): - """Test get_controller_config with complex organization mapping scenarios.""" - # Mock LDAP configuration with various mapping types - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = { - # This case is added for AAP-51531 - "Networking": {"admins": "cn=networkadmins,ou=groups,dc=example,dc=com", "users": True, "remove_admins": True, "remove_users": True}, - "Development": { - "admins": ["cn=devadmins,ou=groups,dc=example,dc=com", "cn=leaddevs,ou=groups,dc=example,dc=com"], - "users": ["cn=developers,ou=groups,dc=example,dc=com"], - "remove_admins": False, - "remove_users": False, - }, - "QA": {"users": False, "remove_users": False}, # Never allow - } - mock_settings.AUTH_LDAP_TEAM_MAP = {} - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = {} - mock_settings.AUTH_LDAP_REQUIRE_GROUP = None - mock_settings.AUTH_LDAP_DENY_GROUP = None - - # Mock all other settings to None - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - ]: - setattr(mock_settings, f"AUTH_LDAP_{key}", None) - - # Mock all other instances to return None - for i in [1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" - setattr(mock_settings, f"{prefix}SERVER_URI", None) - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - 'USER_FLAGS_BY_GROUP', - 'ORGANIZATION_MAP', - 'TEAM_MAP', - ]: - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - - assert len(result) == 1 - config = result[0] - - # Should have 5 organization mappers total: - # Networking: 2 (admins + users) - # Development: 2 (admins list creates 1 + users list creates 1) - # QA: 1 (users False creates 1) - assert len(config['org_mappers']) == 5 - - # Verify Networking mappers - networking_mappers = [m for m in config['org_mappers'] if m['organization'] == 'Networking'] - assert len(networking_mappers) == 2 - - # Verify Development mappers (should have 2: 1 admin group + 1 user group) - development_mappers = [m for m in config['org_mappers'] if m['organization'] == 'Development'] - assert len(development_mappers) == 2 - - # Verify QA mappers (should have 1: users = False creates Never Allow) - qa_mappers = [m for m in config['org_mappers'] if m['organization'] == 'QA'] - assert len(qa_mappers) == 1 - qa_user_mapper = qa_mappers[0] - assert 'Never Allow' in qa_user_mapper['name'] - assert qa_user_mapper['triggers']['never'] == {} - assert qa_user_mapper['revoke'] is False - - def test_ldap_organization_mapping_with_remove_flags_integration(self): - """Integration test for the specific organization mapping with remove flags.""" - # Test the exact scenario from the user's request using the gateway mapping functions directly - from awx.main.utils.gateway_mapping import org_map_to_gateway_format - - # This case is added for AAP-51531 - org_map = {"Networking": {"admins": "cn=networkadmins,ou=groups,dc=example,dc=com", "users": True, "remove_admins": True, "remove_users": True}} - - result, next_order = org_map_to_gateway_format(org_map, start_order=1, auth_type='ldap') - - assert len(result) == 2 - - # Find admin and user mappers - admin_mapper = next((m for m in result if m['role'] == 'Organization Admin'), None) - user_mapper = next((m for m in result if m['role'] == 'Organization Member'), None) - - assert admin_mapper is not None - assert user_mapper is not None - - # Verify admin mapper - assert admin_mapper['organization'] == 'Networking' - assert admin_mapper['revoke'] is True - assert admin_mapper['triggers']['groups']['has_or'] == ['cn=networkadmins,ou=groups,dc=example,dc=com'] - assert 'Match User Groups' in admin_mapper['name'] - - # Verify user mapper - assert user_mapper['organization'] == 'Networking' - assert user_mapper['revoke'] is True - assert user_mapper['triggers']['always'] == {} - assert 'Always Allow' in user_mapper['name'] - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_mixed_boolean_and_group_mappings(self, mock_settings): - """Test organization mapping with mixed boolean and group assignments.""" - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = { - "MixedOrg": { - "admins": True, # All users are admins - "users": ["cn=engineers,ou=groups,dc=example,dc=com", "cn=qa,ou=groups,dc=example,dc=com"], # Specific groups are users - "remove_admins": False, - "remove_users": True, - } - } - mock_settings.AUTH_LDAP_TEAM_MAP = {} - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'USER_FLAGS_BY_GROUP', - 'REQUIRE_GROUP', - 'DENY_GROUP', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should have 2 mappers: admin (True) and users (groups) - assert len(config['org_mappers']) == 2 - - # Find admin mapper (should have 'always' trigger) - admin_mapper = next(mapper for mapper in config['org_mappers'] if 'Admins' in mapper['name']) - assert admin_mapper['triggers']['always'] == {} - - # Find user mapper (should have groups trigger) - user_mapper = next(mapper for mapper in config['org_mappers'] if 'Users' in mapper['name']) - assert user_mapper['triggers']['groups']['has_or'] == ["cn=engineers,ou=groups,dc=example,dc=com", "cn=qa,ou=groups,dc=example,dc=com"] - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_user_flags_multiple_types(self, mock_settings): - """Test LDAP user flags with multiple flag types simultaneously.""" - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = {} - mock_settings.AUTH_LDAP_TEAM_MAP = {} - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = { - "is_superuser": ["cn=superusers,ou=groups,dc=example,dc=com", "cn=admins,ou=groups,dc=example,dc=com"], - "is_system_auditor": "cn=auditors,ou=groups,dc=example,dc=com", - } - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'REQUIRE_GROUP', - 'DENY_GROUP', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP', 'USER_FLAGS_BY_GROUP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should have role mappers for both flag types - assert len(config['role_mappers']) == 2 - - role_mapper_names = [mapper['name'] for mapper in config['role_mappers']] - assert "is_superuser - role" in role_mapper_names - assert "is_system_auditor - role" in role_mapper_names - - # Verify superuser mapper has multiple groups - superuser_mapper = next(mapper for mapper in config['role_mappers'] if mapper['name'] == "is_superuser - role") - assert superuser_mapper['triggers']['groups']['has_or'] == ["cn=superusers,ou=groups,dc=example,dc=com", "cn=admins,ou=groups,dc=example,dc=com"] - - # Verify auditor mapper has single group - auditor_mapper = next(mapper for mapper in config['role_mappers'] if mapper['name'] == "is_system_auditor - role") - assert auditor_mapper['triggers']['groups']['has_or'] == ["cn=auditors,ou=groups,dc=example,dc=com"] - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_team_mapping_nonexistent_organization(self, mock_settings): - """Test team mapping that references a non-existent organization.""" - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = {} # No organizations defined - mock_settings.AUTH_LDAP_TEAM_MAP = { - "OrphanTeam": {"organization": "NonExistentOrg", "users": "cn=teamusers,ou=groups,dc=example,dc=com", "remove": True} - } - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'USER_FLAGS_BY_GROUP', - 'REQUIRE_GROUP', - 'DENY_GROUP', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should still create team mapper - assert len(config['team_mappers']) == 1 - team_mapper = config['team_mappers'][0] - assert "OrphanTeam" in team_mapper['name'] - assert team_mapper['organization'] == "NonExistentOrg" - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_organization_with_special_characters(self, mock_settings): - """Test organization mapping with special characters in organization names.""" - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = { - "Org-With-Dashes": {"users": True, "admins": False}, - "Org With Spaces": {"users": "cn=users,dc=example,dc=com", "admins": None}, - "Org_With_Underscores": {"users": ["cn=group1,dc=example,dc=com"], "admins": True}, - } - mock_settings.AUTH_LDAP_TEAM_MAP = {} - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'USER_FLAGS_BY_GROUP', - 'REQUIRE_GROUP', - 'DENY_GROUP', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should create mappers for all organizations with special characters - assert len(config['org_mappers']) == 5 # 3 orgs: 2 mappers for Org-With-Dashes, 1 for Org With Spaces, 2 for Org_With_Underscores - - org_mapper_names = [mapper['name'] for mapper in config['org_mappers']] - assert "Org-With-Dashes - Users Always Allow" in org_mapper_names - assert "Org With Spaces - Users Match User Groups" in org_mapper_names - assert "Org_With_Underscores - Admins Always Allow" in org_mapper_names - assert "Org_With_Underscores - Users Match User Groups" in org_mapper_names - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_empty_organization_mapping(self, mock_settings): - """Test LDAP config with empty organization mapping.""" - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = {} # Empty mapping - mock_settings.AUTH_LDAP_TEAM_MAP = {} - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - 'USER_FLAGS_BY_GROUP', - 'REQUIRE_GROUP', - 'DENY_GROUP', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should have no organization mappers - assert len(config['org_mappers']) == 0 - assert len(config['team_mappers']) == 0 - - @patch('awx.sso.utils.ldap_migrator.settings') - def test_ldap_networking_org_mapping_aap_51531_dedicated(self, mock_settings): - """Dedicated test for the specific LDAP organization mapping case for JIRA AAP-51531.""" - # This case is added for JIRA AAP-51531 - mock_settings.AUTH_LDAP_SERVER_URI = "ldap://ldap.example.com" - mock_settings.AUTH_LDAP_ORGANIZATION_MAP = { - "Networking": {"admins": "cn=networkadmins,ou=groups,dc=example,dc=com", "users": True, "remove_admins": True, "remove_users": True} - } - mock_settings.AUTH_LDAP_TEAM_MAP = {} - mock_settings.AUTH_LDAP_USER_FLAGS_BY_GROUP = {} - mock_settings.AUTH_LDAP_REQUIRE_GROUP = None - mock_settings.AUTH_LDAP_DENY_GROUP = None - - # Mock all other settings to None - for i in [None, 1, 2, 3, 4, 5]: - prefix = f"AUTH_LDAP_{i}_" if i is not None else "AUTH_LDAP_" - for key in [ - 'BIND_DN', - 'BIND_PASSWORD', - 'START_TLS', - 'CONNECTION_OPTIONS', - 'USER_SEARCH', - 'USER_DN_TEMPLATE', - 'USER_ATTR_MAP', - 'GROUP_SEARCH', - 'GROUP_TYPE', - 'GROUP_TYPE_PARAMS', - ]: - if i is None and key in ['SERVER_URI', 'ORGANIZATION_MAP', 'TEAM_MAP', 'USER_FLAGS_BY_GROUP', 'REQUIRE_GROUP', 'DENY_GROUP']: - continue - setattr(mock_settings, f"{prefix}{key}", None) - - result = self.migrator.get_controller_config() - assert len(result) == 1 - config = result[0] - - # Should create exactly 2 organization mappers for the Networking org - assert len(config['org_mappers']) == 2 - assert config['category'] == 'ldap' - - # Find admin and user mappers - admin_mapper = next((m for m in config['org_mappers'] if 'Admins' in m['name']), None) - user_mapper = next((m for m in config['org_mappers'] if 'Users' in m['name']), None) - - assert admin_mapper is not None - assert user_mapper is not None - - # Verify admin mapper details for JIRA AAP-51531 - assert admin_mapper['organization'] == 'Networking' - assert admin_mapper['revoke'] is True # remove_admins: true - assert 'Match User Groups' in admin_mapper['name'] - assert admin_mapper['triggers']['groups']['has_or'] == ['cn=networkadmins,ou=groups,dc=example,dc=com'] - - # Verify user mapper details for JIRA AAP-51531 - assert user_mapper['organization'] == 'Networking' - assert user_mapper['revoke'] is True # remove_users: true - assert 'Always Allow' in user_mapper['name'] - assert user_mapper['triggers']['always'] == {} - - # Verify both mappers have correct properties - assert admin_mapper['map_type'] == 'organization' - assert user_mapper['map_type'] == 'organization' - assert admin_mapper['authenticator'] == -1 - assert user_mapper['authenticator'] == -1 diff --git a/awx/main/tests/unit/utils/test_role_mapping.py b/awx/main/tests/unit/utils/test_role_mapping.py deleted file mode 100644 index 72c0de84bb..0000000000 --- a/awx/main/tests/unit/utils/test_role_mapping.py +++ /dev/null @@ -1,614 +0,0 @@ -""" -Unit tests for role mapping utilities. -""" - -import pytest -from awx.main.utils.gateway_mapping import role_map_to_gateway_format -from awx.sso.utils.ldap_migrator import LDAPMigrator - - -def get_role_mappers(role_map, start_order=1): - """Helper function to get just the mappers from role_map_to_gateway_format.""" - result, _ = role_map_to_gateway_format(role_map, start_order) - return result - - -def ldap_group_allow_to_gateway_format(result, ldap_group, deny=False, start_order=1): - """Helper function to test LDAP group allow mapping via LDAPMigrator.""" - migrator = LDAPMigrator() - return migrator._ldap_group_allow_to_gateway_format(result, ldap_group, deny, start_order) - - -class TestRoleMapToGatewayFormat: - """Tests for role_map_to_gateway_format function.""" - - def test_none_input(self): - """Test that None input returns empty list.""" - result, next_order = role_map_to_gateway_format(None) - assert result == [] - assert next_order == 1 # Default start_order - - def test_empty_dict(self): - """Test that empty dict returns empty list.""" - result, next_order = role_map_to_gateway_format({}) - assert result == [] - assert next_order == 1 - - def test_is_superuser_single_group(self): - """Test is_superuser with single group.""" - role_map = {"is_superuser": "cn=awx_super_users,OU=administration groups,DC=contoso,DC=com"} - - result, _ = role_map_to_gateway_format(role_map) - - expected = [ - { - "name": "is_superuser - role", - "authenticator": -1, - "revoke": True, - "map_type": "is_superuser", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=awx_super_users,OU=administration groups,DC=contoso,DC=com"], - } - }, - "order": 1, - } - ] - - assert result == expected - - def test_is_superuser_multiple_groups(self): - """Test is_superuser with multiple groups.""" - role_map = {"is_superuser": ["cn=super_users,dc=example,dc=com", "cn=admins,dc=example,dc=com"]} - - result, _ = role_map_to_gateway_format(role_map) - - expected = [ - { - "name": "is_superuser - role", - "authenticator": -1, - "revoke": True, - "map_type": "is_superuser", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=super_users,dc=example,dc=com", "cn=admins,dc=example,dc=com"], - } - }, - "order": 1, - } - ] - - assert result == expected - - def test_is_system_auditor_single_group(self): - """Test is_system_auditor with single group.""" - role_map = {"is_system_auditor": "cn=auditors,dc=example,dc=com"} - - result, _ = role_map_to_gateway_format(role_map) - - expected = [ - { - "name": "is_system_auditor - role", - "authenticator": -1, - "revoke": True, - "map_type": "role", - "role": "Platform Auditor", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=auditors,dc=example,dc=com"], - } - }, - "order": 1, - } - ] - - assert result == expected - - def test_is_system_auditor_multiple_groups(self): - """Test is_system_auditor with multiple groups.""" - role_map = {"is_system_auditor": ["cn=auditors,dc=example,dc=com", "cn=viewers,dc=example,dc=com"]} - - result, _ = role_map_to_gateway_format(role_map) - - expected = [ - { - "name": "is_system_auditor - role", - "authenticator": -1, - "revoke": True, - "map_type": "role", - "role": "Platform Auditor", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=auditors,dc=example,dc=com", "cn=viewers,dc=example,dc=com"], - } - }, - "order": 1, - } - ] - - assert result == expected - - def test_multiple_roles(self): - """Test multiple role mappings.""" - role_map = {"is_superuser": "cn=super_users,dc=example,dc=com", "is_system_auditor": "cn=auditors,dc=example,dc=com"} - - result, _ = role_map_to_gateway_format(role_map) - - expected = [ - { - "name": "is_superuser - role", - "authenticator": -1, - "revoke": True, - "map_type": "is_superuser", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=super_users,dc=example,dc=com"], - } - }, - "order": 1, - }, - { - "name": "is_system_auditor - role", - "authenticator": -1, - "revoke": True, - "map_type": "role", - "role": "Platform Auditor", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": ["cn=auditors,dc=example,dc=com"], - } - }, - "order": 2, - }, - ] - - assert result == expected - - def test_unsupported_role_flag(self): - """Test that unsupported role flags are ignored.""" - role_map = { - "is_superuser": "cn=super_users,dc=example,dc=com", - "is_staff": "cn=staff,dc=example,dc=com", # Unsupported flag - "is_system_auditor": "cn=auditors,dc=example,dc=com", - } - - result, _ = role_map_to_gateway_format(role_map) - - # Should only have 2 mappers (is_superuser and is_system_auditor) - assert len(result) == 2 - assert result[0]["map_type"] == "is_superuser" - assert result[1]["map_type"] == "role" - assert result[1]["role"] == "Platform Auditor" - - def test_order_increments_correctly(self): - """Test that order values increment correctly.""" - role_map = {"is_superuser": "cn=super_users,dc=example,dc=com", "is_system_auditor": "cn=auditors,dc=example,dc=com"} - - result, _ = role_map_to_gateway_format(role_map) - - assert len(result) == 2 - assert result[0]["order"] == 1 - assert result[1]["order"] == 2 - - def test_start_order_parameter(self): - """Test that start_order parameter is respected.""" - role_map = {"is_superuser": "cn=super_users,dc=example,dc=com"} - - result, next_order = role_map_to_gateway_format(role_map, start_order=5) - - assert result[0]["order"] == 5 - assert next_order == 6 - - def test_string_to_list_conversion(self): - """Test that string groups are converted to lists.""" - role_map = {"is_superuser": "single-group"} - - result, _ = role_map_to_gateway_format(role_map) - - # Should convert string to list for has_or - assert result[0]["triggers"]["groups"]["has_or"] == ["single-group"] - - def test_triggers_format_validation(self): - """Test that trigger formats match Gateway specification.""" - role_map = {"is_superuser": ["group1", "group2"]} - - result, _ = role_map_to_gateway_format(role_map) - - # Validate that triggers follow Gateway format - triggers = result[0]["triggers"] - assert "groups" in triggers - assert "has_or" in triggers["groups"] - assert isinstance(triggers["groups"]["has_or"], list) - assert triggers["groups"]["has_or"] == ["group1", "group2"] - - def test_ldap_dn_format(self): - """Test with realistic LDAP DN format.""" - role_map = { - "is_superuser": "cn=awx_super_users,OU=administration groups,DC=contoso,DC=com", - "is_system_auditor": "cn=awx_auditors,OU=administration groups,DC=contoso,DC=com", - } - - result, _ = role_map_to_gateway_format(role_map) - - assert len(result) == 2 - assert result[0]["triggers"]["groups"]["has_or"] == ["cn=awx_super_users,OU=administration groups,DC=contoso,DC=com"] - assert result[1]["triggers"]["groups"]["has_or"] == ["cn=awx_auditors,OU=administration groups,DC=contoso,DC=com"] - - def test_gateway_format_compliance(self): - """Test that all results comply with Gateway role mapping format.""" - role_map = {"is_superuser": "cn=super_users,dc=example,dc=com", "is_system_auditor": "cn=auditors,dc=example,dc=com"} - - result, _ = role_map_to_gateway_format(role_map) - - for mapping in result: - # Required fields per Gateway spec - assert "name" in mapping - assert "authenticator" in mapping - assert "map_type" in mapping - assert "organization" in mapping - assert "team" in mapping - assert "triggers" in mapping - assert "order" in mapping - assert "revoke" in mapping - - # Field types - assert isinstance(mapping["name"], str) - assert isinstance(mapping["authenticator"], int) - assert mapping["map_type"] in ["is_superuser", "role"] - assert mapping["organization"] is None - assert mapping["team"] is None - assert isinstance(mapping["triggers"], dict) - assert isinstance(mapping["order"], int) - assert isinstance(mapping["revoke"], bool) - - # Specific field validations based on map_type - if mapping["map_type"] == "is_superuser": - assert "role" not in mapping - elif mapping["map_type"] == "role": - assert "role" in mapping - assert isinstance(mapping["role"], str) - assert mapping["role"] == "Platform Auditor" - - -# Parametrized tests for role mappings -@pytest.mark.parametrize( - "role_map,expected_length", - [ - (None, 0), - ({}, 0), - ({"is_superuser": "group1"}, 1), - ({"is_system_auditor": "group1"}, 1), - ({"is_superuser": "group1", "is_system_auditor": "group2"}, 2), - ({"is_staff": "group1"}, 0), # Unsupported flag - ({"is_superuser": "group1", "is_staff": "group2", "is_system_auditor": "group3"}, 2), # Mixed supported/unsupported - ], -) -def test_role_map_result_lengths(role_map, expected_length): - """Test that role_map_to_gateway_format returns expected number of mappings.""" - result, _ = role_map_to_gateway_format(role_map) - assert len(result) == expected_length - - -# Edge case tests -def test_empty_groups_handling(): - """Test handling of empty group lists.""" - role_map = {"is_superuser": []} - - result, _ = role_map_to_gateway_format(role_map) - - assert len(result) == 1 - assert result[0]["triggers"]["groups"]["has_or"] == [] - - -def test_mixed_group_types(): - """Test handling of mixed group types (string and list).""" - role_map = {"is_superuser": "single-group", "is_system_auditor": ["group1", "group2"]} - - result, _ = role_map_to_gateway_format(role_map) - - assert len(result) == 2 - assert result[0]["triggers"]["groups"]["has_or"] == ["single-group"] - assert result[1]["triggers"]["groups"]["has_or"] == ["group1", "group2"] - - -def test_realistic_ldap_user_flags_by_group(): - """Test with realistic LDAP USER_FLAGS_BY_GROUP data.""" - role_map = {"is_superuser": "cn=awx_super_users,OU=administration groups,DC=contoso,DC=com"} - - result, _ = role_map_to_gateway_format(role_map) - - # This is exactly the use case from the user's example - assert len(result) == 1 - assert result[0]["map_type"] == "is_superuser" - assert result[0]["triggers"]["groups"]["has_or"] == ["cn=awx_super_users,OU=administration groups,DC=contoso,DC=com"] - assert result[0]["revoke"] is True - assert result[0]["team"] is None - assert result[0]["organization"] is None - - -class TestLdapGroupAllowToGatewayFormat: - """Tests for ldap_group_allow_to_gateway_format function.""" - - def test_none_input_with_empty_result(self): - """Test that None input with empty result returns unchanged result.""" - result = [] - output_result, next_order = ldap_group_allow_to_gateway_format(result, None, deny=False) - - assert output_result == [] - assert next_order == 1 # Default start_order - - def test_none_input_with_existing_result(self): - """Test that None input with existing mappers returns unchanged result.""" - result = [{"existing": "mapper"}] - output_result, next_order = ldap_group_allow_to_gateway_format(result, None, deny=False, start_order=5) - - assert output_result == [{"existing": "mapper"}] - assert next_order == 5 # start_order unchanged - - def test_require_group_mapping(self): - """Test LDAP REQUIRE_GROUP mapping (deny=False).""" - result = [] - ldap_group = "cn=allowed_users,dc=example,dc=com" - - output_result, next_order = ldap_group_allow_to_gateway_format(result, ldap_group, deny=False, start_order=1) - - expected = [ - { - "name": "LDAP-RequireGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": False, - "triggers": {"groups": {"has_and": ["cn=allowed_users,dc=example,dc=com"]}}, - "order": 1, - } - ] - - assert output_result == expected - assert next_order == 2 - - def test_deny_group_mapping(self): - """Test LDAP DENY_GROUP mapping (deny=True).""" - result = [] - ldap_group = "cn=blocked_users,dc=example,dc=com" - - output_result, next_order = ldap_group_allow_to_gateway_format(result, ldap_group, deny=True, start_order=1) - - expected = [ - { - "name": "LDAP-DenyGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": True, - "triggers": {"groups": {"has_or": ["cn=blocked_users,dc=example,dc=com"]}}, - "order": 1, - } - ] - - assert output_result == expected - assert next_order == 2 - - def test_appending_to_existing_result(self): - """Test appending to existing result list.""" - existing_mapper = { - "name": "existing-mapper", - "authenticator": -1, - "map_type": "role", - "order": 1, - } - result = [existing_mapper] - ldap_group = "cn=new_group,dc=example,dc=com" - - output_result, next_order = ldap_group_allow_to_gateway_format(result, ldap_group, deny=False, start_order=2) - - assert len(output_result) == 2 - assert output_result[0] == existing_mapper # Original mapper unchanged - assert output_result[1]["name"] == "LDAP-RequireGroup" - assert output_result[1]["order"] == 2 - assert next_order == 3 - - def test_custom_start_order(self): - """Test that custom start_order is respected.""" - result = [] - ldap_group = "cn=test_group,dc=example,dc=com" - - output_result, next_order = ldap_group_allow_to_gateway_format(result, ldap_group, deny=False, start_order=10) - - assert output_result[0]["order"] == 10 - assert next_order == 11 - - def test_require_vs_deny_trigger_differences(self): - """Test the difference between require and deny group triggers.""" - ldap_group = "cn=test_group,dc=example,dc=com" - - # Test require group (deny=False) - require_result, _ = ldap_group_allow_to_gateway_format([], ldap_group, deny=False) - - # Test deny group (deny=True) - deny_result, _ = ldap_group_allow_to_gateway_format([], ldap_group, deny=True) - - # Require group should use has_and - assert require_result[0]["triggers"]["groups"]["has_and"] == ["cn=test_group,dc=example,dc=com"] - assert require_result[0]["revoke"] is False - assert require_result[0]["name"] == "LDAP-RequireGroup" - - # Deny group should use has_or - assert deny_result[0]["triggers"]["groups"]["has_or"] == ["cn=test_group,dc=example,dc=com"] - assert deny_result[0]["revoke"] is True - assert deny_result[0]["name"] == "LDAP-DenyGroup" - - def test_realistic_ldap_dn_format(self): - """Test with realistic LDAP DN format.""" - result = [] - - # Test with require group - require_group = "cn=awx_users,OU=application groups,DC=contoso,DC=com" - output_result, next_order = ldap_group_allow_to_gateway_format(result, require_group, deny=False, start_order=1) - - assert len(output_result) == 1 - assert output_result[0]["triggers"]["groups"]["has_and"] == ["cn=awx_users,OU=application groups,DC=contoso,DC=com"] - assert output_result[0]["name"] == "LDAP-RequireGroup" - assert next_order == 2 - - def test_multiple_sequential_calls(self): - """Test multiple sequential calls to build complex allow mappers.""" - result = [] - - # Add deny group first - result, next_order = ldap_group_allow_to_gateway_format(result, "cn=blocked,dc=example,dc=com", deny=True, start_order=1) - - # Add require group second - result, next_order = ldap_group_allow_to_gateway_format(result, "cn=allowed,dc=example,dc=com", deny=False, start_order=next_order) - - assert len(result) == 2 - - # First mapper should be deny group - assert result[0]["name"] == "LDAP-DenyGroup" - assert result[0]["revoke"] is True - assert result[0]["triggers"]["groups"]["has_or"] == ["cn=blocked,dc=example,dc=com"] - assert result[0]["order"] == 1 - - # Second mapper should be require group - assert result[1]["name"] == "LDAP-RequireGroup" - assert result[1]["revoke"] is False - assert result[1]["triggers"]["groups"]["has_and"] == ["cn=allowed,dc=example,dc=com"] - assert result[1]["order"] == 2 - - assert next_order == 3 - - def test_gateway_format_compliance(self): - """Test that all results comply with Gateway allow mapping format.""" - result = [] - - # Test both deny and require groups - result, _ = ldap_group_allow_to_gateway_format(result, "cn=denied,dc=example,dc=com", deny=True, start_order=1) - result, _ = ldap_group_allow_to_gateway_format(result, "cn=required,dc=example,dc=com", deny=False, start_order=2) - - for mapping in result: - # Required fields per Gateway spec - assert "name" in mapping - assert "authenticator" in mapping - assert "map_type" in mapping - assert "triggers" in mapping - assert "order" in mapping - assert "revoke" in mapping - - # Field types - assert isinstance(mapping["name"], str) - assert isinstance(mapping["authenticator"], int) - assert mapping["map_type"] == "allow" - assert isinstance(mapping["triggers"], dict) - assert isinstance(mapping["order"], int) - assert isinstance(mapping["revoke"], bool) - - # Trigger format validation - assert "groups" in mapping["triggers"] - groups_trigger = mapping["triggers"]["groups"] - - # Should have either has_and or has_or, but not both - has_and = "has_and" in groups_trigger - has_or = "has_or" in groups_trigger - assert has_and != has_or # XOR - exactly one should be true - - if has_and: - assert isinstance(groups_trigger["has_and"], list) - assert len(groups_trigger["has_and"]) == 1 - if has_or: - assert isinstance(groups_trigger["has_or"], list) - assert len(groups_trigger["has_or"]) == 1 - - def test_original_result_not_modified_when_none(self): - """Test that original result list is not modified when ldap_group is None.""" - original_result = [{"original": "mapper"}] - result_copy = original_result.copy() - - output_result, _ = ldap_group_allow_to_gateway_format(original_result, None, deny=False) - - # Original list should be unchanged - assert original_result == result_copy - # Output should be the same reference - assert output_result is original_result - - def test_empty_string_group(self): - """Test handling of empty string group.""" - result = [] - - output_result, next_order = ldap_group_allow_to_gateway_format(result, "", deny=False, start_order=1) - - # Should still create a mapper even with empty string - assert len(output_result) == 1 - assert output_result[0]["triggers"]["groups"]["has_and"] == [""] - assert next_order == 2 - - -# Parametrized tests for ldap_group_allow_to_gateway_format -@pytest.mark.parametrize( - "ldap_group,deny,expected_name,expected_revoke,expected_trigger_type", - [ - ("cn=test,dc=example,dc=com", True, "LDAP-DenyGroup", True, "has_or"), - ("cn=test,dc=example,dc=com", False, "LDAP-RequireGroup", False, "has_and"), - ("cn=users,ou=groups,dc=company,dc=com", True, "LDAP-DenyGroup", True, "has_or"), - ("cn=users,ou=groups,dc=company,dc=com", False, "LDAP-RequireGroup", False, "has_and"), - ], -) -def test_ldap_group_parametrized(ldap_group, deny, expected_name, expected_revoke, expected_trigger_type): - """Parametrized test for various LDAP group configurations.""" - result = [] - - output_result, next_order = ldap_group_allow_to_gateway_format(result, ldap_group, deny=deny, start_order=1) - - assert len(output_result) == 1 - mapper = output_result[0] - - assert mapper["name"] == expected_name - assert mapper["revoke"] == expected_revoke - assert expected_trigger_type in mapper["triggers"]["groups"] - assert mapper["triggers"]["groups"][expected_trigger_type] == [ldap_group] - assert next_order == 2 - - -def test_realistic_awx_ldap_migration_scenario(): - """Test realistic scenario from AWX LDAP migration.""" - result = [] - - # Simulate AWX LDAP configuration with both REQUIRE_GROUP and DENY_GROUP - deny_group = "cn=blocked_users,OU=blocked groups,DC=contoso,DC=com" - require_group = "cn=awx_users,OU=application groups,DC=contoso,DC=com" - - # Add deny group first (as in the migrator) - result, next_order = ldap_group_allow_to_gateway_format(result, deny_group, deny=True, start_order=1) - - # Add require group second - result, next_order = ldap_group_allow_to_gateway_format(result, require_group, deny=False, start_order=next_order) - - # Should have 2 allow mappers - assert len(result) == 2 - - # Verify deny group mapper - deny_mapper = result[0] - assert deny_mapper["name"] == "LDAP-DenyGroup" - assert deny_mapper["map_type"] == "allow" - assert deny_mapper["revoke"] is True - assert deny_mapper["triggers"]["groups"]["has_or"] == [deny_group] - assert deny_mapper["order"] == 1 - - # Verify require group mapper - require_mapper = result[1] - assert require_mapper["name"] == "LDAP-RequireGroup" - assert require_mapper["map_type"] == "allow" - assert require_mapper["revoke"] is False - assert require_mapper["triggers"]["groups"]["has_and"] == [require_group] - assert require_mapper["order"] == 2 - - assert next_order == 3 diff --git a/awx/main/utils/gateway_client.py b/awx/main/utils/gateway_client.py deleted file mode 100644 index dad1641553..0000000000 --- a/awx/main/utils/gateway_client.py +++ /dev/null @@ -1,511 +0,0 @@ -""" -Gateway API client for AAP Gateway interactions. - -This module provides a client class to interact with the AAP Gateway REST API, -specifically for creating authenticators and mapping configurations. -""" - -import requests -import logging -from typing import Dict, List, Optional, Any -from urllib.parse import urljoin - - -logger = logging.getLogger(__name__) - - -class GatewayAPIError(Exception): - """Exception raised for Gateway API errors.""" - - def __init__(self, message: str, status_code: Optional[int] = None, response_data: Optional[Dict] = None): - self.message = message - self.status_code = status_code - self.response_data = response_data - super().__init__(self.message) - - -class GatewayClient: - """Client for AAP Gateway REST API interactions.""" - - def __init__(self, base_url: str, username: str, password: str, skip_verify: bool = False, skip_session_init: bool = False, command=None): - """Initialize Gateway client. - - Args: - base_url: Base URL of the AAP Gateway instance - username: Username for authentication - password: Password for authentication - skip_verify: Skip SSL certificate verification - skip_session_init: Skip initializing the session. Only set to True if you are using a base class that doesn't need the initialization of the session. - command: The command object. This is used to write output to the console. - """ - self.base_url = base_url.rstrip('/') - self.username = username - self.password = password - self.skip_verify = skip_verify - self.command = command - self.session_was_not_initialized = skip_session_init - - # Initialize session - if not skip_session_init: - self.session = requests.Session() - - # Configure SSL verification - if skip_verify: - self.session.verify = False - # Disable SSL warnings when verification is disabled - import urllib3 - - urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) - - # Set default headers - self.session.headers.update( - { - 'User-Agent': 'AWX-Gateway-Migration-Client/1.0', - 'Accept': 'application/json', - 'Content-Type': 'application/json', - } - ) - else: - self.session = None - - # Authentication state - self._authenticated = False - - def authenticate(self) -> bool: - """Authenticate with the Gateway using HTTP Basic Authentication. - - Returns: - bool: True if authentication successful, False otherwise - - Raises: - GatewayAPIError: If authentication fails - """ - try: - # Set up HTTP Basic Authentication - from requests.auth import HTTPBasicAuth - - self.session.auth = HTTPBasicAuth(self.username, self.password) - - # Test authentication by making a simple request to the API - test_url = urljoin(self.base_url, '/api/gateway/v1/authenticators/') - - response = self.session.get(test_url) - - if response.status_code in [200, 401]: # 401 means auth is working but might need permissions - self._authenticated = True - logger.info("Successfully authenticated with Gateway using Basic Auth") - return True - else: - error_msg = f"Authentication test failed with status {response.status_code}" - try: - error_data = response.json() - error_msg += f": {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f": {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Network error during authentication: {str(e)}") - - def _ensure_authenticated(self): - """Ensure the client is authenticated, authenticate if needed.""" - if not self._authenticated: - self.authenticate() - - def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None, params: Optional[Dict] = None) -> requests.Response: - """Make an authenticated request to the Gateway API. - - Args: - method: HTTP method (GET, POST, PUT, DELETE, etc.) - endpoint: API endpoint (without base URL) - data: JSON data to send in request body - params: Query parameters - - Returns: - requests.Response: The response object - - Raises: - GatewayAPIError: If request fails - """ - self._ensure_authenticated() - - url = urljoin(self.base_url, endpoint.lstrip('/')) - - try: - response = self.session.request(method=method.upper(), url=url, json=data, params=params) - - # Log request details - logger.debug(f"{method.upper()} {url} - Status: {response.status_code}") - - return response - - except requests.RequestException as e: - raise GatewayAPIError(f"Request failed: {str(e)}") - - def create_authenticator(self, authenticator_config: Dict[str, Any]) -> Dict[str, Any]: - """Create a new authenticator in Gateway. - - Args: - authenticator_config: Authenticator configuration dictionary - - Returns: - dict: Created authenticator data - - Raises: - GatewayAPIError: If creation fails - """ - endpoint = '/api/gateway/v1/authenticators/' - - try: - response = self._make_request('POST', endpoint, data=authenticator_config) - - if response.status_code == 201: - result = response.json() - logger.info(f"Successfully created authenticator: {result.get('name', 'Unknown')}") - return result - else: - error_msg = f"Failed to create authenticator. Status: {response.status_code}" - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to create authenticator: {str(e)}") - - def update_authenticator(self, authenticator_id: int, authenticator_config: Dict[str, Any]) -> Dict[str, Any]: - """Update an existing authenticator in Gateway. - - Args: - authenticator_id: ID of the authenticator to update - authenticator_config: Authenticator configuration dictionary - - Returns: - dict: Updated authenticator data - - Raises: - GatewayAPIError: If update fails - """ - endpoint = f'/api/gateway/v1/authenticators/{authenticator_id}/' - - try: - response = self._make_request('PATCH', endpoint, data=authenticator_config) - - if response.status_code == 200: - result = response.json() - logger.info(f"Successfully updated authenticator: {result.get('name', 'Unknown')}") - return result - else: - error_msg = f"Failed to update authenticator. Status: {response.status_code}" - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to update authenticator: {str(e)}") - - def create_authenticator_map(self, authenticator_id: int, mapper_config: Dict[str, Any]) -> Dict[str, Any]: - """Create a new authenticator map in Gateway. - - Args: - authenticator_id: ID of the authenticator to create map for - mapper_config: Mapper configuration dictionary - - Returns: - dict: Created mapper data - - Raises: - GatewayAPIError: If creation fails - """ - endpoint = '/api/gateway/v1/authenticator_maps/' - - try: - - response = self._make_request('POST', endpoint, data=mapper_config) - - if response.status_code == 201: - result = response.json() - logger.info(f"Successfully created authenticator map: {result.get('name', 'Unknown')}") - return result - else: - error_msg = f"Failed to create authenticator map. Status: {response.status_code}" - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to create authenticator map: {str(e)}") - - def update_authenticator_map(self, mapper_id: int, mapper_config: Dict[str, Any]) -> Dict[str, Any]: - """Update an existing authenticator map in Gateway. - - Args: - mapper_id: ID of the authenticator map to update - mapper_config: Mapper configuration dictionary - - Returns: - dict: Updated mapper data - - Raises: - GatewayAPIError: If update fails - """ - endpoint = f'/api/gateway/v1/authenticator_maps/{mapper_id}/' - - try: - response = self._make_request('PATCH', endpoint, data=mapper_config) - - if response.status_code == 200: - result = response.json() - logger.info(f"Successfully updated authenticator map: {result.get('name', 'Unknown')}") - return result - else: - error_msg = f"Failed to update authenticator map. Status: {response.status_code}" - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to update authenticator map: {str(e)}") - - def get_authenticators(self, params: Optional[Dict] = None) -> List[Dict[str, Any]]: - """Get list of authenticators from Gateway. - - Args: - params: Optional query parameters - - Returns: - list: List of authenticator configurations - - Raises: - GatewayAPIError: If request fails - """ - endpoint = '/api/gateway/v1/authenticators/' - - try: - response = self._make_request('GET', endpoint, params=params) - - if response.status_code == 200: - result = response.json() - # Handle paginated response - if isinstance(result, dict) and 'results' in result: - return result['results'] - return result - else: - error_msg = f"Failed to get authenticators. Status: {response.status_code}" - raise GatewayAPIError(error_msg, response.status_code) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to get authenticators: {str(e)}") - - def get_authenticator_by_slug(self, slug: str) -> Optional[Dict[str, Any]]: - """Get a specific authenticator by slug. - - Args: - slug: The authenticator slug to search for - - Returns: - dict: The authenticator data if found, None otherwise - - Raises: - GatewayAPIError: If request fails - """ - try: - # Use query parameter to filter by slug - more efficient than getting all - authenticators = self.get_authenticators(params={'slug': slug}) - - # Return the first match (slugs should be unique) - if authenticators: - return authenticators[0] - return None - - except GatewayAPIError as e: - # Re-raise Gateway API errors - raise e - except Exception as e: - raise GatewayAPIError(f"Failed to get authenticator by slug: {str(e)}") - - def get_authenticator_maps(self, authenticator_id: int) -> List[Dict[str, Any]]: - """Get list of maps for a specific authenticator. - - Args: - authenticator_id: ID of the authenticator - - Returns: - list: List of authenticator maps - - Raises: - GatewayAPIError: If request fails - """ - endpoint = f'/api/gateway/v1/authenticators/{authenticator_id}/authenticator_maps/' - - try: - response = self._make_request('GET', endpoint) - - if response.status_code == 200: - result = response.json() - # Handle paginated response - if isinstance(result, dict) and 'results' in result: - return result['results'] - return result - else: - error_msg = f"Failed to get authenticator maps. Status: {response.status_code}" - raise GatewayAPIError(error_msg, response.status_code) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to get authenticator maps: {str(e)}") - - def create_github_authenticator( - self, name: str, client_id: str, client_secret: str, enabled: bool = True, create_objects: bool = False, remove_users: bool = False - ) -> Dict[str, Any]: - """Create a GitHub authenticator with the specified configuration. - - Args: - name: Name for the authenticator - client_id: GitHub OAuth App Client ID - client_secret: GitHub OAuth App Client Secret - enabled: Whether authenticator should be enabled - create_objects: Whether to create users/orgs/teams automatically - remove_users: Whether to remove users when they lose access - - Returns: - dict: Created authenticator data - """ - config = { - "name": name, - "type": "ansible_base.authentication.authenticator_plugins.github", - "enabled": enabled, - "create_objects": create_objects, - "remove_users": remove_users, - "configuration": {"KEY": client_id, "SECRET": client_secret}, - } - - return self.create_authenticator(config) - - def update_gateway_setting(self, setting_name: str, setting_value: Any) -> Dict[str, Any]: - """Update a Gateway setting via the settings API. - - Args: - setting_name: Name of the setting to update - setting_value: Value to set for the setting - - Returns: - dict: Upon successful update, well formed responses are returned, otherwise the original payload is returned. - - Raises: - GatewayAPIError: If update fails, anything other than a 200 or 204 response code. - """ - endpoint = '/api/gateway/v1/settings/all/' - - # Create the JSON payload with the setting name and value - payload = {setting_name: setting_value} - - try: - response = self._make_request('PUT', endpoint, data=payload) - - if response.status_code in [200, 204]: - logger.info(f"Successfully updated Gateway setting: {setting_name}") - # Return the response data if available, otherwise return the payload - if response.content: - try: - return response.json() - except requests.exceptions.JSONDecodeError: - return payload - return payload - else: - error_msg = f"Failed to update Gateway setting. Status: {response.status_code}" - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, response.json() if response.content else None) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to update Gateway setting: {str(e)}") - - def get_gateway_setting(self, setting_name: str) -> Any: - """Get a Gateway setting value via the settings API. - - Args: - setting_name: Name of the setting to retrieve - - Returns: - Any: The value of the setting, or None if not found - - Raises: - GatewayAPIError: If request fails - """ - endpoint = '/api/gateway/v1/settings/all/' - - try: - response = self._make_request('GET', endpoint) - - if response.status_code == 200: - settings_data = response.json() - logger.info("Successfully retrieved Gateway settings") - - # Return the specific setting value or None if not found - return settings_data.get(setting_name) - else: - error_msg = f"Failed to get Gateway settings from '{endpoint}' for '{setting_name}'. Status: {response.status_code}" - error_data = response.text - try: - error_data = response.json() - error_msg += f", Error: {error_data}" - except requests.exceptions.JSONDecodeError: - error_msg += f", Response: {response.text}" - - raise GatewayAPIError(error_msg, response.status_code, error_data) - - except requests.RequestException as e: - raise GatewayAPIError(f"Failed to get Gateway settings from '{endpoint}' for '{setting_name}'. Unexpected Exception - Error: {str(e)}") - - def get_base_url(self) -> str: - """Get the base URL of the Gateway instance. - - Returns: - str: The base URL of the Gateway instance - """ - return self.base_url - - def close(self): - """Close the session and clean up resources.""" - if self.session: - self.session.close() - - def __enter__(self): - """Context manager entry.""" - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - """Context manager exit.""" - self.close() - - def _write_output(self, message, style=None): - """Write output message if command is available.""" - if self.command: - if style == 'success': - self.command.stdout.write(self.command.style.SUCCESS(message)) - elif style == 'warning': - self.command.stdout.write(self.command.style.WARNING(message)) - elif style == 'error': - self.command.stdout.write(self.command.style.ERROR(message)) - else: - self.command.stdout.write(message) diff --git a/awx/main/utils/gateway_client_svc_token.py b/awx/main/utils/gateway_client_svc_token.py deleted file mode 100644 index 1a7cd8fcac..0000000000 --- a/awx/main/utils/gateway_client_svc_token.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Gateway API client for AAP Gateway interactions with Service Tokens. - -This module provides a client class to interact with the AAP Gateway REST API, -specifically for creating authenticators and mapping configurations. -""" - -import requests -import logging -from typing import Dict, Optional -from awx.main.utils.gateway_client import GatewayClient, GatewayAPIError - - -logger = logging.getLogger(__name__) - - -class GatewayClientSVCToken(GatewayClient): - """Client for AAP Gateway REST API interactions.""" - - def __init__(self, resource_api_client=None, command=None): - """Initialize Gateway client. - - Args: - resource_api_client: Resource API Client for Gateway leveraging service tokens - """ - super().__init__( - base_url=resource_api_client.base_url, - username=resource_api_client.jwt_user_id, - password="required-in-GatewayClient-authenticate()-but-unused-by-GatewayClientSVCToken", - skip_verify=(not resource_api_client.verify_https), - skip_session_init=True, - command=command, - ) - self.resource_api_client = resource_api_client - # Authentication state - self._authenticated = True - - def authenticate(self) -> bool: - """Overload the base class method to always return True. - - Returns: - bool: True always - """ - - return True - - def _ensure_authenticated(self): - """Refresh JWT service token""" - self.resource_api_client.refresh_jwt() - - def _make_request(self, method: str, endpoint: str, data: Optional[Dict] = None, params: Optional[Dict] = None) -> requests.Response: - """Make a service token authenticated request to the Gateway API. - - Args: - method: HTTP method (GET, POST, PUT, DELETE, etc.) - endpoint: API endpoint (without base URL) - data: JSON data to send in request body - params: Query parameters - - Returns: - requests.Response: The response object - - Raises: - GatewayAPIError: If request fails - """ - self._ensure_authenticated() - - try: - response = self.resource_api_client._make_request(method=method, path=endpoint, data=data, params=params) - - # Log request details - logger.debug(f"{method.upper()} {self.base_url}{endpoint} - Status: {response.status_code}") - - return response - - except requests.RequestException as e: - raise GatewayAPIError(f"Request failed: {str(e)}") diff --git a/awx/main/utils/gateway_mapping.py b/awx/main/utils/gateway_mapping.py deleted file mode 100644 index 0d6bd2bd4e..0000000000 --- a/awx/main/utils/gateway_mapping.py +++ /dev/null @@ -1,361 +0,0 @@ -""" -Gateway mapping conversion utilities. - -This module contains functions to convert AWX authentication mappings -(organization and team mappings) to AAP Gateway format. -""" - -import re -from typing import cast, Any, Literal, Pattern, Union - -email_regex = re.compile(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$") - - -def truncate_name(name: str, max_length: int = 128) -> str: - """Truncate a name to the specified maximum length.""" - if len(name) <= max_length: - return name - return name[:max_length] - - -def build_truncated_name(org_name: str, entity_name: str, trigger_name: str, max_component_length: int = 40) -> str: - """Build a name by truncating each component individually and joining with ' - '.""" - truncated_org = truncate_name(org_name, max_component_length) - truncated_entity = truncate_name(entity_name, max_component_length) - truncated_trigger = truncate_name(trigger_name, max_component_length) - return f"{truncated_org} - {truncated_entity} {truncated_trigger}" - - -def pattern_to_slash_format(pattern: Any) -> str: - """Convert a re.Pattern object to /pattern/flags format.""" - if not isinstance(pattern, re.Pattern): - return str(pattern) - - flags_str = "" - if pattern.flags & re.IGNORECASE: - flags_str += "i" - if pattern.flags & re.MULTILINE: - flags_str += "m" - if pattern.flags & re.DOTALL: - flags_str += "s" - if pattern.flags & re.VERBOSE: - flags_str += "x" - - return f"/{pattern.pattern}/{flags_str}" - - -def process_ldap_user_list( - groups: Union[None, str, bool, list[Union[None, str, bool]]], -) -> list[dict[str, Any]]: - if not isinstance(groups, list): - groups = [groups] - - # Type cast to help mypy understand the type after conversion - groups_list: list[Union[str, bool, None]] = cast(list[Union[str, bool, None]], groups) - - triggers = [] - if groups_list == [None]: - # A None value means we shouldn't update whatever this is based on LDAP values - pass - elif groups_list == []: - # Empty list means no triggers should be created - pass - elif groups_list == [True]: - triggers.append({"name": "Always Allow", "trigger": {"always": {}}}) - elif groups_list == [False]: - triggers.append( - { - "name": "Never Allow", - "trigger": {"never": {}}, - } - ) - else: - triggers.append({"name": "Match User Groups", "trigger": {"groups": {"has_or": groups_list}}}) - return triggers - - -def process_sso_user_list( - users: Union[str, bool, Pattern[str], list[Union[str, bool, Pattern[str]]]], email_attr: str = 'email', username_attr: str = 'username' -) -> dict[str, Union[str, dict[str, dict[str, Union[str, list[str]]]]]]: - """Process SSO user list and return a single consolidated trigger instead of multiple separate ones.""" - if not isinstance(users, list): - users = [users] - - # Type cast to help mypy understand the type after conversion - user_list: list[Union[str, bool, Pattern[str]]] = cast(list[Union[str, bool, Pattern[str]]], users) - - if user_list == ["false"] or user_list == [False]: - return {"name": "Never Allow", "trigger": {"never": {}}} - elif user_list == ["true"] or user_list == [True]: - return {"name": "Always Allow", "trigger": {"always": {}}} - else: - # Group users by type - emails = [] - usernames = [] - regexes_username = [] - regexes_email = [] - - for user_or_email in user_list: - if isinstance(user_or_email, re.Pattern): - pattern_str = pattern_to_slash_format(user_or_email) - regexes_username.append(pattern_str) - regexes_email.append(pattern_str) - elif isinstance(user_or_email, str): - if email_regex.match(user_or_email): - emails.append(user_or_email) - else: - usernames.append(user_or_email) - else: - # Convert other objects to string and treat as both - str_val = str(user_or_email) - usernames.append(str_val) - emails.append(str_val) - - # Build consolidated trigger - attributes = {"join_condition": "or"} - - if emails: - if len(emails) == 1: - attributes[email_attr] = {"equals": emails[0]} - else: - attributes[email_attr] = {"in": emails} - - if usernames: - if len(usernames) == 1: - attributes[username_attr] = {"equals": usernames[0]} - else: - attributes[username_attr] = {"in": usernames} - - # For regex patterns, we need to create separate matches conditions since there's no matches_or - for i, pattern in enumerate(regexes_username): - pattern_key = f"{username_attr}_pattern_{i}" if len(regexes_username) > 1 else username_attr - if pattern_key not in attributes: - attributes[pattern_key] = {} - attributes[pattern_key]["matches"] = pattern - - for i, pattern in enumerate(regexes_email): - pattern_key = f"{email_attr}_pattern_{i}" if len(regexes_email) > 1 else email_attr - if pattern_key not in attributes: - attributes[pattern_key] = {} - attributes[pattern_key]["matches"] = pattern - - # Create a deterministic, concise name based on trigger types and counts - name_parts = [] - if emails: - name_parts.append(f"E:{len(emails)}") - if usernames: - name_parts.append(f"U:{len(usernames)}") - if regexes_username: - name_parts.append(f"UP:{len(regexes_username)}") - if regexes_email: - name_parts.append(f"EP:{len(regexes_email)}") - - name = " ".join(name_parts) if name_parts else "Mixed Rules" - - return {"name": name, "trigger": {"attributes": attributes}} - - -def team_map_to_gateway_format(team_map, start_order=1, email_attr: str = 'email', username_attr: str = 'username', auth_type: Literal['sso', 'ldap'] = 'sso'): - """Convert AWX team mapping to Gateway authenticator format. - - Args: - team_map: The SOCIAL_AUTH_*_TEAM_MAP setting value - start_order: Starting order value for the mappers - email_attr: The attribute representing the email - username_attr: The attribute representing the username - - Returns: - tuple: (List of Gateway-compatible team mappers, next_order) - """ - if team_map is None: - return [], start_order - - result = [] - order = start_order - - for team_name in team_map.keys(): - team = team_map[team_name] - # TODO: Confirm that if we have None with remove we still won't remove - if team['users'] is None: - continue - - # Get the organization name - organization_name = team.get('organization', 'Unknown') - - # Check for remove flag - revoke = team.get('remove', False) - - if auth_type == 'ldap': - triggers = process_ldap_user_list(team['users']) - for trigger in triggers: - result.append( - { - "name": build_truncated_name(organization_name, team_name, trigger['name']), - "map_type": "team", - "order": order, - "authenticator": -1, # Will be updated when creating the mapper - "triggers": trigger['trigger'], - "organization": organization_name, - "team": team_name, - "role": "Team Member", # Gateway team member role - "revoke": revoke, - } - ) - order += 1 - - if auth_type == 'sso': - trigger = process_sso_user_list(team['users'], email_attr=email_attr, username_attr=username_attr) - result.append( - { - "name": build_truncated_name(organization_name, team_name, trigger['name']), - "map_type": "team", - "order": order, - "authenticator": -1, # Will be updated when creating the mapper - "triggers": trigger['trigger'], - "organization": organization_name, - "team": team_name, - "role": "Team Member", # Gateway team member role - "revoke": revoke, - } - ) - order += 1 - - return result, order - - -def org_map_to_gateway_format(org_map, start_order=1, email_attr: str = 'email', username_attr: str = 'username', auth_type: Literal['sso', 'ldap'] = 'sso'): - """Convert AWX organization mapping to Gateway authenticator format. - - Args: - org_map: The SOCIAL_AUTH_*_ORGANIZATION_MAP setting value - start_order: Starting order value for the mappers - email_attr: The attribute representing the email - username_attr: The attribute representing the username - - Returns: - tuple: (List of Gateway-compatible organization mappers, next_order) - """ - if org_map is None: - return [], start_order - - result = [] - order = start_order - - for organization_name in org_map.keys(): - organization = org_map[organization_name] - for user_type in ['admins', 'users']: - if organization.get(user_type, None) is None: - # TODO: Confirm that if we have None with remove we still won't remove - continue - - # Get the permission type - permission_type = user_type.title() - - # Map AWX admin/users to appropriate Gateway organization roles - role = "Organization Admin" if user_type == "admins" else "Organization Member" - - # Check for remove flags - revoke = False - if organization.get(f"remove_{user_type}"): - revoke = True - - if auth_type == 'ldap': - triggers = process_ldap_user_list(organization[user_type]) - for trigger in triggers: - result.append( - { - "name": build_truncated_name(organization_name, permission_type, trigger['name']), - "map_type": "organization", - "order": order, - "authenticator": -1, # Will be updated when creating the mapper - "triggers": trigger['trigger'], - "organization": organization_name, - "team": None, # Organization-level mapping, not team-specific - "role": role, - "revoke": revoke, - } - ) - order += 1 - - if auth_type == 'sso': - trigger = process_sso_user_list(organization[user_type], email_attr=email_attr, username_attr=username_attr) - result.append( - { - "name": build_truncated_name(organization_name, permission_type, trigger['name']), - "map_type": "organization", - "order": order, - "authenticator": -1, # Will be updated when creating the mapper - "triggers": trigger['trigger'], - "organization": organization_name, - "team": None, # Organization-level mapping, not team-specific - "role": role, - "revoke": revoke, - } - ) - order += 1 - - return result, order - - -def role_map_to_gateway_format(role_map, start_order=1): - """Convert AWX role mapping to Gateway authenticator format. - - Args: - role_map: An LDAP or SAML role mapping - start_order: Starting order value for the mappers - - Returns: - tuple: (List of Gateway-compatible organization mappers, next_order) - """ - if role_map is None: - return [], start_order - - result = [] - order = start_order - - for flag in role_map: - groups = role_map[flag] - if type(groups) is str: - groups = [groups] - - if flag == 'is_superuser': - # Gateway has a special map_type for superusers - result.append( - { - "name": f"{flag} - role", - "authenticator": -1, - "revoke": True, - "map_type": flag, - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": groups, - } - }, - "order": order, - } - ) - elif flag == 'is_system_auditor': - # roles other than superuser must be represented as a generic role mapper - result.append( - { - "name": f"{flag} - role", - "authenticator": -1, - "revoke": True, - "map_type": "role", - "role": "Platform Auditor", - "team": None, - "organization": None, - "triggers": { - "groups": { - "has_or": groups, - } - }, - "order": order, - } - ) - - order += 1 - - return result, order diff --git a/awx/settings/development_defaults.py b/awx/settings/development_defaults.py index bb726cb372..9725b0abb7 100644 --- a/awx/settings/development_defaults.py +++ b/awx/settings/development_defaults.py @@ -73,4 +73,5 @@ AWX_DISABLE_TASK_MANAGERS = False def set_dev_flags(settings): defaults_flags = settings.get("FLAGS", {}) defaults_flags['FEATURE_INDIRECT_NODE_COUNTING_ENABLED'] = [{'condition': 'boolean', 'value': True}] + defaults_flags['FEATURE_DISPATCHERD_ENABLED'] = [{'condition': 'boolean', 'value': True}] return {'FLAGS': defaults_flags} diff --git a/awx/settings/production_defaults.py b/awx/settings/production_defaults.py index 5599b81753..35bebc1f7b 100644 --- a/awx/settings/production_defaults.py +++ b/awx/settings/production_defaults.py @@ -23,8 +23,13 @@ ALLOWED_HOSTS = [] # only used for deprecated fields and management commands for them BASE_VENV_PATH = os.path.realpath("/var/lib/awx/venv") +# Switch to a writable location for the dispatcher sockfile location +DISPATCHERD_DEBUGGING_SOCKFILE = os.path.realpath('/var/run/tower/dispatcherd.sock') + # Very important that this is editable (not read_only) in the API AWX_ISOLATION_SHOW_PATHS = [ '/etc/pki/ca-trust:/etc/pki/ca-trust:O', '/usr/share/pki:/usr/share/pki:O', ] + +del os diff --git a/awx/sso/backends.py b/awx/sso/backends.py deleted file mode 100644 index 572afc3ef0..0000000000 --- a/awx/sso/backends.py +++ /dev/null @@ -1,469 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved. - -# Python -from collections import OrderedDict -import logging -import uuid - -import ldap - -# Django -from django.dispatch import receiver -from django.contrib.auth.models import User -from django.conf import settings as django_settings -from django.core.signals import setting_changed -from django.utils.encoding import force_str -from django.http import HttpResponse - -# django-auth-ldap -from django_auth_ldap.backend import LDAPSettings as BaseLDAPSettings -from django_auth_ldap.backend import LDAPBackend as BaseLDAPBackend -from django_auth_ldap.backend import populate_user -from django.core.exceptions import ImproperlyConfigured - -# radiusauth -from radiusauth.backends import RADIUSBackend as BaseRADIUSBackend - -# tacacs+ auth -import tacacs_plus - -# social -from social_core.backends.saml import OID_USERID -from social_core.backends.saml import SAMLAuth as BaseSAMLAuth -from social_core.backends.saml import SAMLIdentityProvider as BaseSAMLIdentityProvider - -# Ansible Tower -from awx.sso.models import UserEnterpriseAuth -from awx.sso.common import create_org_and_teams, reconcile_users_org_team_mappings - -logger = logging.getLogger('awx.sso.backends') - - -class LDAPSettings(BaseLDAPSettings): - defaults = dict(list(BaseLDAPSettings.defaults.items()) + list({'ORGANIZATION_MAP': {}, 'TEAM_MAP': {}, 'GROUP_TYPE_PARAMS': {}}.items())) - - def __init__(self, prefix='AUTH_LDAP_', defaults={}): - super(LDAPSettings, self).__init__(prefix, defaults) - - # If a DB-backed setting is specified that wipes out the - # OPT_NETWORK_TIMEOUT, fall back to a sane default - if ldap.OPT_NETWORK_TIMEOUT not in getattr(self, 'CONNECTION_OPTIONS', {}): - options = getattr(self, 'CONNECTION_OPTIONS', {}) - options[ldap.OPT_NETWORK_TIMEOUT] = 30 - self.CONNECTION_OPTIONS = options - - # when specifying `.set_option()` calls for TLS in python-ldap, the - # *order* in which you invoke them *matters*, particularly in Python3, - # where dictionary insertion order is persisted - # - # specifically, it is *critical* that `ldap.OPT_X_TLS_NEWCTX` be set *last* - # this manual sorting puts `OPT_X_TLS_NEWCTX` *after* other TLS-related - # options - # - # see: https://github.com/python-ldap/python-ldap/issues/55 - newctx_option = self.CONNECTION_OPTIONS.pop(ldap.OPT_X_TLS_NEWCTX, None) - self.CONNECTION_OPTIONS = OrderedDict(self.CONNECTION_OPTIONS) - if newctx_option is not None: - self.CONNECTION_OPTIONS[ldap.OPT_X_TLS_NEWCTX] = newctx_option - - -class LDAPBackend(BaseLDAPBackend): - """ - Custom LDAP backend for AWX. - """ - - settings_prefix = 'AUTH_LDAP_' - - def __init__(self, *args, **kwargs): - self._dispatch_uid = uuid.uuid4() - super(LDAPBackend, self).__init__(*args, **kwargs) - setting_changed.connect(self._on_setting_changed, dispatch_uid=self._dispatch_uid) - - def _on_setting_changed(self, sender, **kwargs): - # If any AUTH_LDAP_* setting changes, force settings to be reloaded for - # this backend instance. - if kwargs.get('setting', '').startswith(self.settings_prefix): - self._settings = None - - def _get_settings(self): - if self._settings is None: - self._settings = LDAPSettings(self.settings_prefix) - return self._settings - - def _set_settings(self, settings): - self._settings = settings - - settings = property(_get_settings, _set_settings) - - def authenticate(self, request, username, password): - if self.settings.START_TLS and ldap.OPT_X_TLS_REQUIRE_CERT in self.settings.CONNECTION_OPTIONS: - # with python-ldap, if you want to set connection-specific TLS - # parameters, you must also specify OPT_X_TLS_NEWCTX = 0 - # see: https://stackoverflow.com/a/29722445 - # see: https://stackoverflow.com/a/38136255 - self.settings.CONNECTION_OPTIONS[ldap.OPT_X_TLS_NEWCTX] = 0 - - if not self.settings.SERVER_URI: - return None - try: - user = User.objects.get(username=username) - if user and (not user.profile or not user.profile.ldap_dn): - return None - except User.DoesNotExist: - pass - - try: - for setting_name, type_ in [('GROUP_SEARCH', 'LDAPSearch'), ('GROUP_TYPE', 'LDAPGroupType')]: - if getattr(self.settings, setting_name) is None: - raise ImproperlyConfigured("{} must be an {} instance.".format(setting_name, type_)) - ldap_user = super(LDAPBackend, self).authenticate(request, username, password) - # If we have an LDAP user and that user we found has an ldap_user internal object and that object has a bound connection - # Then we can try and force an unbind to close the sticky connection - if ldap_user and ldap_user.ldap_user and ldap_user.ldap_user._connection_bound: - logger.debug("Forcing LDAP connection to close") - try: - ldap_user.ldap_user._connection.unbind_s() - ldap_user.ldap_user._connection_bound = False - except Exception: - logger.exception(f"Got unexpected LDAP exception when forcing LDAP disconnect for user {ldap_user}, login will still proceed") - return ldap_user - except Exception: - logger.exception("Encountered an error authenticating to LDAP") - return None - - def get_user(self, user_id): - if not self.settings.SERVER_URI: - return None - return super(LDAPBackend, self).get_user(user_id) - - # Disable any LDAP based authorization / permissions checking. - - def has_perm(self, user, perm, obj=None): - return False - - def has_module_perms(self, user, app_label): - return False - - def get_all_permissions(self, user, obj=None): - return set() - - def get_group_permissions(self, user, obj=None): - return set() - - -class LDAPBackend1(LDAPBackend): - settings_prefix = 'AUTH_LDAP_1_' - - -class LDAPBackend2(LDAPBackend): - settings_prefix = 'AUTH_LDAP_2_' - - -class LDAPBackend3(LDAPBackend): - settings_prefix = 'AUTH_LDAP_3_' - - -class LDAPBackend4(LDAPBackend): - settings_prefix = 'AUTH_LDAP_4_' - - -class LDAPBackend5(LDAPBackend): - settings_prefix = 'AUTH_LDAP_5_' - - -def _decorate_enterprise_user(user, provider): - user.set_unusable_password() - user.save() - enterprise_auth, _ = UserEnterpriseAuth.objects.get_or_create(user=user, provider=provider) - return enterprise_auth - - -def _get_or_set_enterprise_user(username, password, provider): - created = False - try: - user = User.objects.prefetch_related('enterprise_auth').get(username=username) - except User.DoesNotExist: - user = User(username=username) - enterprise_auth = _decorate_enterprise_user(user, provider) - logger.debug("Created enterprise user %s via %s backend." % (username, enterprise_auth.get_provider_display())) - created = True - if created or user.is_in_enterprise_category(provider): - return user - logger.warning("Enterprise user %s already defined in Tower." % username) - - -class RADIUSBackend(BaseRADIUSBackend): - """ - Custom Radius backend to verify license status - """ - - def authenticate(self, request, username, password): - if not django_settings.RADIUS_SERVER: - return None - return super(RADIUSBackend, self).authenticate(request, username, password) - - def get_user(self, user_id): - if not django_settings.RADIUS_SERVER: - return None - user = super(RADIUSBackend, self).get_user(user_id) - if not user.has_usable_password(): - return user - - def get_django_user(self, username, password=None, groups=[], is_staff=False, is_superuser=False): - return _get_or_set_enterprise_user(force_str(username), force_str(password), 'radius') - - -class TACACSPlusBackend(object): - """ - Custom TACACS+ auth backend for AWX - """ - - def authenticate(self, request, username, password): - if not django_settings.TACACSPLUS_HOST: - return None - try: - # Upstream TACACS+ client does not accept non-string, so convert if needed. - tacacs_client = tacacs_plus.TACACSClient( - django_settings.TACACSPLUS_HOST, - django_settings.TACACSPLUS_PORT, - django_settings.TACACSPLUS_SECRET, - timeout=django_settings.TACACSPLUS_SESSION_TIMEOUT, - ) - auth_kwargs = {'authen_type': tacacs_plus.TAC_PLUS_AUTHEN_TYPES[django_settings.TACACSPLUS_AUTH_PROTOCOL]} - if django_settings.TACACSPLUS_AUTH_PROTOCOL: - client_ip = self._get_client_ip(request) - if client_ip: - auth_kwargs['rem_addr'] = client_ip - auth = tacacs_client.authenticate(username, password, **auth_kwargs) - except Exception as e: - logger.exception("TACACS+ Authentication Error: %s" % str(e)) - return None - if auth.valid: - return _get_or_set_enterprise_user(username, password, 'tacacs+') - - def get_user(self, user_id): - if not django_settings.TACACSPLUS_HOST: - return None - try: - return User.objects.get(pk=user_id) - except User.DoesNotExist: - return None - - def _get_client_ip(self, request): - if not request or not hasattr(request, 'META'): - return None - - x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') - if x_forwarded_for: - ip = x_forwarded_for.split(',')[0] - else: - ip = request.META.get('REMOTE_ADDR') - return ip - - -class TowerSAMLIdentityProvider(BaseSAMLIdentityProvider): - """ - Custom Identity Provider to make attributes to what we expect. - """ - - def get_user_permanent_id(self, attributes): - uid = attributes[self.conf.get('attr_user_permanent_id', OID_USERID)] - if isinstance(uid, str): - return uid - return uid[0] - - def get_attr(self, attributes, conf_key, default_attribute): - """ - Get the attribute 'default_attribute' out of the attributes, - unless self.conf[conf_key] overrides the default by specifying - another attribute to use. - """ - key = self.conf.get(conf_key, default_attribute) - value = attributes[key] if key in attributes else None - # In certain implementations (like https://pagure.io/ipsilon) this value is a string, not a list - if isinstance(value, (list, tuple)): - value = value[0] - if conf_key in ('attr_first_name', 'attr_last_name', 'attr_username', 'attr_email') and value is None: - logger.warning( - "Could not map user detail '%s' from SAML attribute '%s'; update SOCIAL_AUTH_SAML_ENABLED_IDPS['%s']['%s'] with the correct SAML attribute.", - conf_key[5:], - key, - self.name, - conf_key, - ) - return str(value) if value is not None else value - - -class SAMLAuth(BaseSAMLAuth): - """ - Custom SAMLAuth backend to verify license status - """ - - def get_idp(self, idp_name): - idp_config = self.setting('ENABLED_IDPS')[idp_name] - return TowerSAMLIdentityProvider(idp_name, **idp_config) - - def authenticate(self, request, *args, **kwargs): - if not all( - [ - django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, - django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT, - django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, - django_settings.SOCIAL_AUTH_SAML_ORG_INFO, - django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, - django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT, - django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS, - ] - ): - return None - pipeline_result = super(SAMLAuth, self).authenticate(request, *args, **kwargs) - - if isinstance(pipeline_result, HttpResponse): - return pipeline_result - else: - user = pipeline_result - - # Comes from https://github.com/omab/python-social-auth/blob/v0.2.21/social/backends/base.py#L91 - if getattr(user, 'is_new', False): - enterprise_auth = _decorate_enterprise_user(user, 'saml') - logger.debug("Created enterprise user %s from %s backend." % (user.username, enterprise_auth.get_provider_display())) - elif user and not user.is_in_enterprise_category('saml'): - return None - if user: - logger.debug("Enterprise user %s already created in Tower." % user.username) - return user - - def get_user(self, user_id): - if not all( - [ - django_settings.SOCIAL_AUTH_SAML_SP_ENTITY_ID, - django_settings.SOCIAL_AUTH_SAML_SP_PUBLIC_CERT, - django_settings.SOCIAL_AUTH_SAML_SP_PRIVATE_KEY, - django_settings.SOCIAL_AUTH_SAML_ORG_INFO, - django_settings.SOCIAL_AUTH_SAML_TECHNICAL_CONTACT, - django_settings.SOCIAL_AUTH_SAML_SUPPORT_CONTACT, - django_settings.SOCIAL_AUTH_SAML_ENABLED_IDPS, - ] - ): - return None - return super(SAMLAuth, self).get_user(user_id) - - -def _update_m2m_from_groups(ldap_user, opts, remove=True): - """ - Hepler function to evaluate the LDAP team/org options to determine if LDAP user should - be a member of the team/org based on their ldap group dns. - - Returns: - True - User should be added - False - User should be removed - None - Users membership should not be changed - """ - if opts is None: - return None - elif not opts: - pass - elif isinstance(opts, bool) and opts is True: - return True - else: - if isinstance(opts, str): - opts = [opts] - # If any of the users groups matches any of the list options - for group_dn in opts: - if not isinstance(group_dn, str): - continue - if ldap_user._get_groups().is_member_of(group_dn): - return True - if remove: - return False - return None - - -@receiver(populate_user, dispatch_uid='populate-ldap-user') -def on_populate_user(sender, **kwargs): - """ - Handle signal from LDAP backend to populate the user object. Update user - organization/team memberships according to their LDAP groups. - """ - user = kwargs['user'] - ldap_user = kwargs['ldap_user'] - backend = ldap_user.backend - - # Boolean to determine if we should force an user update - # to avoid duplicate SQL update statements - force_user_update = False - - # Prefetch user's groups to prevent LDAP queries for each org/team when - # checking membership. - ldap_user._get_groups().get_group_dns() - - # If the LDAP user has a first or last name > $maxlen chars, truncate it - for field in ('first_name', 'last_name'): - max_len = User._meta.get_field(field).max_length - field_len = len(getattr(user, field)) - if field_len > max_len: - setattr(user, field, getattr(user, field)[:max_len]) - force_user_update = True - logger.warning('LDAP user {} has {} > max {} characters'.format(user.username, field, max_len)) - - org_map = getattr(backend.settings, 'ORGANIZATION_MAP', {}) - team_map_settings = getattr(backend.settings, 'TEAM_MAP', {}) - orgs_list = list(org_map.keys()) - team_map = {} - for team_name, team_opts in team_map_settings.items(): - if not team_opts.get('organization', None): - # You can't save the LDAP config in the UI w/o an org (or '' or null as the org) so if we somehow got this condition its an error - logger.error("Team named {} in LDAP team map settings is invalid due to missing organization".format(team_name)) - continue - team_map[team_name] = team_opts['organization'] - - create_org_and_teams(orgs_list, team_map, 'LDAP') - - # Compute in memory what the state is of the different LDAP orgs - org_roles_and_ldap_attributes = {'admin_role': 'admins', 'auditor_role': 'auditors', 'member_role': 'users'} - desired_org_states = {} - for org_name, org_opts in org_map.items(): - remove = bool(org_opts.get('remove', True)) - desired_org_states[org_name] = {} - for org_role_name in org_roles_and_ldap_attributes.keys(): - ldap_name = org_roles_and_ldap_attributes[org_role_name] - opts = org_opts.get(ldap_name, None) - remove = bool(org_opts.get('remove_{}'.format(ldap_name), remove)) - desired_org_states[org_name][org_role_name] = _update_m2m_from_groups(ldap_user, opts, remove) - - # If everything returned None (because there was no configuration) we can remove this org from our map - # This will prevent us from loading the org in the next query - if all(desired_org_states[org_name][org_role_name] is None for org_role_name in org_roles_and_ldap_attributes.keys()): - del desired_org_states[org_name] - - # Compute in memory what the state is of the different LDAP teams - desired_team_states = {} - for team_name, team_opts in team_map_settings.items(): - if 'organization' not in team_opts: - continue - users_opts = team_opts.get('users', None) - remove = bool(team_opts.get('remove', True)) - state = _update_m2m_from_groups(ldap_user, users_opts, remove) - if state is not None: - organization = team_opts['organization'] - if organization not in desired_team_states: - desired_team_states[organization] = {} - desired_team_states[organization][team_name] = {'member_role': state} - - # Check if user.profile is available, otherwise force user.save() - try: - _ = user.profile - except ValueError: - force_user_update = True - finally: - if force_user_update: - user.save() - - # Update user profile to store LDAP DN. - profile = user.profile - if profile.ldap_dn != ldap_user.dn: - profile.ldap_dn = ldap_user.dn - profile.save() - - reconcile_users_org_team_mappings(user, desired_org_states, desired_team_states, 'LDAP') diff --git a/awx/sso/middleware.py b/awx/sso/middleware.py deleted file mode 100644 index 59c2a3c0e3..0000000000 --- a/awx/sso/middleware.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2015 Ansible, Inc. -# All Rights Reserved. - -# Python -import urllib.parse - -# Django -from django.conf import settings -from django.utils.functional import LazyObject -from django.shortcuts import redirect - -# Python Social Auth -from social_core.exceptions import SocialAuthBaseException -from social_core.utils import social_logger -from social_django import utils -from social_django.middleware import SocialAuthExceptionMiddleware - - -class SocialAuthMiddleware(SocialAuthExceptionMiddleware): - def __call__(self, request): - return self.process_request(request) - - def process_request(self, request): - if request.path.startswith('/sso'): - # See upgrade blocker note in requirements/README.md - utils.BACKENDS = settings.AUTHENTICATION_BACKENDS - token_key = request.COOKIES.get('token', '') - token_key = urllib.parse.quote(urllib.parse.unquote(token_key).strip('"')) - - if not hasattr(request, 'successful_authenticator'): - request.successful_authenticator = None - - if not request.path.startswith('/sso/') and 'migrations_notran' not in request.path: - if request.user and request.user.is_authenticated: - # The rest of the code base rely hevily on type/inheritance checks, - # LazyObject sent from Django auth middleware can be buggy if not - # converted back to its original object. - if isinstance(request.user, LazyObject) and request.user._wrapped: - request.user = request.user._wrapped - request.session.pop('social_auth_error', None) - request.session.pop('social_auth_last_backend', None) - return self.get_response(request) - - def process_view(self, request, callback, callback_args, callback_kwargs): - if request.path.startswith('/sso/login/'): - request.session['social_auth_last_backend'] = callback_kwargs['backend'] - - def process_exception(self, request, exception): - strategy = getattr(request, 'social_strategy', None) - if strategy is None or self.raise_exception(request, exception): - return - - if isinstance(exception, SocialAuthBaseException) or request.path.startswith('/sso/'): - backend = getattr(request, 'backend', None) - backend_name = getattr(backend, 'name', 'unknown-backend') - - message = self.get_message(request, exception) - if request.session.get('social_auth_last_backend') != backend_name: - backend_name = request.session.get('social_auth_last_backend') - message = request.GET.get('error_description', message) - - full_backend_name = backend_name - try: - idp_name = strategy.request_data()['RelayState'] - full_backend_name = '%s:%s' % (backend_name, idp_name) - except KeyError: - pass - - social_logger.error(message) - - url = self.get_redirect_uri(request, exception) - request.session['social_auth_error'] = (full_backend_name, message) - return redirect(url) - - def get_message(self, request, exception): - msg = str(exception) - if msg and msg[-1] not in '.?!': - msg = msg + '.' - return msg - - def get_redirect_uri(self, request, exception): - strategy = getattr(request, 'social_strategy', None) - return strategy.session_get('next', '') or strategy.setting('LOGIN_ERROR_URL') diff --git a/awx/sso/tests/conftest.py b/awx/sso/tests/conftest.py deleted file mode 100644 index 825640e902..0000000000 --- a/awx/sso/tests/conftest.py +++ /dev/null @@ -1,150 +0,0 @@ -import pytest - -from django.contrib.auth.models import User - -from awx.sso.backends import TACACSPlusBackend -from awx.sso.models import UserEnterpriseAuth - - -@pytest.fixture -def tacacsplus_backend(): - return TACACSPlusBackend() - - -@pytest.fixture -def existing_normal_user(): - try: - user = User.objects.get(username="alice") - except User.DoesNotExist: - user = User(username="alice", password="password") - user.save() - return user - - -@pytest.fixture -def existing_tacacsplus_user(): - try: - user = User.objects.get(username="foo") - except User.DoesNotExist: - user = User(username="foo") - user.set_unusable_password() - user.save() - enterprise_auth = UserEnterpriseAuth(user=user, provider='tacacs+') - enterprise_auth.save() - return user - - -@pytest.fixture -def test_radius_config(settings): - settings.RADIUS_SERVER = '127.0.0.1' - settings.RADIUS_PORT = 1812 - settings.RADIUS_SECRET = 'secret' - - -@pytest.fixture -def basic_saml_config(settings): - settings.SAML_SECURITY_CONFIG = { - "wantNameId": True, - "signMetadata": False, - "digestAlgorithm": "http://www.w3.org/2001/04/xmlenc#sha256", - "nameIdEncrypted": False, - "signatureAlgorithm": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", - "authnRequestsSigned": False, - "logoutRequestSigned": False, - "wantNameIdEncrypted": False, - "logoutResponseSigned": False, - "wantAssertionsSigned": True, - "requestedAuthnContext": False, - "wantAssertionsEncrypted": False, - } - settings.SOCIAL_AUTH_SAML_ENABLED_IDPS = { - "example": { - "attr_email": "email", - "attr_first_name": "first_name", - "attr_last_name": "last_name", - "attr_user_permanent_id": "username", - "attr_username": "username", - "entity_id": "https://www.example.com/realms/sample", - "url": "https://www.example.com/realms/sample/protocol/saml", - "x509cert": "A" * 64 + "B" * 64 + "C" * 23, - } - } - - settings.SOCIAL_AUTH_SAML_TEAM_ATTR = { - "remove": False, - "saml_attr": "group_name", - "team_org_map": [ - {"team": "internal:unix:domain:admins", "team_alias": "Administrators", "organization": "Default"}, - {"team": "East Coast", "organization": "North America"}, - {"team": "developers", "organization": "North America"}, - {"team": "developers", "organization": "South America"}, - ], - } - - settings.SOCIAL_AUTH_SAML_USER_FLAGS_BY_ATTR = { - "is_superuser_role": ["wilma"], - "is_superuser_attr": "friends", - "is_superuser_value": ["barney", "fred"], - "remove_superusers": False, - "is_system_auditor_role": ["fred"], - "is_system_auditor_attr": "auditor", - "is_system_auditor_value": ["bamm-bamm"], - } - - settings.SOCIAL_AUTH_SAML_ORGANIZATION_ATTR = {"saml_attr": "member-of", "remove": True, "saml_admin_attr": "admin-of", "remove_admins": False} - - -@pytest.fixture -def test_tacacs_config(settings): - settings.TACACSPLUS_HOST = "tacacshost" - settings.TACACSPLUS_PORT = 49 - settings.TACACSPLUS_SECRET = "secret" - settings.TACACSPLUS_SESSION_TIMEOUT = 10 - settings.TACACSPLUS_AUTH_PROTOCOL = "pap" - settings.TACACSPLUS_REM_ADDR = True - - -@pytest.fixture -def saml_config_user_flags_no_value(settings): - settings.SAML_SECURITY_CONFIG = { - "wantNameId": True, - "signMetadata": False, - "digestAlgorithm": "http://www.w3.org/2001/04/xmlenc#sha256", - "nameIdEncrypted": False, - "signatureAlgorithm": "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", - "authnRequestsSigned": False, - "logoutRequestSigned": False, - "wantNameIdEncrypted": False, - "logoutResponseSigned": False, - "wantAssertionsSigned": True, - "requestedAuthnContext": False, - "wantAssertionsEncrypted": False, - } - settings.SOCIAL_AUTH_SAML_ENABLED_IDPS = { - "example": { - "attr_email": "email", - "attr_first_name": "first_name", - "attr_last_name": "last_name", - "attr_user_permanent_id": "username", - "attr_username": "username", - "entity_id": "https://www.example.com/realms/sample", - "url": "https://www.example.com/realms/sample/protocol/saml", - "x509cert": "A" * 64 + "B" * 64 + "C" * 23, - } - } - - settings.SOCIAL_AUTH_SAML_TEAM_ATTR = { - "remove": False, - "saml_attr": "group_name", - "team_org_map": [ - {"team": "internal:unix:domain:admins", "team_alias": "Administrators", "organization": "Default"}, - {"team": "East Coast", "organization": "North America"}, - {"team": "developers", "organization": "North America"}, - {"team": "developers", "organization": "South America"}, - ], - } - - settings.SOCIAL_AUTH_SAML_USER_FLAGS_BY_ATTR = { - "is_superuser_role": ["wilma"], - "is_superuser_attr": "friends", - } diff --git a/awx/sso/tests/unit/test_google_oauth2_migrator.py b/awx/sso/tests/unit/test_google_oauth2_migrator.py deleted file mode 100644 index ec7fca5939..0000000000 --- a/awx/sso/tests/unit/test_google_oauth2_migrator.py +++ /dev/null @@ -1,104 +0,0 @@ -import pytest -from unittest.mock import MagicMock -from awx.sso.utils.google_oauth2_migrator import GoogleOAuth2Migrator - - -@pytest.fixture -def test_google_config(settings): - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "test_key" - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "test_secret" - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL = "https://tower.example.com/sso/complete/google-oauth2/" - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP = {"My Org": {"users": True}} - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP = {"My Team": {"organization": "My Org", "users": True}} - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = ["profile", "email"] - - -@pytest.mark.django_db -def test_get_controller_config(test_google_config): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = GoogleOAuth2Migrator(gateway_client, command_obj) - - result = obj.get_controller_config() - assert len(result) == 1 - config = result[0] - assert config['category'] == 'Google OAuth2' - settings = config['settings'] - assert settings['SOCIAL_AUTH_GOOGLE_OAUTH2_KEY'] == 'test_key' - assert settings['SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET'] == 'test_secret' - assert settings['SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL'] == "https://tower.example.com/sso/complete/google-oauth2/" - assert settings['SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE'] == ["profile", "email"] - # Assert that other settings are not present in the returned config - assert 'SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP' not in settings - assert 'SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP' not in settings - - -@pytest.mark.django_db -def test_create_gateway_authenticator(mocker, test_google_config): - mocker.patch('django.conf.settings.LOGGING', {}) - - gateway_client = MagicMock() - command_obj = MagicMock() - obj = GoogleOAuth2Migrator(gateway_client, command_obj) - mock_submit = MagicMock(return_value=True) - obj.submit_authenticator = mock_submit - - configs = obj.get_controller_config() - result = obj.create_gateway_authenticator(configs[0]) - - assert result is True - mock_submit.assert_called_once() - - # Assert payload sent to gateway - payload = mock_submit.call_args[0][0] - assert payload['name'] == 'google' - assert payload['slug'] == 'aap-google-oauth2-google-oauth2' - assert payload['type'] == 'ansible_base.authentication.authenticator_plugins.google_oauth2' - assert payload['enabled'] is False - assert payload['create_objects'] is True - assert payload['remove_users'] is False - - # Assert configuration details - configuration = payload['configuration'] - assert configuration['KEY'] == 'test_key' - assert configuration['SECRET'] == 'test_secret' - assert configuration['CALLBACK_URL'] == 'https://tower.example.com/sso/complete/google-oauth2/' - assert configuration['SCOPE'] == ['profile', 'email'] - - # Assert mappers - assert len(payload['mappers']) == 2 - assert payload['mappers'][0]['map_type'] == 'organization' - assert payload['mappers'][1]['map_type'] == 'team' - - # Assert ignore_keys - ignore_keys = mock_submit.call_args[0][1] - assert ignore_keys == ["ACCESS_TOKEN_METHOD", "REVOKE_TOKEN_METHOD"] - - -@pytest.mark.django_db -def test_create_gateway_authenticator_no_optional_values(mocker, settings): - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = "test_key" - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = "test_secret" - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP = {} - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP = {} - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = None - settings.SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL = None - - mocker.patch('django.conf.settings.LOGGING', {}) - - gateway_client = MagicMock() - command_obj = MagicMock() - obj = GoogleOAuth2Migrator(gateway_client, command_obj) - mock_submit = MagicMock(return_value=True) - obj.submit_authenticator = mock_submit - - configs = obj.get_controller_config() - obj.create_gateway_authenticator(configs[0]) - - payload = mock_submit.call_args[0][0] - assert 'CALLBACK_URL' not in payload['configuration'] - assert 'SCOPE' not in payload['configuration'] - - ignore_keys = mock_submit.call_args[0][1] - assert 'CALLBACK_URL' in ignore_keys - assert 'SCOPE' in ignore_keys diff --git a/awx/sso/tests/unit/test_radius_migrator.py b/awx/sso/tests/unit/test_radius_migrator.py deleted file mode 100644 index ffc1bbed36..0000000000 --- a/awx/sso/tests/unit/test_radius_migrator.py +++ /dev/null @@ -1,17 +0,0 @@ -import pytest -from unittest.mock import MagicMock -from awx.sso.utils.radius_migrator import RADIUSMigrator - - -@pytest.mark.django_db -def test_get_controller_config(test_radius_config): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = RADIUSMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - config = result[0]['settings']['configuration'] - assert config['SERVER'] == '127.0.0.1' - assert config['PORT'] == 1812 - assert config['SECRET'] == 'secret' - assert len(config) == 3 diff --git a/awx/sso/tests/unit/test_saml_migrator.py b/awx/sso/tests/unit/test_saml_migrator.py deleted file mode 100644 index 97dca5c607..0000000000 --- a/awx/sso/tests/unit/test_saml_migrator.py +++ /dev/null @@ -1,272 +0,0 @@ -import pytest -from unittest.mock import MagicMock, patch -from awx.sso.utils.saml_migrator import SAMLMigrator - - -@pytest.mark.django_db -def test_get_controller_config(basic_saml_config): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = SAMLMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - lines = result[0]['settings']['configuration']['IDP_X509_CERT'].splitlines() - assert lines[0] == '-----BEGIN CERTIFICATE-----' - assert lines[1] == "A" * 64 - assert lines[2] == "B" * 64 - assert lines[3] == "C" * 23 - assert lines[-1] == '-----END CERTIFICATE-----' - - -@pytest.mark.django_db -def test_get_controller_config_with_mapper(saml_config_user_flags_no_value): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = SAMLMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - expected_maps = [ - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'Default', - 'team': 'Administrators', - 'name': 'Team-Administrators-Default', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['internal:unix:domain:admins']}, 'join_condition': 'or'}}, - 'order': 1, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'North America', - 'team': 'East Coast', - 'name': 'Team-East Coast-North America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['East Coast']}, 'join_condition': 'or'}}, - 'order': 2, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'North America', - 'team': 'developers', - 'name': 'Team-developers-North America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['developers']}, 'join_condition': 'or'}}, - 'order': 3, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'South America', - 'team': 'developers', - 'name': 'Team-developers-South America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['developers']}, 'join_condition': 'or'}}, - 'order': 4, - }, - { - 'map_type': 'is_superuser', - 'role': None, - 'name': 'Role-is_superuser', - 'organization': None, - 'team': None, - 'revoke': True, - 'order': 5, - 'authenticator': -1, - 'triggers': {'attributes': {'Role': {'in': ['wilma']}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'is_superuser', - 'role': None, - 'name': 'Role-is_superuser-attr', - 'organization': None, - 'team': None, - 'revoke': True, - 'order': 6, - 'authenticator': -1, - 'triggers': {'attributes': {'friends': {}, 'join_condition': 'or'}}, - }, - ] - assert result[0]['team_mappers'] == expected_maps - extra_data = result[0]['settings']['configuration']['EXTRA_DATA'] - assert ['Role', 'Role'] in extra_data - assert ['friends', 'friends'] in extra_data - assert ['group_name', 'group_name'] in extra_data - - -@pytest.mark.django_db -def test_get_controller_config_with_roles(basic_saml_config): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = SAMLMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - - expected_maps = [ - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'Default', - 'team': 'Administrators', - 'name': 'Team-Administrators-Default', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['internal:unix:domain:admins']}, 'join_condition': 'or'}}, - 'order': 1, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'North America', - 'team': 'East Coast', - 'name': 'Team-East Coast-North America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['East Coast']}, 'join_condition': 'or'}}, - 'order': 2, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'North America', - 'team': 'developers', - 'name': 'Team-developers-North America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['developers']}, 'join_condition': 'or'}}, - 'order': 3, - }, - { - 'map_type': 'team', - 'role': 'Team Member', - 'organization': 'South America', - 'team': 'developers', - 'name': 'Team-developers-South America', - 'revoke': False, - 'authenticator': -1, - 'triggers': {'attributes': {'group_name': {'in': ['developers']}, 'join_condition': 'or'}}, - 'order': 4, - }, - { - 'map_type': 'is_superuser', - 'role': None, - 'name': 'Role-is_superuser', - 'organization': None, - 'team': None, - 'revoke': False, - 'order': 5, - 'authenticator': -1, - 'triggers': {'attributes': {'Role': {'in': ['wilma']}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'role', - 'role': 'Platform Auditor', - 'name': 'Role-Platform Auditor', - 'organization': None, - 'team': None, - 'revoke': True, - 'order': 6, - 'authenticator': -1, - 'triggers': {'attributes': {'Role': {'in': ['fred']}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'is_superuser', - 'role': None, - 'name': 'Role-is_superuser-attr', - 'organization': None, - 'team': None, - 'revoke': False, - 'order': 7, - 'authenticator': -1, - 'triggers': {'attributes': {'friends': {'in': ['barney', 'fred']}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'role', - 'role': 'Platform Auditor', - 'name': 'Role-Platform Auditor-attr', - 'organization': None, - 'team': None, - 'revoke': True, - 'order': 8, - 'authenticator': -1, - 'triggers': {'attributes': {'auditor': {'in': ['bamm-bamm']}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'organization', - 'role': 'Organization Member', - 'name': 'Role-Organization Member-attr', - 'organization': "{% for_attr_value('member-of') %}", - 'team': None, - 'revoke': True, - 'order': 9, - 'authenticator': -1, - 'triggers': {'attributes': {'member-of': {}, 'join_condition': 'or'}}, - }, - { - 'map_type': 'organization', - 'role': 'Organization Admin', - 'name': 'Role-Organization Admin-attr', - 'organization': "{% for_attr_value('admin-of') %}", - 'team': None, - 'revoke': False, - 'order': 10, - 'authenticator': -1, - 'triggers': {'attributes': {'admin-of': {}, 'join_condition': 'or'}}, - }, - ] - - assert result[0]['team_mappers'] == expected_maps - extra_data = result[0]['settings']['configuration']['EXTRA_DATA'] - extra_data_items = [ - ['member-of', 'member-of'], - ['admin-of', 'admin-of'], - ['Role', 'Role'], - ['friends', 'friends'], - ['group_name', 'group_name'], - ] - for item in extra_data_items: - assert item in extra_data - assert extra_data.count(item) == 1 - - -@pytest.mark.django_db -def test_get_controller_config_enabled_false(basic_saml_config): - """SAML controller export marks settings.enabled False by default.""" - gateway_client = MagicMock() - command_obj = MagicMock() - obj = SAMLMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - assert isinstance(result, list) and len(result) >= 1 - assert result[0]['settings']['enabled'] is False - - -@pytest.mark.django_db -def test_create_gateway_authenticator_submits_disabled(basic_saml_config): - """Submitted Gateway authenticator config must have enabled=False and correct ignore keys.""" - gateway_client = MagicMock() - command_obj = MagicMock() - obj = SAMLMigrator(gateway_client, command_obj) - - config = obj.get_controller_config()[0] - - with patch.object( - obj, - 'submit_authenticator', - return_value={'success': True, 'action': 'created', 'error': None}, - ) as submit_mock: - obj.create_gateway_authenticator(config) - - # Extract submitted args: gateway_config, ignore_keys, original_config - submitted_gateway_config = submit_mock.call_args[0][0] - ignore_keys = submit_mock.call_args[0][1] - - assert submitted_gateway_config['enabled'] is False - assert 'CALLBACK_URL' in ignore_keys - assert 'SP_PRIVATE_KEY' in ignore_keys diff --git a/awx/sso/tests/unit/test_settings_migrator.py b/awx/sso/tests/unit/test_settings_migrator.py deleted file mode 100644 index f7bd5fc342..0000000000 --- a/awx/sso/tests/unit/test_settings_migrator.py +++ /dev/null @@ -1,384 +0,0 @@ -""" -Unit tests for SettingsMigrator class. -""" - -import pytest -from unittest.mock import Mock, patch -from awx.sso.utils.settings_migrator import SettingsMigrator - - -class TestSettingsMigrator: - """Tests for SettingsMigrator class.""" - - def setup_method(self): - """Set up test fixtures.""" - self.gateway_client = Mock() - self.command = Mock() - self.migrator = SettingsMigrator(self.gateway_client, self.command) - - def test_get_authenticator_type(self): - """Test that get_authenticator_type returns 'Settings'.""" - assert self.migrator.get_authenticator_type() == "Settings" - - @pytest.mark.parametrize( - "input_name,expected_output", - [ - ('CUSTOM_LOGIN_INFO', 'custom_login_info'), - ('CUSTOM_LOGO', 'custom_logo'), - ('UNKNOWN_SETTING', 'UNKNOWN_SETTING'), - ('ANOTHER_UNKNOWN', 'ANOTHER_UNKNOWN'), - ], - ) - def test_convert_setting_name(self, input_name, expected_output): - """Test setting name conversion.""" - result = self.migrator._convert_setting_name(input_name) - assert result == expected_output - - @pytest.mark.parametrize( - "transformer_method,test_values", - [ - ('_transform_social_auth_username_is_full_email', [True, False]), - ('_transform_allow_oauth2_for_external_users', [True, False]), - ], - ) - def test_boolean_transformers(self, transformer_method, test_values): - """Test that boolean transformers return values as-is.""" - transformer = getattr(self.migrator, transformer_method) - for value in test_values: - assert transformer(value) is value - - @pytest.mark.parametrize( - "settings_values,expected_count", - [ - # Test case: all settings are None - ( - { - 'SESSION_COOKIE_AGE': None, - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': None, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': None, - 'LOGIN_REDIRECT_OVERRIDE': None, - 'ORG_ADMINS_CAN_SEE_ALL_USERS': None, - 'MANAGE_ORGANIZATION_AUTH': None, - }, - 0, - ), - # Test case: all settings are empty strings - ( - { - 'SESSION_COOKIE_AGE': "", - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': "", - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': "", - 'LOGIN_REDIRECT_OVERRIDE': "", - 'ORG_ADMINS_CAN_SEE_ALL_USERS': "", - 'MANAGE_ORGANIZATION_AUTH': "", - }, - 0, - ), - # Test case: only new settings have values - ( - { - 'SESSION_COOKIE_AGE': None, - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': None, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': None, - 'LOGIN_REDIRECT_OVERRIDE': None, - 'ORG_ADMINS_CAN_SEE_ALL_USERS': True, - 'MANAGE_ORGANIZATION_AUTH': False, - }, - 2, - ), - ], - ) - @patch('awx.sso.utils.settings_migrator.settings') - def test_get_controller_config_various_scenarios(self, mock_settings, settings_values, expected_count): - """Test get_controller_config with various setting combinations.""" - # Apply the settings values to the mock - for setting_name, setting_value in settings_values.items(): - setattr(mock_settings, setting_name, setting_value) - - result = self.migrator.get_controller_config() - assert len(result) == expected_count - - # Verify structure if we have results - if result: - for config in result: - assert config['category'] == 'global-settings' - assert 'setting_name' in config - assert 'setting_value' in config - assert config['org_mappers'] == [] - assert config['team_mappers'] == [] - assert config['role_mappers'] == [] - assert config['allow_mappers'] == [] - - @patch('awx.sso.utils.settings_migrator.settings') - def test_get_controller_config_with_all_settings(self, mock_settings): - """Test get_controller_config with all settings configured.""" - # Mock all settings with valid values - mock_settings.SESSION_COOKIE_AGE = 3600 - mock_settings.SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True - mock_settings.ALLOW_OAUTH2_FOR_EXTERNAL_USERS = False - mock_settings.LOGIN_REDIRECT_OVERRIDE = "https://example.com/login" - mock_settings.ORG_ADMINS_CAN_SEE_ALL_USERS = True - mock_settings.MANAGE_ORGANIZATION_AUTH = False - - # Mock the login redirect override to not be set by migrator - with patch.object(self.migrator.__class__.__bases__[0], 'login_redirect_override_set_by_migrator', False): - result = self.migrator.get_controller_config() - - assert len(result) == 6 - - # Check that all expected settings are present - setting_names = [config['setting_name'] for config in result] - expected_settings = [ - 'SESSION_COOKIE_AGE', - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL', - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS', - 'LOGIN_REDIRECT_OVERRIDE', - 'ORG_ADMINS_CAN_SEE_ALL_USERS', - 'MANAGE_ORGANIZATION_AUTH', - ] - - for setting in expected_settings: - assert setting in setting_names - - # Verify structure of returned configs - for config in result: - assert config['category'] == 'global-settings' - assert 'setting_name' in config - assert 'setting_value' in config - assert config['org_mappers'] == [] - assert config['team_mappers'] == [] - assert config['role_mappers'] == [] - assert config['allow_mappers'] == [] - - @patch('awx.sso.utils.settings_migrator.settings') - def test_get_controller_config_with_new_settings_only(self, mock_settings): - """Test get_controller_config with only the new settings configured.""" - # Mock only the new settings - mock_settings.SESSION_COOKIE_AGE = None - mock_settings.SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = None - mock_settings.ALLOW_OAUTH2_FOR_EXTERNAL_USERS = None - mock_settings.LOGIN_REDIRECT_OVERRIDE = None - mock_settings.ORG_ADMINS_CAN_SEE_ALL_USERS = True - mock_settings.MANAGE_ORGANIZATION_AUTH = False - - result = self.migrator.get_controller_config() - - assert len(result) == 2 - - # Check the new settings are present - setting_names = [config['setting_name'] for config in result] - assert 'ORG_ADMINS_CAN_SEE_ALL_USERS' in setting_names - assert 'MANAGE_ORGANIZATION_AUTH' in setting_names - - # Verify the values - org_admins_config = next(c for c in result if c['setting_name'] == 'ORG_ADMINS_CAN_SEE_ALL_USERS') - assert org_admins_config['setting_value'] is True - - manage_org_auth_config = next(c for c in result if c['setting_name'] == 'MANAGE_ORGANIZATION_AUTH') - assert manage_org_auth_config['setting_value'] is False - - @patch('awx.sso.utils.settings_migrator.settings') - def test_get_controller_config_with_login_redirect_override_from_migrator(self, mock_settings): - """Test get_controller_config when LOGIN_REDIRECT_OVERRIDE is set by migrator.""" - # Mock settings - mock_settings.SESSION_COOKIE_AGE = None - mock_settings.SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = None - mock_settings.ALLOW_OAUTH2_FOR_EXTERNAL_USERS = None - mock_settings.LOGIN_REDIRECT_OVERRIDE = "https://original.com/login" - mock_settings.ORG_ADMINS_CAN_SEE_ALL_USERS = None - mock_settings.MANAGE_ORGANIZATION_AUTH = None - - # Mock the login redirect override to be set by migrator - with patch.object(self.migrator.__class__.__bases__[0], 'login_redirect_override_set_by_migrator', True): - with patch.object(self.migrator.__class__.__bases__[0], 'login_redirect_override_new_url', 'https://new.com/login'): - result = self.migrator.get_controller_config() - - assert len(result) == 1 - assert result[0]['setting_name'] == 'LOGIN_REDIRECT_OVERRIDE' - assert result[0]['setting_value'] == 'https://new.com/login' # Should use the migrator URL - - @pytest.mark.parametrize( - "config,current_value,expected_action,should_update", - [ - # Test case: setting needs update - ({'setting_name': 'ORG_ADMINS_CAN_SEE_ALL_USERS', 'setting_value': True}, False, 'updated', True), - # Test case: setting is unchanged - ({'setting_name': 'MANAGE_ORGANIZATION_AUTH', 'setting_value': False}, False, 'skipped', False), - # Test case: another setting needs update - ({'setting_name': 'SESSION_COOKIE_AGE', 'setting_value': 7200}, 3600, 'updated', True), - # Test case: another setting is unchanged - ({'setting_name': 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL', 'setting_value': True}, True, 'skipped', False), - ], - ) - def test_create_gateway_authenticator_success_scenarios(self, config, current_value, expected_action, should_update): - """Test create_gateway_authenticator success scenarios.""" - # Mock gateway client methods - self.gateway_client.get_gateway_setting.return_value = current_value - self.gateway_client.update_gateway_setting.return_value = None - - result = self.migrator.create_gateway_authenticator(config) - - assert result['success'] is True - assert result['action'] == expected_action - assert result['error'] is None - - # Verify gateway client calls - expected_setting_name = config['setting_name'] - self.gateway_client.get_gateway_setting.assert_called_once_with(expected_setting_name) - - if should_update: - self.gateway_client.update_gateway_setting.assert_called_once_with(expected_setting_name, config['setting_value']) - else: - self.gateway_client.update_gateway_setting.assert_not_called() - - # Reset mocks for next iteration - self.gateway_client.reset_mock() - - def test_create_gateway_authenticator_with_setting_name_conversion(self): - """Test create_gateway_authenticator with setting name that needs conversion.""" - config = {'setting_name': 'CUSTOM_LOGIN_INFO', 'setting_value': 'Some custom info'} - - # Mock gateway client methods - self.gateway_client.get_gateway_setting.return_value = 'Old info' # Different value - self.gateway_client.update_gateway_setting.return_value = None - - result = self.migrator.create_gateway_authenticator(config) - - assert result['success'] is True - assert result['action'] == 'updated' - - # Verify gateway client was called with converted name - self.gateway_client.get_gateway_setting.assert_called_once_with('custom_login_info') - self.gateway_client.update_gateway_setting.assert_called_once_with('custom_login_info', 'Some custom info') - - def test_create_gateway_authenticator_failure(self): - """Test create_gateway_authenticator when gateway update fails.""" - config = {'setting_name': 'SESSION_COOKIE_AGE', 'setting_value': 7200} - - # Mock gateway client to raise exception - self.gateway_client.get_gateway_setting.return_value = 3600 - self.gateway_client.update_gateway_setting.side_effect = Exception("Gateway error") - - result = self.migrator.create_gateway_authenticator(config) - - assert result['success'] is False - assert result['action'] == 'failed' - assert result['error'] == 'Gateway error' - - @pytest.mark.parametrize( - "scenario,settings_config,gateway_responses,update_side_effects,expected_counts", - [ - # Scenario 1: No settings configured - ( - "no_settings", - { - 'SESSION_COOKIE_AGE': None, - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': None, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': None, - 'LOGIN_REDIRECT_OVERRIDE': None, - 'ORG_ADMINS_CAN_SEE_ALL_USERS': None, - 'MANAGE_ORGANIZATION_AUTH': None, - }, - [], # No gateway calls expected - [], # No update calls expected - {'settings_created': 0, 'settings_updated': 0, 'settings_unchanged': 0, 'settings_failed': 0}, - ), - # Scenario 2: All updates successful - ( - "successful_updates", - { - 'SESSION_COOKIE_AGE': None, - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': None, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': None, - 'LOGIN_REDIRECT_OVERRIDE': None, - 'ORG_ADMINS_CAN_SEE_ALL_USERS': True, - 'MANAGE_ORGANIZATION_AUTH': False, - }, - [False, True], # Different values to trigger updates - [None, None], # Successful updates - {'settings_created': 0, 'settings_updated': 2, 'settings_unchanged': 0, 'settings_failed': 0}, - ), - # Scenario 3: One unchanged, one updated - ( - "mixed_results", - { - 'SESSION_COOKIE_AGE': None, - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': None, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': None, - 'LOGIN_REDIRECT_OVERRIDE': None, - 'ORG_ADMINS_CAN_SEE_ALL_USERS': True, - 'MANAGE_ORGANIZATION_AUTH': False, - }, - [True, True], # Gateway returns: ORG_ADMINS_CAN_SEE_ALL_USERS=True (unchanged), MANAGE_ORGANIZATION_AUTH=True (needs update) - [ValueError("Update failed")], # Only one update call (for MANAGE_ORGANIZATION_AUTH), and it fails - {'settings_created': 0, 'settings_updated': 0, 'settings_unchanged': 1, 'settings_failed': 1}, - ), - ], - ) - @patch('awx.sso.utils.settings_migrator.settings') - def test_migrate_scenarios(self, mock_settings, scenario, settings_config, gateway_responses, update_side_effects, expected_counts): - """Test migrate method with various scenarios.""" - # Apply settings configuration - for setting_name, setting_value in settings_config.items(): - setattr(mock_settings, setting_name, setting_value) - - # Mock gateway client responses - if gateway_responses: - self.gateway_client.get_gateway_setting.side_effect = gateway_responses - if update_side_effects: - self.gateway_client.update_gateway_setting.side_effect = update_side_effects - - # Mock the login redirect override to not be set by migrator for these tests - with patch.object(self.migrator.__class__.__bases__[0], 'login_redirect_override_set_by_migrator', False): - result = self.migrator.migrate() - - # Verify expected counts - for key, expected_value in expected_counts.items(): - assert result[key] == expected_value, f"Scenario {scenario}: Expected {key}={expected_value}, got {result[key]}" - - # All authenticator/mapper counts should be 0 since settings don't have them - authenticator_mapper_keys = ['created', 'updated', 'unchanged', 'failed', 'mappers_created', 'mappers_updated', 'mappers_failed'] - for key in authenticator_mapper_keys: - assert result[key] == 0, f"Scenario {scenario}: Expected {key}=0, got {result[key]}" - - def test_setting_transformers_defined(self): - """Test that setting transformers are properly defined.""" - expected_transformers = {'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL', 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS'} - - actual_transformers = set(self.migrator.setting_transformers.keys()) - assert actual_transformers == expected_transformers - - @pytest.mark.parametrize( - "transformer_return_value,expected_result_count", - [ - (None, 0), # Transformer returns None - should be excluded - ("", 0), # Transformer returns empty string - should be excluded - (True, 1), # Transformer returns valid value - should be included - ], - ) - @patch('awx.sso.utils.settings_migrator.settings') - def test_get_controller_config_transformer_edge_cases(self, mock_settings, transformer_return_value, expected_result_count): - """Test get_controller_config when transformer returns various edge case values.""" - # Mock settings - only one setting with a value that has a transformer - mock_settings.SESSION_COOKIE_AGE = None - mock_settings.SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True - mock_settings.ALLOW_OAUTH2_FOR_EXTERNAL_USERS = None - mock_settings.LOGIN_REDIRECT_OVERRIDE = None - mock_settings.ORG_ADMINS_CAN_SEE_ALL_USERS = None - mock_settings.MANAGE_ORGANIZATION_AUTH = None - - # Mock transformer to return the specified value - # We need to patch the transformer in the dictionary, not just the method - original_transformer = self.migrator.setting_transformers.get('SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL') - self.migrator.setting_transformers['SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL'] = lambda x: transformer_return_value - - try: - # Mock the login redirect override to not be set by migrator - with patch.object(self.migrator.__class__.__bases__[0], 'login_redirect_override_set_by_migrator', False): - result = self.migrator.get_controller_config() - finally: - # Restore the original transformer - if original_transformer: - self.migrator.setting_transformers['SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL'] = original_transformer - - assert len(result) == expected_result_count diff --git a/awx/sso/tests/unit/test_tacacs_migrator.py b/awx/sso/tests/unit/test_tacacs_migrator.py deleted file mode 100644 index 05c075d33b..0000000000 --- a/awx/sso/tests/unit/test_tacacs_migrator.py +++ /dev/null @@ -1,37 +0,0 @@ -import pytest -from unittest.mock import MagicMock -from awx.sso.utils.tacacs_migrator import TACACSMigrator - - -@pytest.mark.django_db -def test_get_controller_config(test_tacacs_config): - gateway_client = MagicMock() - command_obj = MagicMock() - obj = TACACSMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - assert len(result) == 1 - config = result[0] - assert config['category'] == 'TACACSPLUS' - settings_data = config['settings'] - assert settings_data['name'] == 'default' - assert settings_data['type'] == 'ansible_base.authentication.authenticator_plugins.tacacs' - - configuration = settings_data['configuration'] - assert configuration['HOST'] == 'tacacshost' - assert configuration['PORT'] == 49 - assert configuration['SECRET'] == 'secret' - assert configuration['SESSION_TIMEOUT'] == 10 - assert configuration['AUTH_PROTOCOL'] == 'pap' - assert configuration['REM_ADDR'] is True - - -@pytest.mark.django_db -def test_get_controller_config_no_host(settings): - settings.TACACSPLUS_HOST = "" - gateway_client = MagicMock() - command_obj = MagicMock() - obj = TACACSMigrator(gateway_client, command_obj) - - result = obj.get_controller_config() - assert len(result) == 0 diff --git a/awx/sso/utils/__init__.py b/awx/sso/utils/__init__.py deleted file mode 100644 index 4d9f494723..0000000000 --- a/awx/sso/utils/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from awx.sso.utils.azure_ad_migrator import AzureADMigrator -from awx.sso.utils.github_migrator import GitHubMigrator -from awx.sso.utils.google_oauth2_migrator import GoogleOAuth2Migrator -from awx.sso.utils.ldap_migrator import LDAPMigrator -from awx.sso.utils.oidc_migrator import OIDCMigrator -from awx.sso.utils.radius_migrator import RADIUSMigrator -from awx.sso.utils.saml_migrator import SAMLMigrator - -__all__ = [ - 'AzureADMigrator', - 'GitHubMigrator', - 'GoogleOAuth2Migrator', - 'LDAPMigrator', - 'OIDCMigrator', - 'RADIUSMigrator', - 'SAMLMigrator', -] diff --git a/awx/sso/utils/azure_ad_migrator.py b/awx/sso/utils/azure_ad_migrator.py deleted file mode 100644 index 121fa59fc9..0000000000 --- a/awx/sso/utils/azure_ad_migrator.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Azure AD authenticator migrator. - -This module handles the migration of Azure AD 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 - - -class AzureADMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of Azure AD authenticators from AWX to Gateway. - """ - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "Azure AD" - - def get_controller_config(self): - """ - Export Azure AD authenticators. An Azure AD authenticator is only exported if - KEY and SECRET are configured. - - Returns: - list: List of configured Azure AD authentication providers with their settings - """ - key_value = getattr(settings, 'SOCIAL_AUTH_AZUREAD_OAUTH2_KEY', None) - secret_value = getattr(settings, 'SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET', None) - - # Skip this category if OIDC Key and/or Secret are not configured - if not key_value or not secret_value: - return [] - - # If we have both key and secret, collect all settings - org_map_value = getattr(settings, 'SOCIAL_AUTH_AZUREAD_OAUTH2_ORGANIZATION_MAP', None) - team_map_value = getattr(settings, 'SOCIAL_AUTH_AZUREAD_OAUTH2_TEAM_MAP', None) - login_redirect_override = getattr(settings, "LOGIN_REDIRECT_OVERRIDE", None) - - # 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 - 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) - - category = 'AzureAD' - - # Generate authenticator name and slug - authenticator_name = "Azure AD" - authenticator_slug = self._generate_authenticator_slug("azure_ad", category) - - return [ - { - 'category': category, - 'settings': { - "name": authenticator_name, - "slug": authenticator_slug, - "type": "ansible_base.authentication.authenticator_plugins.azuread", - "enabled": False, - "create_objects": True, - "remove_users": False, - "configuration": { - "KEY": key_value, - "SECRET": secret_value, - "GROUPS_CLAIM": "groups", - }, - }, - 'org_mappers': org_mappers, - 'team_mappers': team_mappers, - 'login_redirect_override': login_redirect_override, - } - ] - - def create_gateway_authenticator(self, config): - """Create an Azure AD authenticator in Gateway.""" - - category = config["category"] - gateway_config = config["settings"] - - self._write_output(f"\n--- Processing {category} authenticator ---") - self._write_output(f"Name: {gateway_config['name']}") - self._write_output(f"Slug: {gateway_config['slug']}") - self._write_output(f"Type: {gateway_config['type']}") - - # CALLBACK_URL - automatically created by Gateway - # GROUPS_CLAIM - Not an AWX feature - # ADDITIONAL_UNVERIFIED_ARGS - Not an AWX feature - ignore_keys = ["CALLBACK_URL", "GROUPS_CLAIM"] - - # Submit the authenticator (create or update as needed) - result = self.submit_authenticator(gateway_config, ignore_keys, config) - - # Handle LOGIN_REDIRECT_OVERRIDE if applicable - valid_login_urls = ['/sso/login/azuread-oauth2'] - self.handle_login_override(config, valid_login_urls) - - return result diff --git a/awx/sso/utils/base_migrator.py b/awx/sso/utils/base_migrator.py deleted file mode 100644 index 2d3c9246cf..0000000000 --- a/awx/sso/utils/base_migrator.py +++ /dev/null @@ -1,679 +0,0 @@ -""" -Base authenticator migrator class. - -This module defines the contract that all specific authenticator migrators must follow. -""" - -from urllib.parse import urlparse, parse_qs, urlencode -from django.conf import settings -from awx.main.utils.gateway_client import GatewayAPIError - - -class BaseAuthenticatorMigrator: - """ - Base class for all authenticator migrators. - Defines the contract that all specific authenticator migrators must follow. - """ - - KEYS_TO_PRESERVE = ['idp'] - # Class-level flag to track if LOGIN_REDIRECT_OVERRIDE was set by any migrator - login_redirect_override_set_by_migrator = False - # Class-level variable to store the new LOGIN_REDIRECT_OVERRIDE URL computed by migrators - login_redirect_override_new_url = None - - def __init__(self, gateway_client=None, command=None, force=False): - """ - Initialize the authenticator migrator. - - Args: - gateway_client: GatewayClient instance for API calls - command: Optional Django management command instance (for styled output) - force: If True, force migration even if configurations already exist - """ - self.gateway_client = gateway_client - self.command = command - self.force = force - self.encrypted_fields = [ - # LDAP Fields - 'BIND_PASSWORD', - # The following authenticators all use the same key to store encrypted information: - # Generic OIDC - # RADIUS - # TACACS+ - # GitHub OAuth2 - # Azure AD OAuth2 - # Google OAuth2 - 'SECRET', - # SAML Fields - 'SP_PRIVATE_KEY', - ] - - def migrate(self): - """ - Main entry point - orchestrates the migration process. - - Returns: - dict: Summary of migration results - """ - # Get configuration from AWX/Controller - configs = self.get_controller_config() - - if not configs: - self._write_output(f'No {self.get_authenticator_type()} authenticators found to migrate.', 'warning') - return {'created': 0, 'updated': 0, 'unchanged': 0, 'failed': 0, 'mappers_created': 0, 'mappers_updated': 0, 'mappers_failed': 0} - - self._write_output(f'Found {len(configs)} {self.get_authenticator_type()} authentication configuration(s).', 'success') - - # Process each authenticator configuration - created_authenticators = [] - updated_authenticators = [] - unchanged_authenticators = [] - failed_authenticators = [] - - for config in configs: - result = self.create_gateway_authenticator(config) - if result['success']: - if result['action'] == 'created': - created_authenticators.append(config) - elif result['action'] == 'updated': - updated_authenticators.append(config) - elif result['action'] == 'skipped': - unchanged_authenticators.append(config) - else: - failed_authenticators.append(config) - - # Process mappers for successfully created/updated/unchanged authenticators - mappers_created = 0 - mappers_updated = 0 - mappers_failed = 0 - successful_authenticators = created_authenticators + updated_authenticators + unchanged_authenticators - if successful_authenticators: - self._write_output('\n=== Processing Authenticator Mappers ===', 'success') - for config in successful_authenticators: - mapper_result = self._process_gateway_mappers(config) - mappers_created += mapper_result['created'] - mappers_updated += mapper_result['updated'] - mappers_failed += mapper_result['failed'] - - # Authenticators don't have settings, so settings counts are always 0 - return { - 'created': len(created_authenticators), - 'updated': len(updated_authenticators), - 'unchanged': len(unchanged_authenticators), - 'failed': len(failed_authenticators), - 'mappers_created': mappers_created, - 'mappers_updated': mappers_updated, - 'mappers_failed': mappers_failed, - 'settings_created': 0, - 'settings_updated': 0, - 'settings_unchanged': 0, - 'settings_failed': 0, - } - - def get_controller_config(self): - """ - Gather configuration from AWX/Controller. - - Returns: - list: List of configuration dictionaries - """ - raise NotImplementedError("Subclasses must implement get_controller_config()") - - def create_gateway_authenticator(self, config): - """ - Create authenticator in Gateway. - - Args: - config: Configuration dictionary from get_controller_config() - - Returns: - bool: True if authenticator was created successfully, False otherwise - """ - raise NotImplementedError("Subclasses must implement create_gateway_authenticator()") - - def get_authenticator_type(self): - """ - Get the human-readable authenticator type name. - - Returns: - str: Authenticator type name for logging - """ - raise NotImplementedError("Subclasses must implement get_authenticator_type()") - - def _generate_authenticator_slug(self, auth_type, category): - """Generate a deterministic slug for an authenticator.""" - return f"aap-{auth_type}-{category}".lower() - - def submit_authenticator(self, gateway_config, ignore_keys=[], config={}): - """ - Submit an authenticator to Gateway - either create new or update existing. - - Args: - gateway_config: Complete Gateway authenticator configuration - ignore_keys: List of configuration keys to ignore during comparison - config: Optional AWX config dict to store result data - - Returns: - dict: Result with 'success' (bool), 'action' ('created', 'updated', 'skipped'), 'error' (str or None) - """ - authenticator_slug = gateway_config.get('slug') - if not authenticator_slug: - self._write_output('Gateway config missing slug, cannot submit authenticator', 'error') - return {'success': False, 'action': None, 'error': 'Missing slug'} - - try: - # Check if authenticator already exists by slug - existing_authenticator = self.gateway_client.get_authenticator_by_slug(authenticator_slug) - - if existing_authenticator: - # Authenticator exists, check if configuration matches - authenticator_id = existing_authenticator.get('id') - - configs_match, differences = self._authenticator_configs_match(existing_authenticator, gateway_config, ignore_keys) - - if configs_match: - self._write_output(f'⚠ Authenticator already exists with matching configuration (ID: {authenticator_id})', 'warning') - # Store the existing result for mapper creation - config['gateway_authenticator_id'] = authenticator_id - config['gateway_authenticator'] = existing_authenticator - return {'success': True, 'action': 'skipped', 'error': None} - else: - self._write_output(f'⚠ Authenticator exists but configuration differs (ID: {authenticator_id})', 'warning') - self._write_output(' Configuration comparison:') - - # Log differences between the existing and the new configuration in case of an update - for difference in differences: - self._write_output(f' {difference}') - - # Update the existing authenticator - self._write_output(' Updating authenticator with new configuration...') - try: - # Don't include the slug in the update since it shouldn't change - update_config = gateway_config.copy() - if 'slug' in update_config: - del update_config['slug'] - - result = self.gateway_client.update_authenticator(authenticator_id, update_config) - self._write_output(f'✓ Successfully updated authenticator with ID: {authenticator_id}', 'success') - - # Store the updated result for mapper creation - config['gateway_authenticator_id'] = authenticator_id - config['gateway_authenticator'] = result - return {'success': True, 'action': 'updated', 'error': None} - except GatewayAPIError as e: - self._write_output(f'✗ Failed to update authenticator: {e.message}', 'error') - if e.response_data: - self._write_output(f' Details: {e.response_data}', 'error') - return {'success': False, 'action': 'update_failed', 'error': e.message} - else: - # Authenticator doesn't exist, create it - self._write_output('Creating new authenticator...') - - # Create the authenticator - result = self.gateway_client.create_authenticator(gateway_config) - - self._write_output(f'✓ Successfully created authenticator with ID: {result.get("id")}', 'success') - - # Store the result for potential mapper creation later - config['gateway_authenticator_id'] = result.get('id') - config['gateway_authenticator'] = result - return {'success': True, 'action': 'created', 'error': None} - - except GatewayAPIError as e: - self._write_output(f'✗ Failed to submit authenticator: {e.message}', 'error') - if e.response_data: - self._write_output(f' Details: {e.response_data}', 'error') - return {'success': False, 'action': 'failed', 'error': e.message} - except Exception as e: - self._write_output(f'✗ Unexpected error submitting authenticator: {str(e)}', 'error') - return {'success': False, 'action': 'failed', 'error': str(e)} - - def _authenticator_configs_match(self, existing_auth, new_config, ignore_keys=[]): - """ - Compare existing authenticator configuration with new configuration. - - Args: - existing_auth: Existing authenticator data from Gateway - new_config: New authenticator configuration to be created - ignore_keys: List of configuration keys to ignore during comparison - (e.g., ['CALLBACK_URL'] for auto-generated fields) - - Returns: - bool: True if configurations match, False otherwise - """ - # Add encrypted fields to ignore_keys if force flag is not set - # This prevents secrets from being updated unless explicitly forced - effective_ignore_keys = ignore_keys.copy() - if not self.force: - effective_ignore_keys.extend(self.encrypted_fields) - - # Keep track of the differences between the existing and the new configuration - # Logging them makes debugging much easier - differences = [] - - if existing_auth.get('name') != new_config.get('name'): - differences.append(f' name: existing="{existing_auth.get("name")}" vs new="{new_config.get("name")}"') - elif existing_auth.get('type') != new_config.get('type'): - differences.append(f' type: existing="{existing_auth.get("type")}" vs new="{new_config.get("type")}"') - elif existing_auth.get('enabled') != new_config.get('enabled'): - differences.append(f' enabled: existing="{existing_auth.get("enabled")}" vs new="{new_config.get("enabled")}"') - elif existing_auth.get('create_objects') != new_config.get('create_objects'): - differences.append(f' create_objects: existing="{existing_auth.get("create_objects")}" vs new="{new_config.get("create_objects")}"') - elif existing_auth.get('remove_users') != new_config.get('remove_users'): - differences.append(f' create_objects: existing="{existing_auth.get("remove_users")}" vs new="{new_config.get("remove_users")}"') - - # Compare configuration section - existing_config = existing_auth.get('configuration', {}) - new_config_section = new_config.get('configuration', {}) - - # Helper function to check if a key should be ignored - def should_ignore_key(config_key): - return config_key in effective_ignore_keys - - # Check if all keys in new config exist in existing config with same values - for key, value in new_config_section.items(): - if should_ignore_key(key): - continue - if key not in existing_config: - differences.append(f' {key}: existing= vs new="{value}"') - elif existing_config[key] != value: - differences.append(f' {key}: existing="{existing_config.get(key)}" vs new="{value}"') - - # Check if existing config has extra keys that new config doesn't have - # (this might indicate configuration drift), but ignore keys in ignore_keys - for key in existing_config: - if should_ignore_key(key): - continue - if key not in new_config_section: - differences.append(f' {key}: existing="{existing_config.get(key)}" vs new=') - - return len(differences) == 0, differences - - def _compare_mapper_lists(self, existing_mappers, new_mappers, ignore_keys=None): - """ - Compare existing and new mapper lists to determine which need updates vs creation. - - Args: - existing_mappers: List of existing mapper configurations from Gateway - new_mappers: List of new mapper configurations to be created/updated - ignore_keys: List of keys to ignore during comparison (e.g., auto-generated fields) - - Returns: - tuple: (mappers_to_update, mappers_to_create) - mappers_to_update: List of tuples (existing_mapper, new_mapper) for updates - mappers_to_create: List of new_mapper configs that don't match any existing - """ - if ignore_keys is None: - ignore_keys = [] - - mappers_to_update = [] - mappers_to_create = [] - - for new_mapper in new_mappers: - matched_existing = None - - # Try to find a matching existing mapper - for existing_mapper in existing_mappers: - if self._mappers_match_structurally(existing_mapper, new_mapper): - matched_existing = existing_mapper - break - - if matched_existing: - # Check if the configuration actually differs (ignoring auto-generated fields) - if not self._mapper_configs_match(matched_existing, new_mapper, ignore_keys): - mappers_to_update.append((matched_existing, new_mapper)) - # If configs match exactly, no action needed (mapper is up to date) - else: - # No matching existing mapper found, needs to be created - mappers_to_create.append(new_mapper) - - return mappers_to_update, mappers_to_create - - def _mappers_match_structurally(self, existing_mapper, new_mapper): - """ - Check if two mappers match structurally (same organization, team, map_type, role). - This identifies if they represent the same logical mapping. - - Args: - existing_mapper: Existing mapper configuration from Gateway - new_mapper: New mapper configuration - - Returns: - bool: True if mappers represent the same logical mapping - """ - - # Compare key structural fields that identify the same logical mapper - structural_fields = ['name'] - - for field in structural_fields: - if existing_mapper.get(field) != new_mapper.get(field): - return False - - return True - - def _mapper_configs_match(self, existing_mapper, new_mapper, ignore_keys=None): - """ - Compare mapper configurations to check if they are identical. - - Args: - existing_mapper: Existing mapper configuration from Gateway - new_mapper: New mapper configuration - ignore_keys: List of keys to ignore during comparison - - Returns: - bool: True if configurations match, False otherwise - """ - if ignore_keys is None: - ignore_keys = [] - - # Helper function to check if a key should be ignored - def should_ignore_key(config_key): - return config_key in ignore_keys - - # Compare all mapper fields except ignored ones - all_keys = set(existing_mapper.keys()) | set(new_mapper.keys()) - - for key in all_keys: - if should_ignore_key(key): - continue - - existing_value = existing_mapper.get(key) - new_value = new_mapper.get(key) - - if existing_value != new_value: - return False - - return True - - def _process_gateway_mappers(self, config): - """Process authenticator mappers in Gateway from AWX config - create or update as needed.""" - authenticator_id = config.get('gateway_authenticator_id') - if not authenticator_id: - self._write_output(f'No authenticator ID found for {config["category"]}, skipping mappers', 'error') - return {'created': 0, 'updated': 0, 'failed': 0} - - category = config['category'] - org_mappers = config.get('org_mappers', []) - team_mappers = config.get('team_mappers', []) - role_mappers = config.get('role_mappers', []) - allow_mappers = config.get('allow_mappers', []) - all_new_mappers = org_mappers + team_mappers + role_mappers + allow_mappers - - if len(all_new_mappers) == 0: - self._write_output(f'No mappers to process for {category} authenticator') - return {'created': 0, 'updated': 0, 'failed': 0} - - self._write_output(f'\n--- Processing mappers for {category} authenticator (ID: {authenticator_id}) ---') - self._write_output(f'Organization mappers: {len(org_mappers)}') - self._write_output(f'Team mappers: {len(team_mappers)}') - self._write_output(f'Role mappers: {len(role_mappers)}') - self._write_output(f'Allow mappers: {len(allow_mappers)}') - - # Get existing mappers from Gateway - try: - existing_mappers = self.gateway_client.get_authenticator_maps(authenticator_id) - except GatewayAPIError as e: - self._write_output(f'Failed to retrieve existing mappers: {e.message}', 'error') - return {'created': 0, 'updated': 0, 'failed': len(all_new_mappers)} - - # Define mapper-specific ignore keys (can be overridden by subclasses) - ignore_keys = self._get_mapper_ignore_keys() - - # Compare existing vs new mappers - mappers_to_update, mappers_to_create = self._compare_mapper_lists(existing_mappers, all_new_mappers, ignore_keys) - - self._write_output(f'Mappers to create: {len(mappers_to_create)}') - self._write_output(f'Mappers to update: {len(mappers_to_update)}') - - created_count = 0 - updated_count = 0 - failed_count = 0 - - # Process updates - for existing_mapper, new_mapper in mappers_to_update: - if self._update_single_mapper(existing_mapper, new_mapper): - updated_count += 1 - else: - failed_count += 1 - - # Process creations - for new_mapper in mappers_to_create: - mapper_type = new_mapper.get('map_type', 'unknown') - if self._create_single_mapper(authenticator_id, new_mapper, mapper_type): - created_count += 1 - else: - failed_count += 1 - - # Summary - self._write_output(f'Mappers created: {created_count}, updated: {updated_count}, failed: {failed_count}') - return {'created': created_count, 'updated': updated_count, 'failed': failed_count} - - def _get_mapper_ignore_keys(self): - """ - Get list of mapper keys to ignore during comparison. - Can be overridden by subclasses for mapper-specific ignore keys. - - Returns: - list: List of keys to ignore (e.g., auto-generated fields) - """ - return ['id', 'authenticator', 'created', 'modified', 'summary_fields', 'modified_by', 'created_by', 'related', 'url'] - - def _update_single_mapper(self, existing_mapper, new_mapper): - """Update a single mapper in Gateway. - - Args: - existing_mapper: Existing mapper data from Gateway - new_mapper: New mapper configuration to update to - - Returns: - bool: True if mapper was updated successfully, False otherwise - """ - try: - mapper_id = existing_mapper.get('id') - if not mapper_id: - self._write_output(' ✗ Existing mapper missing ID, cannot update', 'error') - return False - - # Prepare update config - don't include fields that shouldn't be updated - update_config = new_mapper.copy() - - # Remove fields that shouldn't be updated (read-only or auto-generated) - fields_to_remove = ['id', 'authenticator', 'created', 'modified'] - for field in fields_to_remove: - update_config.pop(field, None) - - # Update the mapper - self.gateway_client.update_authenticator_map(mapper_id, update_config) - - mapper_name = new_mapper.get('name', 'Unknown') - self._write_output(f' ✓ Updated mapper: {mapper_name}', 'success') - return True - - except GatewayAPIError as e: - mapper_name = new_mapper.get('name', 'Unknown') - self._write_output(f' ✗ Failed to update mapper "{mapper_name}": {e.message}', 'error') - if e.response_data: - self._write_output(f' Details: {e.response_data}', 'error') - return False - except Exception as e: - mapper_name = new_mapper.get('name', 'Unknown') - self._write_output(f' ✗ Unexpected error updating mapper "{mapper_name}": {str(e)}', 'error') - return False - - def _create_single_mapper(self, authenticator_id, mapper_config, mapper_type): - """Create a single mapper in Gateway.""" - try: - # Update the mapper config with the correct authenticator ID - mapper_config = mapper_config.copy() # Don't modify the original - mapper_config['authenticator'] = authenticator_id - - # Create the mapper - self.gateway_client.create_authenticator_map(authenticator_id, mapper_config) - - mapper_name = mapper_config.get('name', 'Unknown') - self._write_output(f' ✓ Created {mapper_type} mapper: {mapper_name}', 'success') - return True - - except GatewayAPIError as e: - mapper_name = mapper_config.get('name', 'Unknown') - self._write_output(f' ✗ Failed to create {mapper_type} mapper "{mapper_name}": {e.message}', 'error') - if e.response_data: - self._write_output(f' Details: {e.response_data}', 'error') - return False - except Exception as e: - mapper_name = mapper_config.get('name', 'Unknown') - 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=None): - """ - 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 - if authenticator_setting_name: - if authenticator_map := getattr(settings, authenticator_setting_name, None): - 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=None): - """ - 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 - if authenticator_setting_name: - if authenticator_map := getattr(settings, authenticator_setting_name, None): - return authenticator_map - - # Fall back to global setting - global_map = getattr(settings, 'SOCIAL_AUTH_TEAM_MAP', {}) - return global_map - - def handle_login_override(self, config, valid_login_urls): - """ - Handle LOGIN_REDIRECT_OVERRIDE setting for this authenticator. - - This method checks if the login_redirect_override from the config matches - any of the provided valid_login_urls. If it matches, it updates the - LOGIN_REDIRECT_OVERRIDE setting in Gateway with the new authenticator's - URL and sets the class flag to indicate it was handled. - - Args: - config: Configuration dictionary containing: - - login_redirect_override: The current LOGIN_REDIRECT_OVERRIDE value - - gateway_authenticator: The created/updated authenticator info - valid_login_urls: List of URL patterns to match against - """ - # Check if another migrator has already handled login redirect override - if BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator: - raise RuntimeError("LOGIN_REDIRECT_OVERRIDE has already been handled by another migrator") - - login_redirect_override = config.get('login_redirect_override') - if not login_redirect_override: - return - - # Check if the login_redirect_override matches any of the provided valid URLs - url_matches = False - parsed_redirect = urlparse(login_redirect_override) - self.redirect_query_dict = parse_qs(parsed_redirect.query, keep_blank_values=True) if parsed_redirect.query else {} - - for valid_url in valid_login_urls: - parsed_valid = urlparse(valid_url) - - # Compare path: redirect path should match or contain the valid path at proper boundaries - if parsed_redirect.path == parsed_valid.path: - path_matches = True - elif parsed_redirect.path.startswith(parsed_valid.path): - # Ensure the match is at a path boundary (followed by '/' or end of string) - next_char_pos = len(parsed_valid.path) - if next_char_pos >= len(parsed_redirect.path) or parsed_redirect.path[next_char_pos] in ['/', '?']: - path_matches = True - else: - path_matches = False - else: - path_matches = False - - # Compare query: if valid URL has query params, they should be present in redirect URL - query_matches = True - if parsed_valid.query: - # Parse query parameters for both URLs - valid_params = parse_qs(parsed_valid.query, keep_blank_values=True) - - # All valid URL query params must be present in redirect URL with same values - query_matches = all(param in self.redirect_query_dict and self.redirect_query_dict[param] == values for param, values in valid_params.items()) - - if path_matches and query_matches: - url_matches = True - break - - if not url_matches: - return - - # Extract the created authenticator from config - gateway_authenticator = config.get('gateway_authenticator') - if not gateway_authenticator: - return - - sso_login_url = gateway_authenticator.get('sso_login_url') - if not sso_login_url: - return - - # Compute the new LOGIN_REDIRECT_OVERRIDE URL with the Gateway URL - gateway_base_url = self.gateway_client.get_base_url() - parsed_sso = urlparse(sso_login_url) - parsed_gw = urlparse(gateway_base_url) - updated_query = self._updated_query_string(parsed_sso) - complete_url = parsed_redirect._replace(scheme=parsed_gw.scheme, path=parsed_sso.path, netloc=parsed_gw.netloc, query=updated_query).geturl() - self._write_output(f'LOGIN_REDIRECT_OVERRIDE will be updated to: {complete_url}') - - # Store the new URL in class variable for settings migrator to use - BaseAuthenticatorMigrator.login_redirect_override_new_url = complete_url - - # Set the class-level flag to indicate LOGIN_REDIRECT_OVERRIDE was handled by a migrator - BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator = True - - def _updated_query_string(self, parsed_sso): - if parsed_sso.query: - parsed_sso_dict = parse_qs(parsed_sso.query, keep_blank_values=True) - else: - parsed_sso_dict = {} - - result = {} - for k, v in self.redirect_query_dict.items(): - if k in self.KEYS_TO_PRESERVE and k in parsed_sso_dict: - v = parsed_sso_dict[k] - - if isinstance(v, list) and len(v) == 1: - result[k] = v[0] - else: - result[k] = v - - return urlencode(result, doseq=True) if result else "" - - def _write_output(self, message, style=None): - """Write output message if command is available.""" - if self.command: - if style == 'success': - self.command.stdout.write(self.command.style.SUCCESS(message)) - elif style == 'warning': - self.command.stdout.write(self.command.style.WARNING(message)) - elif style == 'error': - self.command.stdout.write(self.command.style.ERROR(message)) - else: - self.command.stdout.write(message) diff --git a/awx/sso/utils/github_migrator.py b/awx/sso/utils/github_migrator.py deleted file mode 100644 index 01057740c2..0000000000 --- a/awx/sso/utils/github_migrator.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -GitHub authenticator migrator. - -This module handles the migration of GitHub authenticators from AWX to Gateway. -""" - -from django.conf import settings -from awx.conf import settings_registry -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 -import re - - -class GitHubMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of GitHub authenticators from AWX to Gateway. - """ - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "GitHub" - - def get_controller_config(self): - """ - Export all GitHub authenticators. A GitHub authenticator is only exported if both, - id and secret, are defined. Otherwise it will be skipped. - - Returns: - list: List of configured GitHub authentication providers with their settings - """ - github_categories = ['github', 'github-org', 'github-team', 'github-enterprise', 'github-enterprise-org', 'github-enterprise-team'] - login_redirect_override = getattr(settings, "LOGIN_REDIRECT_OVERRIDE", None) - - found_configs = [] - - for category in github_categories: - try: - category_settings = settings_registry.get_registered_settings(category_slug=category) - if category_settings: - config_data = {} - - key_setting = None - secret_setting = None - - # Ensure category_settings is iterable and contains strings - if isinstance(category_settings, re.Pattern) or not hasattr(category_settings, '__iter__') or isinstance(category_settings, str): - continue - - for setting_name in category_settings: - # Skip if setting_name is not a string (e.g., regex pattern) - if not isinstance(setting_name, str): - continue - if setting_name.endswith('_KEY'): - key_setting = setting_name - elif setting_name.endswith('_SECRET'): - secret_setting = setting_name - - # Skip this category if KEY or SECRET is missing or empty - if not key_setting or not secret_setting: - continue - - key_value = getattr(settings, key_setting, None) - secret_value = getattr(settings, secret_setting, None) - - # Skip this category if OIDC Key and/or Secret are not configured - if not key_value or not secret_value: - continue - - # If we have both key and secret, collect all settings - 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) - if not isinstance(setting_name, str): - continue - value = getattr(settings, setting_name, None) - config_data[setting_name] = value - - # Capture org and team map setting names for special processing - if setting_name.endswith('_ORGANIZATION_MAP'): - org_map_setting_name = setting_name - elif setting_name.endswith('_TEAM_MAP'): - 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 - 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) - - found_configs.append( - { - 'category': category, - 'settings': config_data, - 'org_mappers': org_mappers, - 'team_mappers': team_mappers, - 'login_redirect_override': login_redirect_override, - } - ) - - except Exception as e: - raise Exception(f'Could not retrieve {category} settings: {str(e)}') - - return found_configs - - def create_gateway_authenticator(self, config): - """Create a GitHub/OIDC authenticator in Gateway.""" - category = config['category'] - settings = config['settings'] - - # Extract the OAuth2 credentials - key_value = None - secret_value = None - - for setting_name, value in settings.items(): - if setting_name.endswith('_KEY') and value: - key_value = value - elif setting_name.endswith('_SECRET') and value: - secret_value = value - - if not key_value or not secret_value: - self._write_output(f'Skipping {category}: missing OAuth2 credentials', 'warning') - return {'success': False, 'action': 'skipped', 'error': 'Missing OAuth2 credentials'} - - # Generate authenticator name and slug - authenticator_name = category - authenticator_slug = self._generate_authenticator_slug('github', category) - - # Map AWX category to Gateway authenticator type - type_mapping = { - 'github': 'ansible_base.authentication.authenticator_plugins.github', - 'github-org': 'ansible_base.authentication.authenticator_plugins.github_org', - 'github-team': 'ansible_base.authentication.authenticator_plugins.github_team', - 'github-enterprise': 'ansible_base.authentication.authenticator_plugins.github_enterprise', - 'github-enterprise-org': 'ansible_base.authentication.authenticator_plugins.github_enterprise_org', - 'github-enterprise-team': 'ansible_base.authentication.authenticator_plugins.github_enterprise_team', - } - - authenticator_type = type_mapping.get(category) - if not authenticator_type: - self._write_output(f'Unknown category {category}, skipping', 'warning') - return {'success': False, 'action': 'skipped', 'error': f'Unknown category {category}'} - - self._write_output(f'\n--- Processing {category} authenticator ---') - self._write_output(f'Name: {authenticator_name}') - self._write_output(f'Slug: {authenticator_slug}') - self._write_output(f'Type: {authenticator_type}') - self._write_output(f'Client ID: {key_value}') - self._write_output(f'Client Secret: {"*" * 8}') - - # Build Gateway authenticator configuration - gateway_config = { - "name": authenticator_name, - "slug": authenticator_slug, - "type": authenticator_type, - "enabled": False, - "create_objects": True, # Allow Gateway to create users/orgs/teams - "remove_users": False, # Don't remove users by default - "configuration": {"KEY": key_value, "SECRET": secret_value}, - } - - # Add any additional configuration based on AWX settings - additional_config = self._build_additional_config(category, settings) - gateway_config["configuration"].update(additional_config) - - # GitHub authenticators have auto-generated fields that should be ignored during comparison - # CALLBACK_URL - automatically created by Gateway - # SCOPE - relevant for mappers with team/org requirement, allows to read the org or team - # 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) - result = self.submit_authenticator(gateway_config, ignore_keys, config) - - # Handle LOGIN_REDIRECT_OVERRIDE if applicable - valid_login_urls = [f'/sso/login/{category}', f'/sso/login/{category}/'] - self.handle_login_override(config, valid_login_urls) - - return result - - def _build_additional_config(self, category, settings): - """Build additional configuration for specific authenticator types.""" - additional_config = {} - - # Add scope configuration if present - for setting_name, value in settings.items(): - if setting_name.endswith('_SCOPE') and value: - additional_config['SCOPE'] = value - break - - # Add GitHub Enterprise URL if present - if 'enterprise' in category: - for setting_name, value in settings.items(): - if setting_name.endswith('_API_URL') and value: - additional_config['API_URL'] = value - elif setting_name.endswith('_URL') and value: - additional_config['URL'] = value - - # Add organization name for org-specific authenticators - if 'org' in category: - for setting_name, value in settings.items(): - if setting_name.endswith('_NAME') and value: - additional_config['NAME'] = value - break - - # Add team ID for team-specific authenticators - if 'team' in category: - for setting_name, value in settings.items(): - if setting_name.endswith('_ID') and value: - additional_config['ID'] = value - break - - return additional_config diff --git a/awx/sso/utils/google_oauth2_migrator.py b/awx/sso/utils/google_oauth2_migrator.py deleted file mode 100644 index 7d47f532a3..0000000000 --- a/awx/sso/utils/google_oauth2_migrator.py +++ /dev/null @@ -1,102 +0,0 @@ -""" -Google OAuth2 authenticator migrator. - -This module handles the migration of Google OAuth2 authenticators from AWX to Gateway. -""" - -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 - - -class GoogleOAuth2Migrator(BaseAuthenticatorMigrator): - """ - Handles the migration of Google OAuth2 authenticators from AWX to Gateway. - """ - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "Google OAuth2" - - def get_controller_config(self): - """ - Export Google OAuth2 authenticators. A Google OAuth2 authenticator is only exported if - KEY and SECRET are configured. - - Returns: - list: List of configured Google OAuth2 authentication providers with their settings - """ - from django.conf import settings - - if not getattr(settings, 'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY', None): - return [] - - config_data = { - 'SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL, - 'SOCIAL_AUTH_GOOGLE_OAUTH2_KEY': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY, - 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET, - 'SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE, - } - - login_redirect_override = getattr(settings, "LOGIN_REDIRECT_OVERRIDE", None) - - return [ - { - "category": self.get_authenticator_type(), - "settings": config_data, - "login_redirect_override": login_redirect_override, - } - ] - - def _build_mappers(self): - org_map = self.get_social_org_map('SOCIAL_AUTH_GOOGLE_OAUTH2_ORGANIZATION_MAP') - team_map = self.get_social_team_map('SOCIAL_AUTH_GOOGLE_OAUTH2_TEAM_MAP') - - mappers, order = org_map_to_gateway_format(org_map, 1) - team_mappers, _ = team_map_to_gateway_format(team_map, order) - - mappers.extend(team_mappers) - - return mappers - - def create_gateway_authenticator(self, config): - """Create a Google OAuth2 authenticator in Gateway.""" - category = config["category"] - config_settings = config['settings'] - - authenticator_slug = self._generate_authenticator_slug('google-oauth2', category.replace(" ", "-")) - - self._write_output(f"\n--- Processing {category} authenticator ---") - - gateway_config = { - "name": "google", - "slug": authenticator_slug, - "type": "ansible_base.authentication.authenticator_plugins.google_oauth2", - "enabled": False, - "create_objects": True, # Allow Gateway to create users/orgs/teams - "remove_users": False, # Don't remove users by default - "configuration": { - "KEY": config_settings.get('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY'), - "SECRET": config_settings.get('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET'), - "REDIRECT_STATE": True, - }, - "mappers": self._build_mappers(), - } - - ignore_keys = ["ACCESS_TOKEN_METHOD", "REVOKE_TOKEN_METHOD"] - optional = { - "CALLBACK_URL": config_settings.get('SOCIAL_AUTH_GOOGLE_OAUTH2_CALLBACK_URL'), - "SCOPE": config_settings.get('SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE'), - } - for key, value in optional.items(): - if value: - gateway_config["configuration"][key] = value - else: - ignore_keys.append(key) - - result = self.submit_authenticator(gateway_config, ignore_keys, config) - - # Handle LOGIN_REDIRECT_OVERRIDE if applicable - valid_login_urls = ['/sso/login/google-oauth2'] - self.handle_login_override(config, valid_login_urls) - - return result diff --git a/awx/sso/utils/ldap_migrator.py b/awx/sso/utils/ldap_migrator.py deleted file mode 100644 index de06d34888..0000000000 --- a/awx/sso/utils/ldap_migrator.py +++ /dev/null @@ -1,368 +0,0 @@ -""" -LDAP authenticator migrator. - -This module handles the migration of LDAP 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, role_map_to_gateway_format -from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator -import ldap - - -class LDAPMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of LDAP authenticators from AWX to Gateway. - """ - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "LDAP" - - def get_controller_config(self): - """ - Export all LDAP authenticators. An LDAP authenticator is only exported if - SERVER_URI is configured. Otherwise it will be skipped. - - Returns: - list: List of configured LDAP authentication providers with their settings - """ - # AWX supports up to 6 LDAP configurations: AUTH_LDAP (default) and AUTH_LDAP_1 through AUTH_LDAP_5 - ldap_instances = [None, 1, 2, 3, 4, 5] # None represents the default AUTH_LDAP_ configuration - found_configs = [] - - for instance in ldap_instances: - # Build the prefix for this LDAP instance - prefix = f"AUTH_LDAP_{instance}_" if instance is not None else "AUTH_LDAP_" - # The authenticator category is always "ldap" - category = "ldap" - - try: - # Get all LDAP settings for this instance - config_data = self._get_ldap_instance_config(prefix) - except Exception as e: - raise Exception(f'Could not retrieve {category} settings: {str(e)}') - - # Skip if SERVER_URI is not configured (required for LDAP to function) - if not config_data.get('SERVER_URI'): - continue - - # Convert organization, team, and role mappings to Gateway format - org_map_value = config_data.get('ORGANIZATION_MAP', {}) - team_map_value = config_data.get('TEAM_MAP', {}) - role_map_value = config_data.get('USER_FLAGS_BY_GROUP', {}) - require_group_value = config_data.get('REQUIRE_GROUP', {}) - deny_group_value = config_data.get('DENY_GROUP', {}) - - allow_mappers = [] - - # Start with order 1 and maintain sequence across org, team, and role mappers - allow_mappers, next_order = self._ldap_group_allow_to_gateway_format(allow_mappers, deny_group_value, deny=True, start_order=1) - allow_mappers, next_order = self._ldap_group_allow_to_gateway_format(allow_mappers, require_group_value, deny=False, start_order=next_order) - - org_mappers, next_order = org_map_to_gateway_format(org_map_value, start_order=next_order, auth_type='ldap') - team_mappers, next_order = team_map_to_gateway_format(team_map_value, start_order=next_order, auth_type='ldap') - role_mappers, _ = role_map_to_gateway_format(role_map_value, start_order=next_order) - - found_configs.append( - { - 'category': category, - 'settings': config_data, - 'org_mappers': org_mappers, - 'team_mappers': team_mappers, - 'role_mappers': role_mappers, - 'allow_mappers': allow_mappers, - } - ) - - return found_configs - - def _get_ldap_instance_config(self, prefix): - """ - Get all LDAP configuration settings for a specific instance. - - Args: - prefix: The setting prefix (e.g., 'AUTH_LDAP_' or 'AUTH_LDAP_1_') - - Returns: - dict: Dictionary of LDAP configuration settings - """ - # Define all LDAP setting keys - ldap_keys = [ - 'SERVER_URI', # Required: LDAP server URI(s) - 'BIND_DN', # Optional: Bind DN for authentication - 'BIND_PASSWORD', # Optional: Bind password - 'START_TLS', # Optional: Enable TLS - 'CONNECTION_OPTIONS', # Optional: LDAP connection options - 'USER_SEARCH', # Optional: User search configuration - 'USER_DN_TEMPLATE', # Optional: User DN template - 'USER_ATTR_MAP', # Optional: User attribute mapping - 'GROUP_SEARCH', # Optional: Group search configuration - 'GROUP_TYPE', # Optional: Group type class - 'GROUP_TYPE_PARAMS', # Optional: Group type parameters - 'REQUIRE_GROUP', # Optional: Required group DN - 'DENY_GROUP', # Optional: Denied group DN - 'USER_FLAGS_BY_GROUP', # Optional: User flags mapping - 'ORGANIZATION_MAP', # Optional: Organization mapping - 'TEAM_MAP', # Optional: Team mapping - ] - - config_data = {} - - for key in ldap_keys: - setting_name = f"{prefix}{key}" - value = getattr(settings, setting_name, None) - - # Handle special field types that need conversion - if key == 'GROUP_TYPE' and value: - # Convert GROUP_TYPE class to string representation - config_data[key] = type(value).__name__ - elif key == 'SERVER_URI' and value: - # Convert SERVER_URI to list format if it's a comma-separated string - config_data[key] = [uri.strip() for uri in value.split(',')] - elif key in ['USER_SEARCH', 'GROUP_SEARCH'] and value: - # Convert LDAPSearch objects to list format [base_dn, scope, filter] - if hasattr(value, 'base_dn') and hasattr(value, 'filterstr'): - # Get the actual scope instead of hardcoding SCOPE_SUBTREE - scope = getattr(value, 'scope', ldap.SCOPE_SUBTREE) # 2 is SCOPE_SUBTREE default - scope_name = {ldap.SCOPE_BASE: 'SCOPE_BASE', ldap.SCOPE_ONELEVEL: 'SCOPE_ONELEVEL', ldap.SCOPE_SUBTREE: 'SCOPE_SUBTREE'}.get( - scope, 'SCOPE_SUBTREE' - ) - config_data[key] = [value.base_dn, scope_name, value.filterstr] - else: - config_data[key] = value - elif key in ['USER_ATTR_MAP', 'GROUP_TYPE_PARAMS', 'USER_FLAGS_BY_GROUP', 'ORGANIZATION_MAP', 'TEAM_MAP']: - # Ensure dict fields are properly handled - config_data[key] = value if value is not None else {} - elif key == 'CONNECTION_OPTIONS' and value: - # CONNECTION_OPTIONS is a dict of LDAP options - config_data[key] = value if value is not None else {} - else: - # Store the value as-is for other fields - config_data[key] = value - - return config_data - - def create_gateway_authenticator(self, config): - """Create an LDAP authenticator in Gateway.""" - category = config['category'] - settings = config['settings'] - - # Extract the first server URI for slug generation - authenticator_slug = self._generate_authenticator_slug('ldap', category) - - # Build the gateway payload - gateway_config = { - 'name': category, - 'slug': authenticator_slug, - 'type': 'ansible_base.authentication.authenticator_plugins.ldap', - 'create_objects': True, - 'remove_users': False, - 'enabled': True, - 'configuration': self._build_ldap_configuration(settings), - } - - self._write_output(f'Creating LDAP authenticator: {gateway_config["name"]}') - - # LDAP authenticators have auto-generated fields that should be ignored during comparison - # BIND_PASSWORD - encrypted value, can't be compared - ignore_keys = [] - - # Submit the authenticator using the base class method - return self.submit_authenticator(gateway_config, config=config, ignore_keys=ignore_keys) - - def _build_ldap_configuration(self, settings): - """Build the LDAP configuration section for Gateway.""" - config = {} - - # Server URI is required - if settings.get('SERVER_URI'): - config['SERVER_URI'] = settings['SERVER_URI'] - - # Authentication settings - if settings.get('BIND_DN'): - config['BIND_DN'] = settings['BIND_DN'] - if settings.get('BIND_PASSWORD'): - config['BIND_PASSWORD'] = settings['BIND_PASSWORD'] - - # TLS settings - if settings.get('START_TLS') is not None: - config['START_TLS'] = settings['START_TLS'] - - # User search configuration - if settings.get('USER_SEARCH'): - config['USER_SEARCH'] = settings['USER_SEARCH'] - - # User attribute mapping - if settings.get('USER_ATTR_MAP'): - config['USER_ATTR_MAP'] = settings['USER_ATTR_MAP'] - - # Group search configuration - if settings.get('GROUP_SEARCH'): - config['GROUP_SEARCH'] = settings['GROUP_SEARCH'] - - # Group type and parameters - if settings.get('GROUP_TYPE'): - config['GROUP_TYPE'] = settings['GROUP_TYPE'] - if settings.get('GROUP_TYPE_PARAMS'): - config['GROUP_TYPE_PARAMS'] = settings['GROUP_TYPE_PARAMS'] - - # Connection options - convert numeric LDAP constants to string keys - if settings.get('CONNECTION_OPTIONS'): - config['CONNECTION_OPTIONS'] = self._convert_ldap_connection_options(settings['CONNECTION_OPTIONS']) - - # User DN template - if settings.get('USER_DN_TEMPLATE'): - config['USER_DN_TEMPLATE'] = settings['USER_DN_TEMPLATE'] - - # REQUIRE_GROUP and DENY_GROUP are handled as allow mappers, not included in config - # USER_FLAGS_BY_GROUP is handled as role mappers, not included in config - - return config - - def _convert_ldap_connection_options(self, connection_options): - """ - Convert numeric LDAP connection option constants to their string representations. - Uses the actual constants from the python-ldap library. - - Args: - connection_options: Dictionary with numeric LDAP option keys - - Returns: - dict: Dictionary with string LDAP option keys - """ - # Comprehensive mapping using LDAP constants as keys - ldap_option_map = { - # Basic LDAP options - ldap.OPT_API_INFO: 'OPT_API_INFO', - ldap.OPT_DEREF: 'OPT_DEREF', - ldap.OPT_SIZELIMIT: 'OPT_SIZELIMIT', - ldap.OPT_TIMELIMIT: 'OPT_TIMELIMIT', - ldap.OPT_REFERRALS: 'OPT_REFERRALS', - ldap.OPT_RESULT_CODE: 'OPT_RESULT_CODE', - ldap.OPT_ERROR_NUMBER: 'OPT_ERROR_NUMBER', - ldap.OPT_RESTART: 'OPT_RESTART', - ldap.OPT_PROTOCOL_VERSION: 'OPT_PROTOCOL_VERSION', - ldap.OPT_SERVER_CONTROLS: 'OPT_SERVER_CONTROLS', - ldap.OPT_CLIENT_CONTROLS: 'OPT_CLIENT_CONTROLS', - ldap.OPT_API_FEATURE_INFO: 'OPT_API_FEATURE_INFO', - ldap.OPT_HOST_NAME: 'OPT_HOST_NAME', - ldap.OPT_DESC: 'OPT_DESC', - ldap.OPT_DIAGNOSTIC_MESSAGE: 'OPT_DIAGNOSTIC_MESSAGE', - ldap.OPT_ERROR_STRING: 'OPT_ERROR_STRING', - ldap.OPT_MATCHED_DN: 'OPT_MATCHED_DN', - ldap.OPT_DEBUG_LEVEL: 'OPT_DEBUG_LEVEL', - ldap.OPT_TIMEOUT: 'OPT_TIMEOUT', - ldap.OPT_REFHOPLIMIT: 'OPT_REFHOPLIMIT', - ldap.OPT_NETWORK_TIMEOUT: 'OPT_NETWORK_TIMEOUT', - ldap.OPT_URI: 'OPT_URI', - # TLS options - ldap.OPT_X_TLS: 'OPT_X_TLS', - ldap.OPT_X_TLS_CTX: 'OPT_X_TLS_CTX', - ldap.OPT_X_TLS_CACERTFILE: 'OPT_X_TLS_CACERTFILE', - ldap.OPT_X_TLS_CACERTDIR: 'OPT_X_TLS_CACERTDIR', - ldap.OPT_X_TLS_CERTFILE: 'OPT_X_TLS_CERTFILE', - ldap.OPT_X_TLS_KEYFILE: 'OPT_X_TLS_KEYFILE', - ldap.OPT_X_TLS_REQUIRE_CERT: 'OPT_X_TLS_REQUIRE_CERT', - ldap.OPT_X_TLS_CIPHER_SUITE: 'OPT_X_TLS_CIPHER_SUITE', - ldap.OPT_X_TLS_RANDOM_FILE: 'OPT_X_TLS_RANDOM_FILE', - ldap.OPT_X_TLS_DHFILE: 'OPT_X_TLS_DHFILE', - ldap.OPT_X_TLS_NEVER: 'OPT_X_TLS_NEVER', - ldap.OPT_X_TLS_HARD: 'OPT_X_TLS_HARD', - ldap.OPT_X_TLS_DEMAND: 'OPT_X_TLS_DEMAND', - ldap.OPT_X_TLS_ALLOW: 'OPT_X_TLS_ALLOW', - ldap.OPT_X_TLS_TRY: 'OPT_X_TLS_TRY', - ldap.OPT_X_TLS_CRL_NONE: 'OPT_X_TLS_CRL_NONE', - ldap.OPT_X_TLS_CRL_PEER: 'OPT_X_TLS_CRL_PEER', - ldap.OPT_X_TLS_CRL_ALL: 'OPT_X_TLS_CRL_ALL', - # SASL options - ldap.OPT_X_SASL_MECH: 'OPT_X_SASL_MECH', - ldap.OPT_X_SASL_REALM: 'OPT_X_SASL_REALM', - ldap.OPT_X_SASL_AUTHCID: 'OPT_X_SASL_AUTHCID', - ldap.OPT_X_SASL_AUTHZID: 'OPT_X_SASL_AUTHZID', - ldap.OPT_X_SASL_SSF: 'OPT_X_SASL_SSF', - ldap.OPT_X_SASL_SSF_EXTERNAL: 'OPT_X_SASL_SSF_EXTERNAL', - ldap.OPT_X_SASL_SECPROPS: 'OPT_X_SASL_SECPROPS', - ldap.OPT_X_SASL_SSF_MIN: 'OPT_X_SASL_SSF_MIN', - ldap.OPT_X_SASL_SSF_MAX: 'OPT_X_SASL_SSF_MAX', - } - - # Add optional options that may not be available in all versions - optional_options = [ - 'OPT_TCP_USER_TIMEOUT', - 'OPT_DEFBASE', - 'OPT_X_TLS_VERSION', - 'OPT_X_TLS_CIPHER', - 'OPT_X_TLS_PEERCERT', - 'OPT_X_TLS_CRLCHECK', - 'OPT_X_TLS_CRLFILE', - 'OPT_X_TLS_NEWCTX', - 'OPT_X_TLS_PROTOCOL_MIN', - 'OPT_X_TLS_PACKAGE', - 'OPT_X_TLS_ECNAME', - 'OPT_X_TLS_REQUIRE_SAN', - 'OPT_X_TLS_PROTOCOL_MAX', - 'OPT_X_TLS_PROTOCOL_SSL3', - 'OPT_X_TLS_PROTOCOL_TLS1_0', - 'OPT_X_TLS_PROTOCOL_TLS1_1', - 'OPT_X_TLS_PROTOCOL_TLS1_2', - 'OPT_X_TLS_PROTOCOL_TLS1_3', - 'OPT_X_SASL_NOCANON', - 'OPT_X_SASL_USERNAME', - 'OPT_CONNECT_ASYNC', - 'OPT_X_KEEPALIVE_IDLE', - 'OPT_X_KEEPALIVE_PROBES', - 'OPT_X_KEEPALIVE_INTERVAL', - ] - - for option_name in optional_options: - if hasattr(ldap, option_name): - ldap_option_map[getattr(ldap, option_name)] = option_name - - converted_options = {} - - for key, value in connection_options.items(): - if key in ldap_option_map: - converted_options[ldap_option_map[key]] = value - - return converted_options - - def _ldap_group_allow_to_gateway_format(self, result: list, ldap_group: str, deny=False, start_order=1): - """Convert an LDAP require or deny group to a Gateway mapper - - Args: - result: array to append the mapper to - ldap_group: An LDAP group query - deny: Whether the mapper denies or requires users to be in the group - start_order: Starting order value for the mappers - - Returns: - tuple: (List of Gateway-compatible organization mappers, next_order) - """ - if ldap_group is None: - return result, start_order - - if deny: - result.append( - { - "name": "LDAP-DenyGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": True, - "triggers": {"groups": {"has_or": [ldap_group]}}, - "order": start_order, - } - ) - else: - result.append( - { - "name": "LDAP-RequireGroup", - "authenticator": -1, - "map_type": "allow", - "revoke": False, - "triggers": {"groups": {"has_and": [ldap_group]}}, - "order": start_order, - } - ) - - return result, start_order + 1 diff --git a/awx/sso/utils/oidc_migrator.py b/awx/sso/utils/oidc_migrator.py deleted file mode 100644 index f0802234d7..0000000000 --- a/awx/sso/utils/oidc_migrator.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -Generic OIDC authenticator migrator. - -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 - - -class OIDCMigrator(BaseAuthenticatorMigrator): - """ - 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): - """Get the human-readable authenticator type name.""" - return "OIDC" - - def get_controller_config(self): - """ - Export generic OIDC authenticators. An OIDC authenticator is only exported if both, - key and secret, are defined. Otherwise it will be skipped. - - Returns: - list: List of configured OIDC authentication providers with their settings - """ - key_value = getattr(settings, "SOCIAL_AUTH_OIDC_KEY", None) - secret_value = getattr(settings, "SOCIAL_AUTH_OIDC_SECRET", None) - oidc_endpoint = getattr(settings, "SOCIAL_AUTH_OIDC_OIDC_ENDPOINT", None) - - # Skip if required settings are not configured - if not key_value or not secret_value or not oidc_endpoint: - return [] - - # Get additional OIDC configuration - verify_ssl = getattr(settings, "SOCIAL_AUTH_OIDC_VERIFY_SSL", True) - - # Get organization and team mappings - org_map_value = self.get_social_org_map() - team_map_value = self.get_social_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": False, - "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): - """Create a generic OIDC authenticator in Gateway.""" - category = config["category"] - config_settings = config["settings"] - - # Generate authenticator name and slug - authenticator_name = "oidc" - authenticator_slug = self._generate_authenticator_slug("oidc", category) - - self._write_output(f"\n--- Processing {category} authenticator ---") - self._write_output(f"Name: {authenticator_name}") - 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) - result = self.submit_authenticator(gateway_config, ignore_keys, config) - - # Handle LOGIN_REDIRECT_OVERRIDE if applicable - valid_login_urls = ['/sso/login/oidc'] - self.handle_login_override(config, valid_login_urls) - - return result diff --git a/awx/sso/utils/radius_migrator.py b/awx/sso/utils/radius_migrator.py deleted file mode 100644 index e61702a109..0000000000 --- a/awx/sso/utils/radius_migrator.py +++ /dev/null @@ -1,85 +0,0 @@ -""" -RADIUS authenticator migrator. - -This module handles the migration of RADIUS authenticators from AWX to Gateway. -""" - -from django.conf import settings - -from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator - - -class RADIUSMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of RADIUS authenticators from AWX to Gateway. - """ - - CATEGORY = "RADIUS" - AUTH_TYPE = "ansible_base.authentication.authenticator_plugins.radius" - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "RADIUS" - - def get_controller_config(self): - """ - Export RADIUS authenticators. A RADIUS authenticator is only exported if - required configuration is present. - - Returns: - list: List of configured RADIUS authentication providers with their settings - """ - server = getattr(settings, "RADIUS_SERVER", None) - if not server: - return [] - - port = getattr(settings, "RADIUS_PORT", 1812) - secret = getattr(settings, "RADIUS_SECRET", "") - - config_data = { - "name": "default", - "type": self.AUTH_TYPE, - "enabled": True, - "create_objects": True, - "remove_users": False, - "configuration": { - "SERVER": server, - "PORT": port, - "SECRET": secret, - }, - } - - return [ - { - "category": self.CATEGORY, - "settings": config_data, - } - ] - - def create_gateway_authenticator(self, config): - """Create a RADIUS authenticator in Gateway.""" - category = config["category"] - config_settings = config["settings"] - - # Generate authenticator name and slug - authenticator_name = "radius" - authenticator_slug = self._generate_authenticator_slug("radius", category) - - self._write_output(f"\n--- Processing {category} authenticator ---") - self._write_output(f"Name: {authenticator_name}") - 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"], - } - - # Submit the authenticator (create or update as needed) - return self.submit_authenticator(gateway_config, config=config) diff --git a/awx/sso/utils/saml_migrator.py b/awx/sso/utils/saml_migrator.py deleted file mode 100644 index 736cb4e843..0000000000 --- a/awx/sso/utils/saml_migrator.py +++ /dev/null @@ -1,308 +0,0 @@ -""" -SAML authenticator migrator. - -This module handles the migration of SAML 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 - -ROLE_MAPPER = { - "is_superuser_role": {"role": None, "map_type": "is_superuser", "revoke": "remove_superusers"}, - "is_system_auditor_role": {"role": "Platform Auditor", "map_type": "role", "revoke": "remove_system_auditors"}, -} - -ATTRIBUTE_VALUE_MAPPER = { - "is_superuser_attr": {"role": None, "map_type": "is_superuser", "value": "is_superuser_value", "revoke": "remove_superusers"}, - "is_system_auditor_attr": {"role": "Platform Auditor", "map_type": "role", "value": "is_system_auditor_value", "revoke": "remove_system_auditors"}, -} - -ORG_ATTRIBUTE_MAPPER = { - "saml_attr": {"role": "Organization Member", "revoke": "remove"}, - "saml_admin_attr": {"role": "Organization Admin", "revoke": "remove_admins"}, -} - - -def _split_chunks(data: str, length: int = 64) -> list[str]: - return [data[i : i + length] for i in range(0, len(data), length)] - - -def _to_pem_cert(data: str) -> list[str]: - items = ["-----BEGIN CERTIFICATE-----"] - items += _split_chunks(data) - items.append("-----END CERTIFICATE-----") - return items - - -class SAMLMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of SAML authenticators from AWX to Gateway. - """ - - CATEGORY = "SAML" - AUTH_TYPE = "ansible_base.authentication.authenticator_plugins.saml" - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.next_order = 1 - self.team_mappers = [] - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "SAML" - - def get_controller_config(self): - """ - Export SAML authenticators. A SAML authenticator is only exported if - required configuration is present. - - Returns: - list: List of configured SAML authentication providers with their settings - """ - found_configs = [] - - enabled = False - remove_users = True - create_objects = getattr(settings, "SAML_AUTO_CREATE_OBJECTS", True) - idps = getattr(settings, "SOCIAL_AUTH_SAML_ENABLED_IDPS", {}) - security_config = getattr(settings, "SOCIAL_AUTH_SAML_SECURITY_CONFIG", {}) - - # 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") - self.extra_data = getattr(settings, "SOCIAL_AUTH_SAML_EXTRA_DATA", []) - self._add_to_extra_data(['Role', 'Role']) - - support_contact = getattr(settings, "SOCIAL_AUTH_SAML_SUPPORT_CONTACT", {}) - technical_contact = getattr(settings, "SOCIAL_AUTH_SAML_TECHNICAL_CONTACT", {}) - org_info = getattr(settings, "SOCIAL_AUTH_SAML_ORG_INFO", {}) - - sp_private_key = getattr(settings, "SOCIAL_AUTH_SAML_SP_PRIVATE_KEY", None) - sp_public_cert = getattr(settings, "SOCIAL_AUTH_SAML_SP_PUBLIC_CERT", None) - sp_entity_id = getattr(settings, "SOCIAL_AUTH_SAML_SP_ENTITY_ID", None) - sp_extra = getattr(settings, "SOCIAL_AUTH_SAML_SP_EXTRA", {}) - saml_team_attr = getattr(settings, "SOCIAL_AUTH_SAML_TEAM_ATTR", {}) - org_attr = getattr(settings, "SOCIAL_AUTH_SAML_ORGANIZATION_ATTR", {}) - user_flags_by_attr = getattr(settings, "SOCIAL_AUTH_SAML_USER_FLAGS_BY_ATTR", {}) - login_redirect_override = getattr(settings, "LOGIN_REDIRECT_OVERRIDE", None) - - org_mappers, self.next_order = org_map_to_gateway_format(org_map_value, start_order=self.next_order) - self.team_mappers, self.next_order = team_map_to_gateway_format(team_map_value, start_order=self.next_order) - - self._team_attr_to_gateway_format(saml_team_attr) - self._user_flags_by_role_to_gateway_format(user_flags_by_attr) - self._user_flags_by_attr_value_to_gateway_format(user_flags_by_attr) - self._org_attr_to_gateway_format(org_attr) - - for name, value in idps.items(): - config_data = { - "name": name, - "type": self.AUTH_TYPE, - "enabled": enabled, - "create_objects": create_objects, - "remove_users": remove_users, - "configuration": { - "IDP_URL": value.get("url"), - "IDP_X509_CERT": "\n".join(_to_pem_cert(value.get("x509cert"))), - "IDP_ENTITY_ID": value.get("entity_id"), - "IDP_ATTR_EMAIL": value.get("attr_email"), - "IDP_ATTR_USERNAME": value.get("attr_username"), - "IDP_ATTR_FIRST_NAME": value.get("attr_first_name"), - "IDP_ATTR_LAST_NAME": value.get("attr_last_name"), - "IDP_ATTR_USER_PERMANENT_ID": value.get("attr_user_permanent_id"), - "IDP_GROUPS": value.get("attr_groups"), - "SP_ENTITY_ID": sp_entity_id, - "SP_PUBLIC_CERT": sp_public_cert, - "SP_PRIVATE_KEY": sp_private_key, - "ORG_INFO": org_info, - "TECHNICAL_CONTACT": technical_contact, - "SUPPORT_CONTACT": support_contact, - "SECURITY_CONFIG": security_config, - "SP_EXTRA": sp_extra, - "EXTRA_DATA": self.extra_data, - }, - } - - found_configs.append( - { - "category": self.CATEGORY, - "settings": config_data, - "org_mappers": org_mappers, - "team_mappers": self.team_mappers, - "login_redirect_override": login_redirect_override, - } - ) - return found_configs - - def create_gateway_authenticator(self, config): - """Create a SAML authenticator in Gateway.""" - category = config["category"] - config_settings = config["settings"] - name = config_settings["name"] - - # Generate authenticator name and slug - authenticator_name = f"{category.replace('-', '_').title()}-{name}" - authenticator_slug = self._generate_authenticator_slug("saml", name) - - self._write_output(f"\n--- Processing {category} authenticator ---") - self._write_output(f"Name: {authenticator_name}") - 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": False, - "create_objects": True, # Allow Gateway to create users/orgs/teams - "remove_users": False, # Don't remove users by default - "configuration": config_settings["configuration"], - } - - # CALLBACK_URL - automatically created by Gateway - ignore_keys = ["CALLBACK_URL", "SP_PRIVATE_KEY"] - - # Submit the authenticator (create or update as needed) - result = self.submit_authenticator(gateway_config, ignore_keys, config) - - # Handle LOGIN_REDIRECT_OVERRIDE if applicable - valid_login_urls = [f'/sso/login/saml/?idp={name}', f'/sso/login/saml/?idp={name}/'] - self.handle_login_override(config, valid_login_urls) - - return result - - def _team_attr_to_gateway_format(self, saml_team_attr): - saml_attr = saml_team_attr.get("saml_attr") - if not saml_attr: - return - - revoke = saml_team_attr.get('remove', True) - self._add_to_extra_data([saml_attr, saml_attr]) - - for item in saml_team_attr["team_org_map"]: - team_list = item["team"] - if isinstance(team_list, str): - team_list = [team_list] - team = item.get("team_alias") or item["team"] - self.team_mappers.append( - { - "map_type": "team", - "role": "Team Member", - "organization": item["organization"], - "team": team, - "name": "Team" + "-" + team + "-" + item["organization"], - "revoke": revoke, - "authenticator": -1, - "triggers": {"attributes": {saml_attr: {"in": team_list}, "join_condition": "or"}}, - "order": self.next_order, - } - ) - self.next_order += 1 - - def _user_flags_by_role_to_gateway_format(self, user_flags_by_attr): - for k, v in ROLE_MAPPER.items(): - if k in user_flags_by_attr: - if v['role']: - name = f"Role-{v['role']}" - else: - name = f"Role-{v['map_type']}" - - revoke = user_flags_by_attr.get(v['revoke'], True) - self.team_mappers.append( - { - "map_type": v["map_type"], - "role": v["role"], - "name": name, - "organization": None, - "team": None, - "revoke": revoke, - "order": self.next_order, - "authenticator": -1, - "triggers": { - "attributes": { - "Role": {"in": user_flags_by_attr[k]}, - "join_condition": "or", - } - }, - } - ) - self.next_order += 1 - - def _user_flags_by_attr_value_to_gateway_format(self, user_flags_by_attr): - for k, v in ATTRIBUTE_VALUE_MAPPER.items(): - if k in user_flags_by_attr: - value = user_flags_by_attr.get(v['value']) - - if value: - if isinstance(value, list): - value = {'in': value} - else: - value = {'in': [value]} - else: - value = {} - - revoke = user_flags_by_attr.get(v['revoke'], True) - attr_name = user_flags_by_attr[k] - self._add_to_extra_data([attr_name, attr_name]) - - if v['role']: - name = f"Role-{v['role']}-attr" - else: - name = f"Role-{v['map_type']}-attr" - - self.team_mappers.append( - { - "map_type": v["map_type"], - "role": v["role"], - "name": name, - "organization": None, - "team": None, - "revoke": revoke, - "order": self.next_order, - "authenticator": -1, - "triggers": { - "attributes": { - attr_name: value, - "join_condition": "or", - } - }, - } - ) - self.next_order += 1 - - def _org_attr_to_gateway_format(self, org_attr): - for k, v in ORG_ATTRIBUTE_MAPPER.items(): - if k in org_attr: - attr_name = org_attr.get(k) - organization = "{% " + f"for_attr_value('{attr_name}')" + " %}" - revoke = org_attr.get(v['revoke'], True) - - self._add_to_extra_data([attr_name, attr_name]) - - name = f"Role-{v['role']}-attr" - self.team_mappers.append( - { - "map_type": 'organization', - "role": v['role'], - "name": name, - "organization": organization, - "team": None, - "revoke": revoke, - "order": self.next_order, - "authenticator": -1, - "triggers": { - "attributes": { - attr_name: {}, - "join_condition": "or", - } - }, - } - ) - self.next_order += 1 - - def _add_to_extra_data(self, item: list): - if item not in self.extra_data: - self.extra_data.append(item) diff --git a/awx/sso/utils/settings_migrator.py b/awx/sso/utils/settings_migrator.py deleted file mode 100644 index e501d7aa77..0000000000 --- a/awx/sso/utils/settings_migrator.py +++ /dev/null @@ -1,197 +0,0 @@ -""" -Settings migrator. - -This module handles the migration of AWX settings to Gateway. -""" - -from django.conf import settings -from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator - - -class SettingsMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of AWX settings to Gateway. - """ - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - # Define transformer functions for each setting - self.setting_transformers = { - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL': self._transform_social_auth_username_is_full_email, - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS': self._transform_allow_oauth2_for_external_users, - } - - def _convert_setting_name(self, setting): - keys = { - "CUSTOM_LOGIN_INFO": "custom_login_info", - "CUSTOM_LOGO": "custom_logo", - } - return keys.get(setting, setting) - - def _transform_social_auth_username_is_full_email(self, value): - # SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL is a boolean and does not need to be transformed - return value - - def _transform_allow_oauth2_for_external_users(self, value): - # ALLOW_OAUTH2_FOR_EXTERNAL_USERS is a boolean and does not need to be transformed - return value - - def get_authenticator_type(self): - """Get the human-readable authenticator type name.""" - return "Settings" - - def get_controller_config(self): - """ - Export relevant AWX settings that need to be migrated to Gateway. - - Returns: - list: List of configured settings that need to be migrated - """ - # Define settings that should be migrated from AWX to Gateway - settings_to_migrate = [ - 'SESSION_COOKIE_AGE', - 'SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL', - 'ALLOW_OAUTH2_FOR_EXTERNAL_USERS', - 'LOGIN_REDIRECT_OVERRIDE', - 'ORG_ADMINS_CAN_SEE_ALL_USERS', - 'MANAGE_ORGANIZATION_AUTH', - ] - - found_configs = [] - - for setting_name in settings_to_migrate: - # Handle LOGIN_REDIRECT_OVERRIDE specially - if setting_name == 'LOGIN_REDIRECT_OVERRIDE': - if BaseAuthenticatorMigrator.login_redirect_override_set_by_migrator: - # Use the URL computed by the authenticator migrator - setting_value = BaseAuthenticatorMigrator.login_redirect_override_new_url - else: - # Use the original controller setting value - setting_value = getattr(settings, setting_name, None) - else: - setting_value = getattr(settings, setting_name, None) - - # Only include settings that have non-None and non-empty values - if setting_value is not None and setting_value != "": - # Apply transformer function if available - transformer = self.setting_transformers.get(setting_name) - if transformer: - setting_value = transformer(setting_value) - - # Skip migration if transformer returned None or empty string - if setting_value is not None and setting_value != "": - found_configs.append( - { - 'category': 'global-settings', - 'setting_name': setting_name, - 'setting_value': setting_value, - 'org_mappers': [], # Settings don't have mappers - 'team_mappers': [], # Settings don't have mappers - 'role_mappers': [], # Settings don't have mappers - 'allow_mappers': [], # Settings don't have mappers - } - ) - else: - self._write_output(f'\nIgnoring {setting_name} because it is None or empty after transformation') - else: - self._write_output(f'\nIgnoring {setting_name} because it is None or empty') - - return found_configs - - def create_gateway_authenticator(self, config): - """ - Migrate AWX settings to Gateway. - - Note: This doesn't create authenticators, but updates Gateway settings. - """ - setting_name = config['setting_name'] - setting_value = config['setting_value'] - - self._write_output(f'\n--- Migrating setting: {setting_name} ---') - - try: - gateway_setting_name = self._convert_setting_name(setting_name) - - # Get current gateway setting value to check if update is needed - current_gateway_value = self.gateway_client.get_gateway_setting(gateway_setting_name) - - # Compare current gateway value with controller value - if current_gateway_value == setting_value: - self._write_output(f'↷ Setting unchanged: {setting_name} (value already matches)', 'warning') - return {'success': True, 'action': 'skipped', 'error': None} - - self._write_output(f'Current value: {current_gateway_value}') - self._write_output(f'New value: {setting_value}') - - # Use the new update_gateway_setting method - self.gateway_client.update_gateway_setting(gateway_setting_name, setting_value) - - self._write_output(f'✓ Successfully migrated setting: {setting_name}', 'success') - - # Return success result in the expected format - return {'success': True, 'action': 'updated', 'error': None} - - except Exception as e: - self._write_output(f'✗ Failed to migrate setting {setting_name}: {str(e)}', 'error') - return {'success': False, 'action': 'failed', 'error': str(e)} - - def migrate(self): - """ - Main entry point - orchestrates the settings migration process. - - Returns: - dict: Summary of migration results - """ - # Get settings from AWX/Controller - configs = self.get_controller_config() - - if not configs: - self._write_output('No settings found to migrate.', 'warning') - return { - 'created': 0, - 'updated': 0, - 'unchanged': 0, - 'failed': 0, - 'mappers_created': 0, - 'mappers_updated': 0, - 'mappers_failed': 0, - 'settings_created': 0, - 'settings_updated': 0, - 'settings_unchanged': 0, - 'settings_failed': 0, - } - - self._write_output(f'Found {len(configs)} setting(s) to migrate.', 'success') - - # Process each setting - created_settings = [] - updated_settings = [] - unchanged_settings = [] - failed_settings = [] - - for config in configs: - result = self.create_gateway_authenticator(config) - if result['success']: - if result['action'] == 'created': - created_settings.append(config) - elif result['action'] == 'updated': - updated_settings.append(config) - elif result['action'] == 'skipped': - unchanged_settings.append(config) - else: - failed_settings.append(config) - - # Settings don't have mappers, or authenticators, so authenticator and mapper counts are always 0 - return { - 'created': 0, - 'updated': 0, - 'unchanged': 0, - 'failed': 0, - 'mappers_created': 0, - 'mappers_updated': 0, - 'mappers_failed': 0, - 'settings_created': len(created_settings), - 'settings_updated': len(updated_settings), - 'settings_unchanged': len(unchanged_settings), - 'settings_failed': len(failed_settings), - } diff --git a/awx/sso/utils/tacacs_migrator.py b/awx/sso/utils/tacacs_migrator.py deleted file mode 100644 index 39666a7097..0000000000 --- a/awx/sso/utils/tacacs_migrator.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -TACACS+ authenticator migrator. - -This module handles the migration of TACACS+ authenticators from AWX to Gateway. -""" - -from django.conf import settings - -from awx.sso.utils.base_migrator import BaseAuthenticatorMigrator - - -class TACACSMigrator(BaseAuthenticatorMigrator): - """ - Handles the migration of TACACS+ authenticators from AWX to Gateway. - """ - - CATEGORY = "TACACSPLUS" - AUTH_TYPE = "ansible_base.authentication.authenticator_plugins.tacacs" - - def get_authenticator_type(self): - """Get the human-readable authenticator type name. - Named TACACSPLUS because `+` is not allowed in authenticator slug. - """ - return "TACACSPLUS" - - def get_controller_config(self): - """ - Export TACACS+ authenticator. A TACACS+ authenticator is only exported if - required configuration is present. - - Returns: - list: List of configured TACACS+ authentication providers with their settings - """ - host = getattr(settings, "TACACSPLUS_HOST", None) - if not host: - return [] - - port = getattr(settings, "TACACSPLUS_PORT", 49) - secret = getattr(settings, "TACACSPLUS_SECRET", "") - session_timeout = getattr(settings, "TACACSPLUS_SESSION_TIMEOUT", 5) - auth_protocol = getattr(settings, "TACACSPLUS_AUTH_PROTOCOL", "ascii") - rem_addr = getattr(settings, "TACACSPLUS_REM_ADDR", False) - - config_data = { - "name": "default", - "type": self.AUTH_TYPE, - "enabled": True, - "create_objects": True, - "remove_users": False, - "configuration": { - "HOST": host, - "PORT": port, - "SECRET": secret, - "SESSION_TIMEOUT": session_timeout, - "AUTH_PROTOCOL": auth_protocol, - "REM_ADDR": rem_addr, - }, - } - - return [ - { - "category": self.CATEGORY, - "settings": config_data, - } - ] - - def create_gateway_authenticator(self, config): - """Create a TACACS+ authenticator in Gateway.""" - category = config["category"] - config_settings = config["settings"] - - # Generate authenticator name and slug - authenticator_name = "tacacs" - authenticator_slug = self._generate_authenticator_slug("tacacs", category) - - self._write_output(f"\n--- Processing {category} authenticator ---") - self._write_output(f"Name: {authenticator_name}") - 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"], - } - - # Submit the authenticator (create or update as needed) - return self.submit_authenticator(gateway_config, config=config) diff --git a/awx_collection/README.md b/awx_collection/README.md index d730c627ed..cba0db69b9 100644 --- a/awx_collection/README.md +++ b/awx_collection/README.md @@ -37,7 +37,6 @@ in the future. The `DOCUMENTATION` for each module will report this. You can specify authentication by host, username, and password. -<<<<<<< HEAD These can be specified via (from highest to lowest precedence): - direct module parameters @@ -55,8 +54,6 @@ verify_ssl = true username = foo password = bar ``` -======= ->>>>>>> tower/test_stable-2.6 ## Release and Upgrade Notes diff --git a/awx_collection/meta/runtime.yml b/awx_collection/meta/runtime.yml index cdb5714b36..c663b95daa 100644 --- a/awx_collection/meta/runtime.yml +++ b/awx_collection/meta/runtime.yml @@ -263,14 +263,7 @@ plugin_routing: removal_date: '2022-01-23' warning_text: The tower_* modules have been deprecated, use awx.awx.workflow_node_wait instead. redirect: awx.awx.workflow_node_wait -<<<<<<< HEAD role: deprecation: removal_version: '25.0.0' warning_text: This is replaced by the DAB role system, via the role_definition module. -======= - application: - deprecation: - removal_version: '25.0.0' - warning_text: The application module manages a legacy authentication feature that is being phased out, migrate to token-based authentication instead. ->>>>>>> tower/test_stable-2.6 diff --git a/awx_collection/plugins/doc_fragments/auth.py b/awx_collection/plugins/doc_fragments/auth.py index 9508577fb9..4ada9588a2 100644 --- a/awx_collection/plugins/doc_fragments/auth.py +++ b/awx_collection/plugins/doc_fragments/auth.py @@ -40,7 +40,6 @@ options: - A dictionary structure as returned by the token module. - If value not set, will try environment variable C(CONTROLLER_OAUTH_TOKEN) and then config files type: raw - aliases: [ controller_oauthtoken ] version_added: "3.7.0" validate_certs: description: diff --git a/awx_collection/plugins/doc_fragments/auth_plugin.py b/awx_collection/plugins/doc_fragments/auth_plugin.py index 14c3c12f69..44ad326eda 100644 --- a/awx_collection/plugins/doc_fragments/auth_plugin.py +++ b/awx_collection/plugins/doc_fragments/auth_plugin.py @@ -40,20 +40,11 @@ options: version: '4.0.0' why: Collection name change alternatives: 'TOWER_PASSWORD, AAP_PASSWORD' -<<<<<<< HEAD aap_token: -======= - oauth_token: ->>>>>>> tower/test_stable-2.6 description: - The OAuth token to use. env: - name: AAP_TOKEN -<<<<<<< HEAD -======= - - name: CONTROLLER_OAUTH_TOKEN - - name: TOWER_OAUTH_TOKEN ->>>>>>> tower/test_stable-2.6 deprecated: collection_name: 'awx.awx' version: '4.0.0' diff --git a/awx_collection/plugins/lookup/schedule_rrule.py b/awx_collection/plugins/lookup/schedule_rrule.py index 64b41ddff9..c50d4bf716 100644 --- a/awx_collection/plugins/lookup/schedule_rrule.py +++ b/awx_collection/plugins/lookup/schedule_rrule.py @@ -73,15 +73,9 @@ DOCUMENTATION = """ """ EXAMPLES = """ -<<<<<<< HEAD - name: Create a string for a schedule debug: msg: "{{ lookup('awx.awx.schedule_rrule', 'none', start_date='1979-09-13 03:45:07') }}" -======= - - name: Create a string for a schedule - debug: - msg: "{{ lookup('awx.awx.schedule_rrule', 'none', start_date='1979-09-13 03:45:07') }}" ->>>>>>> tower/test_stable-2.6 """ RETURN = """ diff --git a/awx_collection/plugins/lookup/schedule_rruleset.py b/awx_collection/plugins/lookup/schedule_rruleset.py index 12f58f0fbb..21ca283c2c 100644 --- a/awx_collection/plugins/lookup/schedule_rruleset.py +++ b/awx_collection/plugins/lookup/schedule_rruleset.py @@ -107,7 +107,6 @@ DOCUMENTATION = """ """ EXAMPLES = """ -<<<<<<< HEAD - name: Create a ruleset for everyday except Sundays set_fact: complex_rule: "{{ lookup(awx.awx.schedule_rruleset, '2022-04-30 10:30:45', rules=rrules, timezone='UTC' ) }}" @@ -119,19 +118,6 @@ EXAMPLES = """ interval: 1 byweekday: 'sunday' include: false -======= - - name: Create a ruleset for everyday except Sundays - set_fact: - complex_rule: "{{ lookup(awx.awx.schedule_rruleset, '2022-04-30 10:30:45', rules=rrules, timezone='UTC' ) }}" - vars: - rrules: - - frequency: 'day' - interval: 1 - - frequency: 'day' - interval: 1 - byweekday: 'sunday' - include: False ->>>>>>> tower/test_stable-2.6 """ RETURN = """ diff --git a/awx_collection/plugins/module_utils/controller_api.py b/awx_collection/plugins/module_utils/controller_api.py index ee7d22b4a7..d4718c3237 100644 --- a/awx_collection/plugins/module_utils/controller_api.py +++ b/awx_collection/plugins/module_utils/controller_api.py @@ -75,10 +75,6 @@ class ControllerModule(AnsibleModule): aap_token=dict( type='raw', no_log=True, -<<<<<<< HEAD -======= - aliases=['controller_oauthtoken',], ->>>>>>> tower/test_stable-2.6 required=False, fallback=(env_fallback, ['CONTROLLER_OAUTH_TOKEN', 'TOWER_OAUTH_TOKEN', 'AAP_TOKEN']) ), @@ -136,23 +132,6 @@ class ControllerModule(AnsibleModule): if direct_value is not None: setattr(self, short_param, direct_value) -<<<<<<< HEAD -======= - # Perform magic depending on whether aap_token is a string or a dict - if self.params.get('aap_token'): - token_param = self.params.get('aap_token') - if isinstance(token_param, dict): - if 'token' in token_param: - self.oauth_token = self.params.get('aap_token')['token'] - else: - self.fail_json(msg="The provided dict in aap_token did not properly contain the token entry") - elif isinstance(token_param, string_types): - self.oauth_token = self.params.get('aap_token') - else: - error_msg = "The provided aap_token type was not valid ({0}). Valid options are str or dict.".format(type(token_param).__name__) - self.fail_json(msg=error_msg) - ->>>>>>> tower/test_stable-2.6 # Perform some basic validation if not self.host.startswith(("https://", "http://")): # NOSONAR self.host = "https://{0}".format(self.host) diff --git a/awx_collection/plugins/modules/application.py b/awx_collection/plugins/modules/application.py deleted file mode 100644 index 9e28195db1..0000000000 --- a/awx_collection/plugins/modules/application.py +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2020,Geoffrey Bachelot -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - - -ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: application -author: "Geoffrey Bacheot (@jffz)" -short_description: create, update, or destroy Automation Platform Controller applications -deprecated: - removed_in: '25.0.0' - why: This module manages a legacy authentication feature that is being phased out. - alternative: Migrate to token-based authentication. -description: - - Create, update, or destroy Automation Platform Controller applications. See - U(https://www.ansible.com/tower) for an overview. -options: - name: - description: - - Name of the application. - required: True - type: str - new_name: - description: - - Setting this option will change the existing name (looked up via the name field). - type: str - description: - description: - - Description of the application. - type: str - authorization_grant_type: - description: - - The grant type the user must use for acquire tokens for this application. - choices: ["password", "authorization-code"] - type: str - required: False - client_type: - description: - - Set to public or confidential depending on how secure the client device is. - choices: ["public", "confidential"] - type: str - required: False - organization: - description: - - Name, ID, or named URL of organization for application. - type: str - required: True - redirect_uris: - description: - - Allowed urls list, space separated. Required when authorization-grant-type=authorization-code - type: list - elements: str - state: - description: - - Desired state of the resource. - default: "present" - choices: ["present", "absent", "exists"] - type: str - skip_authorization: - description: - - Set True to skip authorization step for completely trusted applications. - type: bool - -extends_documentation_fragment: awx.awx.auth -''' - - -EXAMPLES = ''' -- name: Add Foo application - application: - name: "Foo" - description: "Foo bar application" - organization: "test" - state: present - authorization_grant_type: password - client_type: public - -- name: Add Foo application - application: - name: "Foo" - description: "Foo bar application" - organization: "test" - state: present - authorization_grant_type: authorization-code - client_type: confidential - redirect_uris: - - http://tower.com/api/v2/ -''' - -from ..module_utils.controller_api import ControllerAPIModule - - -def main(): - # Any additional arguments that are not fields of the item can be added here - argument_spec = dict( - name=dict(required=True), - new_name=dict(), - description=dict(), - authorization_grant_type=dict(choices=["password", "authorization-code"]), - client_type=dict(choices=['public', 'confidential']), - organization=dict(required=True), - redirect_uris=dict(type="list", elements='str'), - state=dict(choices=['present', 'absent', 'exists'], default='present'), - skip_authorization=dict(type='bool'), - ) - - # Create a module for ourselves - module = ControllerAPIModule(argument_spec=argument_spec) - - # Extract our parameters - name = module.params.get('name') - new_name = module.params.get("new_name") - description = module.params.get('description') - authorization_grant_type = module.params.get('authorization_grant_type') - client_type = module.params.get('client_type') - organization = module.params.get('organization') - redirect_uris = module.params.get('redirect_uris') - skip_authorization = module.params.get('skip_authorization') - state = module.params.get('state') - - # Attempt to look up the related items the user specified (these will fail the module if not found) - org_id = module.resolve_name_to_id('organizations', organization) - - # Attempt to look up application based on the provided name and org ID - application = module.get_one('applications', name_or_id=name, check_exists=(state == 'exists'), **{'data': {'organization': org_id}}) - - if state == 'absent': - # If the state was absent we can let the module delete it if needed, the module will handle exiting from this - module.delete_if_needed(application) - - # Create the data that gets sent for create and update - application_fields = { - 'name': new_name if new_name else (module.get_item_name(application) if application else name), - 'organization': org_id, - } - if authorization_grant_type is not None: - application_fields['authorization_grant_type'] = authorization_grant_type - if client_type is not None: - application_fields['client_type'] = client_type - if description is not None: - application_fields['description'] = description - if redirect_uris is not None: - application_fields['redirect_uris'] = ' '.join(redirect_uris) - if skip_authorization is not None: - application_fields['skip_authorization'] = skip_authorization - - response = module.create_or_update_if_needed(application, application_fields, endpoint='applications', item_type='application', auto_exit=False) - if 'client_id' in response: - module.json_output['client_id'] = response['client_id'] - if 'client_secret' in response: - module.json_output['client_secret'] = response['client_secret'] - module.exit_json(**module.json_output) - - -if __name__ == '__main__': - main() diff --git a/awx_collection/plugins/modules/schedule.py b/awx_collection/plugins/modules/schedule.py index c25e0024b8..2d651805a7 100644 --- a/awx_collection/plugins/modules/schedule.py +++ b/awx_collection/plugins/modules/schedule.py @@ -180,13 +180,8 @@ EXAMPLES = ''' - frequency: 'day' interval: 1 - frequency: 'day' -<<<<<<< HEAD interval: 1 byweekday: 'sunday' -======= - every: 1 - on_days: 'sunday' ->>>>>>> tower/test_stable-2.6 include: false - name: Delete 'my_schedule' schedule for my_workflow diff --git a/awx_collection/test/awx/conftest.py b/awx_collection/test/awx/conftest.py index 1fcaf362b0..371ae66014 100644 --- a/awx_collection/test/awx/conftest.py +++ b/awx_collection/test/awx/conftest.py @@ -19,11 +19,8 @@ from ansible.module_utils.six import raise_from from ansible_base.rbac.models import RoleDefinition, DABPermission from ansible_base.rbac import permission_registry -<<<<<<< HEAD from awx.main.tests.conftest import load_all_credentials # noqa: F401; pylint: disable=unused-import -======= ->>>>>>> tower/test_stable-2.6 from awx.main.tests.functional.conftest import _request from awx.main.tests.functional.conftest import credentialtype_scm, credentialtype_ssh # noqa: F401; pylint: disable=unused-import from awx.main.models import ( diff --git a/awx_collection/test/awx/test_organization.py b/awx_collection/test/awx/test_organization.py index c87245372f..6c7d48d9b2 100644 --- a/awx_collection/test/awx/test_organization.py +++ b/awx_collection/test/awx/test_organization.py @@ -20,10 +20,7 @@ def test_create_organization(run_module, admin_user): 'controller_username': None, 'controller_password': None, 'validate_certs': None, -<<<<<<< HEAD -======= 'aap_token': None, ->>>>>>> tower/test_stable-2.6 'controller_config_file': None, } @@ -56,10 +53,7 @@ def test_galaxy_credential_order(run_module, admin_user): 'controller_username': None, 'controller_password': None, 'validate_certs': None, -<<<<<<< HEAD -======= 'aap_token': None, ->>>>>>> tower/test_stable-2.6 'controller_config_file': None, 'galaxy_credentials': cred_ids, } @@ -84,10 +78,7 @@ def test_galaxy_credential_order(run_module, admin_user): 'controller_username': None, 'controller_password': None, 'validate_certs': None, -<<<<<<< HEAD -======= 'aap_token': None, ->>>>>>> tower/test_stable-2.6 'controller_config_file': None, 'galaxy_credentials': cred_ids, } diff --git a/awx_collection/test/awx/test_token.py b/awx_collection/test/awx/test_token.py deleted file mode 100644 index cc8f880e26..0000000000 --- a/awx_collection/test/awx/test_token.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -import pytest - -from awx.main.models import OAuth2AccessToken - - -@pytest.mark.django_db -def test_create_token(run_module, admin_user): - - module_args = { - 'description': 'barfoo', - 'state': 'present', - 'scope': 'read', - 'controller_host': None, - 'controller_username': None, - 'controller_password': None, - 'validate_certs': None, - 'aap_token': None, - 'controller_config_file': None, - } - - result = run_module('token', module_args, admin_user) - assert result.get('changed'), result - - tokens = OAuth2AccessToken.objects.filter(description='barfoo') - assert len(tokens) == 1, 'Tokens with description of barfoo != 0: {0}'.format(len(tokens)) - assert tokens[0].scope == 'read', 'Token was not given read access' diff --git a/awx_collection/tests/integration/targets/credential/tasks/main.yml b/awx_collection/tests/integration/targets/credential/tasks/main.yml index 4d499c139c..1b96b2b856 100644 --- a/awx_collection/tests/integration/targets/credential/tasks/main.yml +++ b/awx_collection/tests/integration/targets/credential/tasks/main.yml @@ -775,33 +775,6 @@ - "result is changed" when: insights_found -- name: Create a valid Insights token credential - credential: - name: "{{ insights_cred_name2 }}" - organization: Default - state: present - credential_type: Insights - inputs: - client_id: joe - client_secret: secret - register: result - -- assert: - that: - - "result is changed" - -- name: Delete an Insights token credential - credential: - name: "{{ insights_cred_name2 }}" - organization: Default - state: absent - credential_type: Insights - register: result - -- assert: - that: - - "result is changed" - - name: Create a valid Tower-to-Tower credential credential: name: "{{ tower_cred_name1 }}" diff --git a/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml b/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml index 90b37c927a..d6c7cd788e 100644 --- a/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml +++ b/awx_collection/tests/integration/targets/schedule_rrule/tasks/main.yml @@ -7,16 +7,10 @@ ansible.builtin.set_fact: plugin_name: "{{ controller_meta.prefix }}.schedule_rrule" -<<<<<<< HEAD - name: Lookup with too many parameters (should fail) ansible.builtin.set_fact: _rrule: "{{ query(plugin_name, days_of_week=[1, 2], days_of_month=[15]) }}" register: result_too_many_params -======= -- name: Test too many params (failure from validation of terms) - ansible.builtin.debug: - msg: "{{ lookup(plugin_name | string, 'none', 'weekly', start_date='2020-4-16 03:45:07') }}" ->>>>>>> tower/test_stable-2.6 ignore_errors: true - name: Assert proper error is reported for too many parameters @@ -27,12 +21,8 @@ - name: Attempt invalid schedule_rrule lookup with bad frequency ansible.builtin.debug: -<<<<<<< HEAD msg: "{{ lookup(plugin_name, 'john', start_date='2020-04-16 03:45:07') }}" register: result_bad_freq -======= - msg: "{{ lookup(plugin_name, 'john', start_date='2020-4-16 03:45:07') }}" ->>>>>>> tower/test_stable-2.6 ignore_errors: true - name: Assert proper error is reported for bad frequency @@ -44,10 +34,7 @@ - name: Test an invalid start date ansible.builtin.debug: msg: "{{ lookup(plugin_name, 'none', start_date='invalid') }}" -<<<<<<< HEAD register: result_bad_date -======= ->>>>>>> tower/test_stable-2.6 ignore_errors: true - name: Assert plugin error message for invalid start date @@ -59,11 +46,7 @@ - name: Test end_on as count (generic success case) ansible.builtin.debug: msg: "{{ lookup(plugin_name, 'minute', start_date='2020-4-16 03:45:07', end_on='2') }}" -<<<<<<< HEAD register: result_success -======= - register: result ->>>>>>> tower/test_stable-2.6 - name: Assert successful rrule generation ansible.builtin.assert: diff --git a/awx_collection/tests/integration/targets/token/tasks/main.yml b/awx_collection/tests/integration/targets/token/tasks/main.yml deleted file mode 100644 index 92aace82cc..0000000000 --- a/awx_collection/tests/integration/targets/token/tasks/main.yml +++ /dev/null @@ -1,154 +0,0 @@ ---- -- name: Generate a test ID - set_fact: - test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - when: test_id is not defined - -- name: Generate names - set_fact: - token_description: "AWX-Collection-tests-token-description-{{ test_id }}" - -- name: Try to use a token as a dict which is missing the token parameter - job_list: - controller_oauthtoken: - not_token: "This has no token entry" - register: results - ignore_errors: true - -- assert: - that: - - results is failed - - '"The provided dict in aap_token did not properly contain the token entry" == results.msg' - -- name: Try to use a token as a list - job_list: - controller_oauthtoken: - - dummy_token - register: results - ignore_errors: true - -- assert: - that: - - results is failed - - '"The provided aap_token type was not valid (list). Valid options are str or dict." == results.msg' - -- name: Try to delete a token with no existing_token or existing_token_id - token: - state: absent - register: results - ignore_errors: true - -- assert: - that: - - results is failed - # We don't assert a message here because it's handled by ansible - -- name: Try to delete a token with both existing_token or existing_token_id - token: - existing_token: - id: 1234 - existing_token_id: 1234 - state: absent - register: results - ignore_errors: true - -- assert: - that: - - results is failed - # We don't assert a message here because it's handled by ansible - - -- block: - - name: Create a Token - token: - description: '{{ token_description }}' - scope: "write" - state: present - register: new_token - - - name: Validate our token works by token - job_list: - controller_oauthtoken: "{{ controller_token.token }}" - register: job_list - - - name: Validate our token works by object - job_list: - controller_oauthtoken: "{{ controller_token }}" - register: job_list - - always: - - name: Delete our Token with our own token - token: - existing_token: "{{ controller_token }}" - controller_oauthtoken: "{{ controller_token }}" - state: absent - when: controller_token is defined - register: results - - - assert: - that: - - results is changed or results is skipped - -- block: - - name: Create a second token - token: - description: '{{ token_description }}' - scope: "write" - state: present - register: results - - - assert: - that: - - results is changed - - always: - - name: Delete the second Token with our own token - token: - existing_token_id: "{{ controller_token['id'] }}" - controller_oauthtoken: "{{ controller_token }}" - state: absent - when: controller_token is defined - register: results - - - assert: - that: - - results is changed or resuslts is skipped - -- block: - - name: Create a less privileged token (read) - token: - description: '{{ token_description }}' - scope: "read" - state: present - register: read_only_token - - - debug: - msg: "{{read_only_token}}" - - - name: Exercise the aap_token parameter with the new token. - job_list: - aap_token: "{{ read_only_token.ansible_facts.controller_token.token }}" - - - name: Ensure the new token is being used and not the default token for the tests. - token: - aap_token: "{{ read_only_token.ansible_facts.controller_token.token }}" - scope: "write" - state: present - ignore_errors: true - register: result - - - assert: - that: - - "'You don\\'t have permission to POST' in result.msg" - - always: - - name: Delete the less privileged token - token: - existing_token_id: "{{ read_only_token['id'] }}" - state: absent - when: read_only_token is defined - register: result - - - assert: - that: - - result is changed diff --git a/awx_collection/tools/roles/template_galaxy/templates/README.md.j2 b/awx_collection/tools/roles/template_galaxy/templates/README.md.j2 index 74ed3b56a7..bffd3eefab 100644 --- a/awx_collection/tools/roles/template_galaxy/templates/README.md.j2 +++ b/awx_collection/tools/roles/template_galaxy/templates/README.md.j2 @@ -119,11 +119,7 @@ The following notes are changes that may require changes to playbooks: - The `notification_configuration` parameter of `tower_notification_template` has changed from a string to a dict. Please use the `lookup` plugin to read an existing file into a dict. - `tower_credential` no longer supports passing a file name to `ssh_key_data`. - The HipChat `notification_type` has been removed and can no longer be created using the `tower_notification_template` module. -<<<<<<< HEAD - Lookup plugins now always return a list, and if you want a scalar value use `lookup` as opposed to `query` -======= - - Lookup plugins now always reutrn a list, and if you want a scalar value use `lookup` as opposed to `query` ->>>>>>> tower/test_stable-2.6 {% if collection_package | lower() == "awx" %} ## Running Unit Tests diff --git a/licenses/pbr.txt b/licenses/pbr.txt deleted file mode 100644 index 68c771a099..0000000000 --- a/licenses/pbr.txt +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/licenses/pygithub-2.6.0.tar.gz b/licenses/pygithub-2.6.0.tar.gz deleted file mode 100644 index 91a2591c13fd47af5ecafb3fa1cc8b7137401f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3655590 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
    MsjXSRcf#4CqR2%KOfF68GJZ%8#}$Bg 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

    ^%7@`!YEa)AWcGbK}{bMW?^-g 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≫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%0DV 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≧`Q3Qo|FXUBfj1LX6}cnJ3ouyy%66D&_aoXV#$%);Q%7 zs**?|V~trT#${^<9Fx`hE&4AFZ&@qC_J1=gUIA4eTWa05J^j>x!fZozQ6K^QObN=B z!2NyinGwdheF2^9K)7uJ8rtD;;1JKbb{Bpg- zf`deaZ$nuTJUv-?k+5-3BNJ*R)!;~|f-Qc{hI-=#ZlopwgM*Iq11fksoLVk45T8e@ zhFAI}n_M>$;&5cgTM}e{^fdK(UyV*vTRGp`kN{(T6(@ERcwAI2&=Owe{=T7)B<O?GTCGno|V3gEeuYor>AekTmfeqKj0v@>H29)WYv(^h}mZNIW=S%*sJ#kS%hMDhi;> zpCtKYj2_ouJKd_a1u;CypW?`;}cAo zut=vT?T?}leO7hGAB=LSr!vG)&;Qii%AN`{H(sHWr!Kl(MIbHCh|1a(AyPSg{03&Y%=prQl@YH1vIg}(M=c4V%ct!z@rA2E?`TXEXiF6$w~LN=wO7&H3M|0W1HB(DR#Ye|?#0_Xx-TuI)yoO3=PDEjqNaqY) zU^@|-^1Be@DQXQriG?%9`TYd(fP_8*s$TYb+&c@hRSp3K-g%RvK_~lx$T1k_y_FKm z7q37lgz{H^LR^j5sjk1@4wp*J=61w244T=>mtq{5;N$Igdil#kdu0RtZw||OK*~~% zS92mn-$X2BUoC%!I_fNjw zQYXmd$`vz~$Q$`G$q3b2fhY>nm}Nc+CYl9tLdHw*Cjl^ zO}#QZbjC5`pr|^GG%ZbI4rvfo+!gYblhjy|z}s%IqF-jfy2vi51%Tq| zB4#rrt(W{rMw50i6m~BaKDV%*BY_b6Q7<<mE(#%&*l%UQ`i385(CE+kLv1K}$(Zfr0@OOADDvmRmvOXr zWkntyM;8EE)ivA6(49W1Hl9UFTxHMkZ{FO^`ae}!dw(s{WAP~#ZpXUpe*K6WuadJ*&4YDO4N`>N z*La{(18*LmV~BM~A<;*;rfz?nUtRHeUka#udz>gVDqhyZC#E6ss@ydtOVx+rrIGE0 zNK`xCRtZ`fzwId8sGh^P3cqtro@10ReAuw~gFL^Q=YJzd48=kpVfgw$_wU@j3#(?pCaewpb zo^vwN<1^U~08p%#%%PIgA33nvs0z+V5;c{ciAk}_qti{EHLD=%Z?+qQMy7lmoZ^Ez zpj;Y=f5^Lqu`FO$kI)Qa>S-=g7Zsh%m7Mi|=iTXL3)wF;KPX@7T_fJNpg`_vY9q<) zszG@dM&Ia<4Za8g169cou=7hC=NaRY%wBpa6}T_o@!h=S1&i09`j?){XO14mig}(n zBoAUl~#_L=E_9nf14?gPG`YH_PTwCBkKKpH0vKBA}#M&_vt zxC3zhvA;a9mtoX&_t!9SB0!9+`W#h*kQWzhS2zRF|-2zs~nKBzRaM=qPcG%VLyOR7JkBv6*?$mo7~Az_273wv`*-t2#fJ|1;6zh@Pg?~{7Pl}&Ek%cs|OE=^XM&k!L!7Um_}KljDh zEnyE1gQlz<3x46ZeHxpcUdog!WZb^leI{WPmN*T zOAfWa*SO!~maqEk{5uPcgAB}9`V2TgT%L>r=!a*C^7W6wI`HZ5K&8pfTuniAdst`e zpmRAaK*v(7DvT`@I9TJW?HN*n`?0uuPE+MQkRNF{-|8WywM|1eKX3I?pC6RbDmdSX z%B28)5~jX2ej*JOwFFAk=a=E&(cT|>vrlaw^(nmWSORApzCT01icS)tEXNdSV-^!h zwXtf*xMn&SwG$W6|7il}>7ut2NqeE7(+*{h9CQ+gXoA{F&C7#M6HN<)>gXjKmg;mN z$*F$cQZtHkC95YyQ~rEP%r3&-mUc?K&trJ2r2O-ln7XgJtKWd31Ou*SlZYb7c&4oi z^HXj2s|*Z=#(^ot(Qw$sK-ED5G>-lcQc|yPilI@Wa!P-cWTGCTfs9jwQ(66QS~Xa1 zaxP)f&-BYdJ;VqZr{b+mp_ z0C3tQZ7=+eDx?(L2+ex*>VXW&&I^B^Gbt<^Opj-+RAdAi&2eV6gZoIB&jrFAdL6r4 zp+&l50J4vv=76i3Lo9yfoG}9$pPG%j=CNySW5@;V9=CMcG)m3?uWGlfIlw?K?coTg zwHdZ(r)Y$#Wg}xwhC^>cHXzW8@>0vStO?9wGdznE+d5nOiLoohciZ*8gSqGOWnX*^ zY|0>^C{|PcThJ3pl zw^ZHTxE+4nxOnsG+qC`>)CK86cv{K-=3dmt0I3!JaJA?~xLV2o;%?Fpf4-RY!(0D< z8bNQp^jo)AzDh4ImLdCqx!p9rP8)6aJ1@0@ZTgAT2_-kiZjIL3EgUsYUE3nsH4O(! zPv!Zd38?r^Xe*yL8?n)ZASi^CO2Rm0QliHJyMq^gH(%Rp2Ozg&oFG29Ap8g*1U~|D ztwB7rt`x?;$&v(m<%vsCdUd+!SOV{Qy08ybZ%g&jVZv@h(H1B+5(6KDla8azmkiA_ zX!JC)A12W$R&?;#_qHYF^Y@Xo#JkkBtRe#kR}E=6@lK-tn3@=4t-T#b9WV%x^tVa5 zj55B*?D)Qc!6`0A_HVWChcHroOrisiAAq93hx;i`^-t(q-f47#lPF-+any;>3QG+7 zPB{9gF{h~}H0s_AC#u?E4$+z>tUnxybyDh9jqhN+zo z#aF^tHNd#Ma393|j0IZnmpA>unwM3(zF6jM*iZB7!Z?9$Qa8+CZJy z*v@V73#Z~p8&Zg*HhDgYiRbEeA-dlCjUWYeUti46)|?~n{7IH!E45B!_}XRGI`Pq(1Rf<{!S3>52&0*3)D@;r>te>Hb&M%OCE+BTarz>e zlWbd;_X&f3p{rN@-J>W3EJ@fIAy|-qSp0qPM;gO;?ug@I40?HLbNz_^v2wWU?l75Y zA!QA1mE>b0k}`9mo03~6?f2X)<3PPp0JH_;vIJ%1fWOcT*7L}c!lVAuJGqdJdk4Z6 zm-%sF{;4wK{q^#U;%0bXRkavFeH!FWj{t5(x#1>t%~mYPa?zE_C!jn=D!B&f1y;tc ze^OSwL}V(KM4F%YlMnm%^;sqZ)R_*9+cup4Ma{Hb;EJCpAN-Hjz^hD=rg!;f?}l+D zDUf~PoXurLSX;9@Sev;~D3RX!3-Ep5l-J#oPlw$|Q0IPcOda=kczWzB5M`x#7bv*; z_~cXXlF}r{JZ6`U>j0&)no~l@DPTbW zpxS@fI1E_(ji>RVK&sucf5{Kx&6Ar*1XunXhcwOS4y6?Q6A9L#65=QcG1x&lYCgln zj3=oo{RqM?@yertFk_Ez2U1IUaeL?ngkpzwJLMIxkH_KMWiqEHJuEQ%7OQX013aF? z%$CPyon<)o)zN!LPMXpU6NNJH5H;LMv6`2pEF#oTX7$4(F=_5Gx+RPBdQ`2~VuP!B zRNTwPSxD{{Zex9;Vk|`H)jhsc`CYLSpw1Cs%c%v9x90Vr+etA8aV@)6d(v_aFx)hX z`AuKfHg9K=8^z0xrAa$SGU8l_fPs`6lFO)b}0Hh!^dIfoHAG&3fys?aGP{w zrV6vaZg=I;ZF7iu0G%8=jDG#oQp<-x;7tD<$5pzo6sR#k>bgm6&4?so7}ABhY8(WO z95qqHbmG{@+Ftm$$aE6BHq)7O*+QdCI^%vUmv!ZG0lrb3KG5ync<4OxV!H((yvb}> z#|!SEF+TY-=<{Lb(<<0`9DieU{-&3~^Md>OUi31Uv`6qEYcSK>sD5#UQ=^B_UmNB} z)3||n*2KjBLenWX=pQ}x?(!K94I%qEdiLK=^Z9qCU-p-NX{XmM5K zKWs9~FkzrjTfFZQd4&t`;#*~o>4vD_Cpcy2+hMmtz)96G(Sx6SLp##yT}Vhfyp->yVf+mB%dJVsUX`=8Y>d?D&z&})AP1itW z*pc@gX&t`gwR5*`yK_JheUeWuec`B%xD3roFim!dSPj`Apf9IuaM6Wz`GeWE zO`HL_EBGEE`o^8)W2cQ%#P=73lWLJ;1K99iqCiL@9w8U7i^xa`g?H*dUwv|Kb)|>j zkc5F==Fl^>q;1ZLG!}Sd^B~2+Zgsej8dCY90|n8Pkpy0Bm^A}0GTf3^8f3&wrBX_y zSZVywMDxjx!_alvqXl)1R0+TNTZ?WgLg@$YgB%d>?Y*82dU9&Q7$rumIKhjT*Yonq z!SEy`88RNAb{|;E2)jlA2n|lpf?*!=P@%4M;ID)2qXC9QO=jbudGNCVAg4$i%MzY$ z--j+Y4W-c)*?iD1N7H6@W^xRVAP8Io=x$(8NBx`&sS-8$b1~k(bg0K>rt@L1I(5zq zsw_GTQ2GEq4N?qCzU%;?hM1x(C7B@CWIIbTWnca%k~IRE+UaLZ1xoKkIsN>2i9w%* zekiLx?aIr<)F6l)Q6!Sm-^|@)Z6n$d9jM`mu2F!|z;tag_0Ww|MRe0|dt+EhdAYNr zc5qBlM&w1V6S@{yoG~H3mI-1bt*T^aRBc-7du4{R>6qkkZ%CXue?Z7 zB_TqrJ~6`@w&m+fUTUgZsyl=ZsX&swIDm{+<(oihd8AN;()I&bj z&*fE5zY*fXAX)TvYwoV#1|t?jFrxD@N??-Kx=`N+1n=*r6wpQ{sSpI<>^SlOAxC1? z15PL18JmAsaNTdF{M)}hHd;n35MCrG3OKAnk|PQ%OL7KB*#_x62+;h!YEol0pf?Bw zPS1Y{qv{o#b3e=m0jk1o$cnQ<{d{-OiUYxcs>zZgyp03WLDM%qDMc%+?mrBN>A{4I z>w5@4w_L8-h2zN@`XnYJ7PFlo92m=0xS}B)K*QS}Xo?f>u{F-~DitJSgcsdeGIH4; zEVUfHXw&izr`L9!NbHGNK^*Zm5=2IVa*k*4H06e{(zIW6m&t+ z1A$lhw?9-cOu0%a<0YO`I^nbUaQ5$i%LZkM`216uIc0(wq7e;HQ|aE8PTx$ZTGW=` zA&kSGlENhWCLEn-xJ`Jz4iiyFFl%*1?<5;3_-Pd`-$q2^^_EGOVAYk zVI&gKucb%nRau@axicsvf@gu?sg}^F+r{DR%Qv265{gmopUmDdx9k#%wZ?l)NyPMS z_hP=fcxep9CJsY`GX4!oqyiC7TnEmXjyqj#qO|_-P(j#59*k#_Vukl(YDpdX!R2(0 z{&rN#V8v-r{G@QA%4SDtgL%sFZtfMy)Q=b1xqGs<(cvLe?ZD{Cm%xH8 zj<%y~S1JBoDc*%@c`Pk@s%vzN#ruN`sYl}{xp5SY8L7)(!e2UQ1U?vNImgrna{imx zKk2o-F4Q#PZi-BHTCNW_fZoIxz740kRSUb|k@#K>1@8AsI;v-Hv&GO7=ay3kxSbw{g6wQ0?ZSk~2a z)?IJf+zx!t?_IYe+eQ}>X!c6`&}EqRDVpg6Kzu46ce`h|=VswT!(fuzN>(l}_m;LgVSg#|^UMW1aq~I3nMxgh>a*8LB%zzE)jn+K>fLOq zp#yl+kz{g!V^u7R74-V0*WnwB=9S)iO_h@nGRD_i?Wf zEY8;sZhk%R14Uh2MDeQX{z(*#;g^C*05LiVPQMb=ByBu=UWVla*0IiB3so(&Dp=G$ z!XOW=+)v7y$$cWgpZh^lHwJmXO?L+hFDyUgJDzMg*q<}od_E1n+-J6?EgnohKJ{+4 z=G5f9z{ic+Z^kojZF6_;t$o60=KbQQ{aEQjolWf`!8#>1E$YB9JcnY=oF7tpcu!E#Px&0_mpt8$X|Cn!iHW{BZZ>t_!2PYg{GF7Gyzg+@zT1(1K#|$I z&opTry!V~r%1_cK{+-GfDvD4=&aC5H*%SMH3Shl>qiM`Xtq1=i!JPlMcY{l#fZXvl z!G+|MQ&Fi3xIxHL|7ZiQvz5=Rl?+UI{V8u7b|B|nMz#&t{T;rEd7|_^(5Rpr*NjFr`_XGd0f!`lXB`X z@Udpp8dcut1e5t@ix$Tg4!%?z{W~c`uw{8Fn;zy(P2|;-6Ed(K=)~Lna-2|!+p&~-W4Tt!mAVb!J7yQsg%ck>+550&8ShD2Z;P8wIinp$- zohJd)c1dS`3&3U3u4-70@vx?b&SJGgEgfpD#f-~isKT5^aETd3r`Hupxp;NudFt^} zIuPdVuYK=#15sf2b}GPNkK=uBHNle^*g5vk0&X*;j``d@$lfapl1es-Ns4GmHdQ8w zk5NNky}SEIoO*P`4Th2*G!1Q-ap5Rg-sGN6kSD zM#iwM5KcRt9B|Fp(Mb?#Ptd7WO|oLbJ`uihhjbWpdM~M6)(O$x$&W;zFiM*`QltR0 zEeW`ycA@hRd+lB7Zl4E>F!ekv4q4z`e<%t4bO!QIJjX9e=*54-A7RZJ!-POF5_E2rWiqcIgiAgp7)(MM8qRuG6{{h9DxS{S8V8w zg+ufn(5^m zwAafh;AW}w?9;WO$2}6Jwn0U5*)GMe!K+uRv$c}cEN6>(a=9&MaCxpgs~>~tchg(+kMi}5{TQJQ5RN0azdYG) z;CeeWdhBXw`WPjk+?SE%Vgv!2VRcBezjtB6bT6>+wG!Ei7&{M61a2F|tY|Kx!2K%d zt-rCi8iKPLz+Wa1qQ(pYZD}7Dw!tI!Kcws_!J{x2sF2i#Z7TH}tz^GB~g z8=SA6kk=PCcz4A&ki$>yU(x@!F7k;t*Wfa_BOisS-WV53$CbmAWdGjphNw2j(f+cV zPVE{scEsPlxn;%DpEBJD_)?6O8v^3mUQv3R4W%w+O!*OMu=P&DtuDb~F2UfU7+?># zA$^`T8A0RN*7J_)o2Y_{>vtQ%9m-(gueo@=erj`Ofx{toraaz}-$AiKQ78RdiLl<& zph_qW7RMQ8zrb)O!lH^VBb9fS3^f-<-1}nAR|Y&926|Ox@J5kW-=ls zf`Pd~w(f}k4sZ50?)Ceg9Y*>&`X8ZUlIHD8_s$0``Xm_A!|~_Hjfd7Z@X@vI;f}bf z*b`)UYX0+jXZ!1=CDPVT~% zxcN@UFM7eB470_wrvjYmAPQUG*?4u1Sp|lg_v65EFDb_U&LWIyNTeLeUhK+UYB;|H z$-g-NHmv^DPj=FrC(jipH!Sv4V`MGlNk<`pL|g|tlS5JhreQY6OoR78?#AqiuG0xP zW*8(Q_g4oZ;%Eg=sV;+AS1LZP*rLJJz?%!QhYo|y<7md{NS}4x29&hN*2re!Pf@mF1u=b@q-<|o&BZt$E(_lVpk)`?S^?n>k-Jo>{N3EhqhV5>KWE(M(x~BFR2g;`N_~cu%G|I)ef7ogmEt zmi5uf==1Do$-{6u>B_rZgi*c%vRMn#5tsaX*i{2_7WYAFdf{iHy4m;s)9X>2PBdL5 zSiN)5LWM(;C4OdpUQ|`%6adwE!9bk@A7jI~^hEb7sQ$UZ#4&>?DRn@7Mm}}D#rQAHUMg*V;e+}c=%#>Vo2Qc# zdjqY(``4o@Ky9as)B)UAbRuosKlLRofTa?=uy> z){Gn!?cwt3kzELRWH2cMkHO6BnY|P12gWf>1?EZL)CHLqVr?KqF`PtWy?kl!Jmlh; zL-tsr)EK=mAi&q7W%GT3w+d)XGP{?2WEQM6`EA8mH zy?hlx^b%OXr5|DUpw!wJAM9G!J}LdkABtneGw&L}H`QBbzrw{XO>-(L(~cVorr*<` zhK8pWR%MFjm!UT`kR|%}M6zYZKh?K;au>{*5v}d$>B@u&5R>$sZBiS6b;hRv6J2@d zldRO+Gkt$%bSbz!8a*jL$O|+{*eb%v&rmmW!h!u9s+OZg7s`DkWCJvfQ+5WFG!Wzb zOrFnrd@rzg%W|+Z^ZR}vxZjbB%HpV;WKuao_C+82!7?ujtQ5tt~0I*Pf7ts3vAseXMnA)B3$ z9#Ci2H&v^~Pp;Y1`m`3nSAAAU={C=IU8ku=$%3zy)F=l7d;hhlxb;WF&nF&{XaW67 zmmh*V6o}L*c#j+DEaUZxFx3JGPw+H zmyu>v6K!aJ7qt+fG(YlE7#FJRjFEQ7;u#~eL((sd<*FlUmyMVzbncXzL7j3 zD9)8D$QV3SbU@+CHndeNp;lQQnOF?;LB-{ddN|TqU%}smVsEE-#SoA)EzQbTxx z8Y~J9-rz}zu$H9#nKKlY1k_QTZCZ*kd3El{Dmf-Ynxte2QING*pu^%M$l00*o4!EW zQ+W*xI3-vTmp0s9Ttfq)Sa1=P^ALARrHfeCp%IWEgJ3~42pwok$OW-(cLaFCD#Rax zLTJ*0aS@pL*x<=0ioXj(oJQ*u7RxaqiAY6CW5bFig6E)n-J$;VRfcVNyP*&?H3AVu z3D&E140xANWlX3)&GVdyZ&gv+M?Q%&BI!2yTmDk}0}5$b7;)0x7OO)m60DZVFd)^p zR|Zp1SG`HUhxs-cpvnvmh^}gaNXAauda6?ndDkv2L#t1J=A3L z(s+cRB{cIX60YjkW$a4$X7KvbQ}8-gwnT{43)?0>h);?058b~fvF%=5dO{Sv-Ou_s`oel4j{UVg zM!yPByeVz|1hFEPGsVw+j$wB$7LmZ$=T4h>u-=vbP1wXqS^cSJ1D^H7IrQD5oj+q* zm=zdxLdD|B?1$AL?O>)?dZb$i7RJHc3Xb&m>#@ohRy#bkpn<(){Bf7km|TfJofVqu zmc@kj+6dq0yR2|*lop_LTcX01XrLqAsqw8AibjlpQ0bEJ$1N`Sf{ZD4ZX!7gJ}wP{ zK^r@odZ>P$`U7qW*Rwl(#r0?_kVDRVfne*Ad2;gjoId|of&4RQZ1u(ivt$8k46S0v z4eU~u@5AF5#ta~?#y3>R?!fCxLia!+s*h)mZ;rbsbU8s!s=N6C9Va}%Pd69~_S1F2 z9prVT+XLYTh&S!zpirNjoefwZdQ>U5V%N0lYQ*7HfU7I1{f}dwib20~2LV6z;9YLy zP&vg-*q!U&UaD{>7lWc-F(#9Wh!VB41{yjBesX7A=6sWfB|=xL<0kRdT`lujvkmzp zPN+Foznn);v8RsXZeTaKwst8s!>=}fKkI>K>Jz#lEQBBCLp80k=4nG)41(Vni6jX_ zmaiqU|23G%a2Vkvqk|=-wu0GHf;<}};&5mWa6)byZX8 zZJ8LjwY0`~j9tNZv&99&^ZIF_6Op9c5k^g&EM9?+Z;l<`@2jNEnG$2554$WGjMPC- z6~A(9BAag2 zyHG5#=W9g6Xg4&NM4#&_DTci<=#Gj}lm7eKO6AJ&u;-=a*CpSMTUve6w3TFV#c(5@ zu*yvGCg&;8Ws4ZZ4J!Evsb?b0PIHX=EvL-C?iThvyWz@L69J$p(Ce+;+Qlz(fmNv~1wq6_!!Q+8_j;M2GiM2|LF4u0?{-NI6oH$ZYz|*W#>5#dK|4WZ zSI+k#Tj5i0`m|lG&{mIJeo800*jj<})r*CeL(fS1yY`k-tMVqI^%kwWk~4byKVk)7 zIsm6)SKg$ZL!fj>?WQx_QLH$|c0X=+dH@nPYPO^f_Xk z;Fkty)v!sBs4UZKBeVNAlZ<)*Lf%_vD(Skk^Vt;=dBER_&#`TH#KeJAqxSMXF!bMT zgfgrUA1)XzgMhMACNjQ>c=RTG!Z6)#0h^!95GCTW@M*zi6GW$*Y2Js7qP%I-r(&;u zJ+v7e$z082row(|u3CWMHH{SazwVmzb7(F0FkKuAYVv?HW1(yI z#b0gq*R7N8du11^Q{VLNgHMOabwTo<*%*;GKkyH0!!KT5w)_?aeiGH&?_s!ptI}oX z*mTsiS6Q;IxXL~E--;Uz2M&;4lFab+Zw77{iMX`9+@s`_|-joMC#};{ z2G9u|lQq+m9p&%LDDh4lF-t_(Z@0u3V#Rp4w66ts=IS#BuaNB|2*P%0SM$$i#3k1+HJ~G+g(4Jq8{~AriTMw0c(}pbFWU~3m z<$8C9&gRE&(m1!8%>KaMgUb}_ZArMxlw3FEPK3pcEqW)FBQjOIF=f2h(pA5t%Y3bl zEgs<&5r|ShO|w~Qw5kwtmMFCrDZLD94!d`3Z*`tgsbPd< zJNKZ}c|%8Bxop6xbZh=};_loORaDkqQ^&xVY19WrUo(eFKaF}?;h=62RvApCOE^%= zNJdRi(!f<(mz1nO9J!5{10Bz+92?!_O|{XirVa`r?81*>@aw`+>BwBcK8dFGfKXKJ zM7OypF1ZL}CC@||=f%j@wya|WQ?VtbXRZ=CVZ#}A73Q#(3Y#`je?j!#LXvFNUuJl# zNM90Pva`#fD~O7 zhrAKfKv=>%KRwHptp7Riapdvud^fJ|QmNjQg|04goQdADhQFy|T1t#Kk2zu%iDt!| z9dIg6kta`7nuNXbA`eIl!4L9sL%Qu7E35l^zA{|gcg^1Pk&DZ&e1ab}bOW62G5QW4KD0Q00?XED!7G2A%WJs5%C zCFDVa{yd@?4|y6f`QpVVW8y=YbIuOB`bh1SWMD1G!7cl^1&oTJnS*u9lfG|DG$H)7 zZF!NvRJyfO+0l>r)fuml{NZSzXo3AeyMndj1~eo&k_ zwPflp$V>$5{+ydXf`tQR(-xRs6*C6cqev!B9B>=JatxGM1<6T?L$S<`OMe`=NX5g? zE9~&{*JwjvnPRUiTH@q>2|OQpup+SFg0%7($}ZZ6)nY_~30iRnEiy8}QW^zl;1^33V(u-f|D3r07Sb?0p$h6`l!|?FQoQ_8>rv zB}jx7dO6EMLusI$c^lHEOtCH$>>_zbo0P)Q0yHk8w!Gu1QNEfH;*3xZQv4f@DMqfD z^m%d6M16;pTHvqIL`B9@k|rx>|J*W<6WNvf`9zZ|F=!E)7jLSxl?B6K1N09C9i<0*RuF)C zo3k^0>zECzHFj^S2HaBmvo@hz;kc>S66aJeGi3w-`}v3Ph}P);R()+

    X}Vu5}Gxbn0zDSGkDhFlC$mC@JIDlj;39#Hxb45}hH9 zdzT2ihW&Tk(GE<<7f4dn>V`xud{tI(t@a4cz(iM%gwQZBf;X4`bSFnT(j_I7_2{N6 z+p;y(cLgEP3mqHl`3i!*?W`ZACm!W>j8YI`r3F}UJ|JjQkkXngn~?NQ@*^fmB6Cqb z$>O%}&y_~6VZNr#i1R;IKeOTpyxpJG_R6A<-A|lh9+1YsPZBZ0QhLtk)CiifJoN{aC;X9mWIf{5ZlIxuWB1ju&P zAN9NbkYE2jA)4g-2`L)W!!6TCaR^pd>Z~?tdyGFwb;tV@2i+e!ifm#5-ZF9e^K?Xk zkt!B8C@KT^)i}3*;3zsd`-rYDe)NF_^kOY^B;U2*i#A_&xj%@M8?R^EqO?NeY%E!X zIO`^wfC;tKZRluTa(EE&RcpTUt!^%U_^Ev>AO)JsG})sBXL!5eTzH&m2Mw5VRN{Kk zQ~qS0)Xu7xvZc@X6|tH=>)d{fEhZ#*XuQoOx3EtF}=|4#hIsF&tu`TNGhK!~EMz&IBb0gBufo+5!2 zj5{l0EZhvr*2f2ugnL=rX$L{JP{C zMLbFlf{SeJquWWN56m!}J_^AWTB*X5vzmijFQk*qZ4X#JOkX|F-%{{=N8$V?WkaE% zJ=6(C(+Mw{%2`abx!fn$rMTrX{bcU$AZ8qWW{V1KM0%DdGg^=ex)v!$Ogg4T_d*Az z6a2_Xa(ZO144i~fAEut)Qjlm0#I0k85PZaVc6jd^-~A7cH}4sToYceyg&*J(d`Sae zHQ*mnLhE?DsSE^rzw$T@1w5lV8Z(u;ub=hKhm#h2BVONA#XPR(i5C&@Tfs)3&K<2p z_d_Dud+cOZO%{j%G{T6bge0rs8?4@?#y0y98 zcP%q4T*fxpFp=Hh{bvROlb%A=WgIpRgXWV8Pr-7INZCe}p^slcz9C4gLU(F%>foJ* zWE(eqr@2ofORw!RPM2GU$RBi1;7TiP^R-}rZuQ0gZvYuUgE8^?VqJ6)7zjFuIWH&wv=XsVDQ=M4|DDL+JNzZKUuLyoLr8G`fHI$RASmmF4sYm0P-w0Y@kd>{cD*2YPOU7{~Bo~xM$ zxL-eY161Gwlo6zpPclQm{3sfI(|g&U%S_`B%X^9_Y2cRrF-PtZ#9Iy9tm6$E064FW zJyK0~P5DPx>#c=|kl#-iJg(V-$<`j2G>FD_5VR{MT!j+3Jf7%c5F$bN)_mtqYnZF?^n}`)Uo`!90!{DepjckDhDH7UesF_Q=BrV zjVvSm2pC=lK$o7smT{mCr6(JEXpJVix<#EWB{@?;znsZ&SI1LQqB$;4hcOHXSF*WV zp&M^HG+-tkY2X?flA2@RfY26|RZsx8JJyKe5+npBO3^B4-(KK+c-w_T136CTEV0$| z8*MNc41Ff~TFb!K-|h90B9fXGzEn>_BSLMmRT}OamdQ)9tTk<1QfZNMsws8cVZf1r zK^Mz-q9E&-W(a19R2=b17a7$iI0zjz#t(@RRd|t&_E~=1dbgVWR%2DOU1+$G$&qih zJGe{*UL;sV0CvQG*Od$HsF0<_oAyG-nFEQWz;Btsfj@=1G35}MdR@hwdW{0Egc{*m zRK@44Wx?l(#s|6ERDL~AeXMJo@5*DoKIb3W{8Nd^Q7^r2!w}cm>C5|O^Yez8>w2ha z@Rgx4X+drcGnvx7`^YaeI;%guQCe562SpvC^aDMo2_4yW@J6|JQkA@Wl)0PVH`)Mm z&+2vZtzs>?*rN!$$)u#nDvj*3Dy2Q&qloMCZ`Yf32$;x?SO-u|)n@VWt>2pvuYX5Y zr<=`}p|h3C9k}Bx@ddT!A#rn15np>?mLTv(KNR~r(!|dm^i&7nvlG3~#xA?)8#M3E zXy|JYj9tjVJVyucO)olOVdHjWPQ}ZOR5zb|BJqclW2iCcx4GyZ_`{1YTrAen*8K57n}i0yGaUbn7}q5uQ=oh? z)s1J6O-lq!TLcjGp}I=}*oxX__gV$8Cf}rYLZ~IQD5TGy13D+Hbn}GPb6cu`cNzgP zfDy4)OiXX9`vvu!JgDQ-kh=Qt5d@?je5f?DX{wQnZAiHJf?gG1*_gA;{Ou|cUq!vJtkE)&e2Z; z1YpRl7__In(O9{8scI>C3A)u;pyR$B;QF{tAR745w4!UngQxMd)r7Q) zRtIE7y&ToDY zy*mf`BhEPJz_T7;p1Pvd->;$QIICP~xQ64bsjc7)EA1LZ`xh}X#YJy19ZE4=Z1Ajr zj0Ihlt)apY9)x2(hw->_Lu2nei34nu5mWI#9SL2^nQIYVYW8Ig!GyBqxcQWW{`qIM zS{;L3w@Wp=C_w~3JZ+?&r9~;LWqK}gRl$hQ7H6!W?tOFYraIToh8?OPEJwSk0 zARnF`HsJ7hs-urCL7kMU9@ZBvShcapv8DqDc<-=<>YQ=*#ecP3PG2d#uJ@^OW!9E8CPp zN7gwUWydrdPOW?nhsw|w*3^m-mKWB>!ZXj0&7JR-UDMZ>*6uIsS@!?Yt-W8wY|r=W zyFD$3lGZ=5tM_D6!5Urj&_;njp`ekBw?F#n86B@b|DbYV?@(N0UYHb*gxR#8YyBle znQ#oV6-WL7z~*;f~NBnK)6kw_)~fi@4muHgI2(Dz%kYF4@uP#lNTLpBvvhUhrR^>Q9QF z>>rCC4VRC+fgl69I|P8tymdx>jGr{(!5`4@JH+x!UeWg^qD&P|2U1aA*rPNeX{Agv zdf^#eMJ(v3mvD!;2p>`B`(2z?2-76Iu!c$_ITF7YDbT=E)>#CYuA%zF92u z5Dqw|MimzT_R;3_L1Gm`K(HPM1Jfy%WpupZz=?$+8W06Bh|ZggsZ4&U92PiS4i1~wMap-z#wKH(IO);@fz$fjQCS*ZZtC^|`E1r}+nkEAC&p|LaPGiW- z8tftgq2~Qc`N$d@z`mU_46+EjfFN~TKDHXkgTS5!e&xiPI>B#Tw-i@-p?MnfP&WG0 zEDZugL|=ra&-@v0Dyt5h+#UlxUlxk*c%S|bIMc{c#H^pUdxHdgHkE>~cnw4Uk4EqJ zH;F;+%!n;duiTDS_TTzI5%kE!v?o{1OWjr8|?Vh$P0*3DJkn{eLi;<2L5o?*_mn`2sQXn4!18Vxrqn$n#XFoRzd z+3-4T%*^2v*P2ruZmSl}HuAMY^I<_5%%X&sxM9}2o#5Qz7svq=EcFv}@dlBUO3%6q zOmyzj_|@Dxse+WS*eLFrmMuh=K*8ZjLjnzk5z8LY;T6j*Mh=GqXzsaiG7sGZD2zB*&v0yB%=ZJlW(>q5>6 zd|JV(^tF_{V-$tZiaO{p8D62w%d{Frx?yF5aDJ>au|Bj z7~GVdAsX(flK-6EZ=S`5s>Rh=v6r`~Y$rF63U;>-_J(xARUWb947R@<6nZ7FiB*?> z>#{ghR+Q47&}rPBTq)i@W}b3?T|HhR%d^1;0%5OQ4N4)mF7Ort`gH*^kix4&R6$>$ zy-1npRdV_oUvD1ht{Je3Ul8!hJ14qy6)+4S%X~OD3spr(7d5|vdf@RGddYo1{Q<(TK?N|le(SAB&oHMM@};A)^!@%p<-wZy zA^!Hwf;$_T06^#{;nbZ3)~?sKpzOGK&)H|keisJbU2uxDl+g3|t$2E-BHHc>681JY zRuRlE!xk<8kba(~*C!f-fK|w3z$Mk>Hm&2mF#y9Nt)ggxUQUD)|JStGwsvv;IVL|v z-H;*v!%dtg$$TbZc|*EcmNK!M3MTIkGfTXtAfvdy2Yr5HigxnENPXqcIdye9&fpu{ z{TriFb&Y>~%*K_8)qKo1N3p*Cg##gGzKlQG4_QdFMwM-fF zWrOgTv=Dv0hPC5Ac~g$cf_Nx{-(gT|Ln)z>R0bb{`bKe}k;k!FF(X9B10ex_$U2>d zIDLzJhkOU~>iRkj2asU8aSg$2mNdfY?7;F&CJg|R0A}@|09OQ8kx6Q8=`+IR{(XYs zIPO_DIPr?p*HPUB>hpM~Dd!X*mzp63t|Sn`;HlpH_G)By+1C;Zbzcy|MzTkI`J?mx z{uWuq?>3_`y7u?`$KMfXp(>QKsA(#`I!U2PxB1ZsfkCcd=;;#-UdLV!Tg%UMjuk{* z9~W{806NMWpnOT4Tc7Pq&>8j$D>9VC6DT@kP zuhsNRxe8v>3JgZICY%JXvoHQd!DT5kBJirL-#12YlpT%=r~8!POyNc|MTVL>58a)s zj{LQ)`0T&FrK+TVrb$lh))ekdr*Iu8lcR~AAk&q{hRePx*#^(h{NVqifza^3W&MDE8an^@G0 zDhHk~K}t6`y1T^*T`HDLE*@tziz(yF1r z@zwQtz8m5j#)zloZyMyp-oNmUfvvm~`alWL@q?)s77@433H_h|JUrJ{f41T1lr_y7ek$v7nFza+Jb_otw70x|5J{c8wj z^xO$HKVQUc!VfkHM}U&w5OLxQ2Ny_#L`?J#*&zT&4L6j1;UNMoAC1)H7yb)sP5~Q$ z!R=cB@#k3nE&W?=l#OV%x;YwOi51%`60E2*3Sx3H0pfVi-_}uiJx$%E`$zgC8{tW| zGN5M({ZttsDu5D5P_qv5@**PAXv|h(6a?|W2PL)tCC?5X>NW4qUVMU^Y%6epo9t7v z;ae3b_ybg}8GtzUD~k0A-24Gj>8bE4ElE$G0_N524)89|pwP#nZP?w#AAH#0$pFC* z#13=DqjJk$H{^V)5so~mryt#eEbzHG;Yq?PG#ib@>C7>$c^naX>@~w)3zYPv5Qr2@ z(cBh@^u)o=AZ*sVKl~`BltJ5Ew}gk>`OjOFQjRo0guX>YgH~r6p&vKjI&cym`tSn2O{=r|Jf*q4MR z4-@4tX&Qe+OXaYK4)}i{i{%k(L&7ypFvzVn^!nlylW0nu*Y5EKLh$n&*SY#K5 z)@8#9=oCjs*h5g`f-8f9#Q(mQ<;>a=NJ+=ebO*Ec*wbQ#31k%AHI|FZWoypWa>BJG zQj$NtoV>yrK%ZRx5>j!l)6h>fZ+Yr}%s3#3lTDE!7OfGSLh{S621?M0EdgWRSwui) z7vt)@za&V`Jso@|gh>OCD`c^C(-N4K0<6+-9s|(O(h_?N((=HM4F@{`daWGOx%8Gf z3o+n=!e&XPnW{a5VaUNC2b2fj$JqcN+f!)}-^EKai6I)6@F(cU5X%TLR!2rA>Bws6 z?3%0_p`%nM^ddV+2L;pi{JcWW^QR?)-V>7Kd7Zx=-Apd{qE0D1Q=bkb}H8fNwoeHXbx8whD)RK8M7oj;0loTLT z;*4WD#0GBbgO67mr%QPSmhTvZ3)toX+W2=qxXC(%_X0i|uuz+*4{``-a5xVzhHeUB zDT{*5&XAjDB9}xHFd~Lj(Nn@^oV`Nr(xHOdf)xwZvMRE&42HXyUSOlql3xqqQA(M% zsUR6LSMY_~$k*$Ak`;QL_~TlZxo4~#OwV;q$oNrgceovk4;Nvk0oFBqN z(HRk+Oh(k10wTYnoh(+uQT{u(yHVF>Qw-_f_jPI7;)=*ia1z)qfa6Zq!+w?Rq2$c` zjt#Ml`d_*t1VsR70AqXSijB}V-<#(b@fuICU;ky25KxkNrE)kG5@U2fOv(KAqoAzj zWH4>3*1xz*0Za4tE;Pb+X%`~V+BvglT1n4gJElym$?IfGLxC5lbxNb!s~i?$&tv-7 zZ)s2An3%E1*Q;@@^@?@_IHp>Yny#pIwVEd>4;V+0Mt26mg6ub#M4U2KBhQD;Dn+pjZ^pVGTZ;52FMl=x)hT)dr7HG-G`V{e-R20se zal*oAsOn0crFY{69#e(78cL(zoc%z&$xKjAm=rr+GGNOsFcip-jOjalb19>~Os=I> zDbcWz9e(h5KlRds%qoE7(e(J1!BwaYDlW2_K20l7_$5JUNCq1w7mJ*BoClO%i6D&Q zXXE*LZlk5`3_W9-YZ0w_zdro#fgSY&>MNxim}=`A7;E91DEK#z4E;-*)o0}%LGPe3 z*T1{|UZLBI)kmChw|qT=g<0=MoL6DDb|?lRo#$N9Bc<(H-=X8g26BvT_6mGM=V;y# zO7bUtORE16US!@7Tr}|pcEs@pnz$^R;rp$dq|Cqky&xX&T@+h=ns`9wk+vU8b^Se` zQk@if+Ouc*AWffH^Bc8J`e75$8E+{1;;FKzHP~2soNd)8sj{*?u+%I+Sn661toK4q zDEdn5Qz(mmZOsC^&SbRspRF@b=wp417x!)~73L?VzOS5Ea;DbH@wx~TjXOyqdFHZF zNh0eNNh0T0jOblPjOtTugYB%P#*FY2gQZfo7fbM}#|0$Yo025|+k7Cx^RbWm0O4RA z+110mJ{Zv2s|y2#chVDa04v?InkTqI)E6WRnd)ix+jmFvtfJ7BaNGn|c@#diSr0L8DB zYpGi+8dr}cJ?lftO+RKOV~AZ23i1HI!5lGO`g?&rVBj7vk>=`)dWEbWa3S5= zN>PBd2nUdx7kbT%g|8(b%Wo}?@V%yRB60?+w-#5qT1^rUF5qnIG@teLQ#JRK;G{Jj zBe5eK@m&=ue3{`u3{-P6>GvS+!%(GAM0+>K6RFc^Zlo$d8ilBO>tRk(r)C#aZw{aLhQ9p41g##k zX}QZ@AtEb~bCcX?!NHh+T@M671zaO~Z6bAVF}+-7Q=aez)lYK=V7ww?Zgcv zaE|`GMLXL4tG8DChUSg-WtL=w+5XHn;YcZ04>4B1>+ZKkj^PyopV~`L86aOIYF~fY znAIMw)!h<(AT)hXyzSxkS;)GS{YIv$CRG^bY2O;{{3~AAE9vR%+xOD@z?e3xu-o%| zcz2DG#I;s}eure>H=mBd-^TRfBJ_)?)KorTJTxs9~fXhcRSu$P(Pr}Is`d)hH6>|2Ds5?3MWovjRR!3{R-M~mffO}d>Cd|mKi4#cA z^@rRCeDIaj*|v-jnRoKT^sfm@`MpoP2zLqlRWh$>UO#LIJ{V7()XR3|;c&V^b3U1h z8|e^A4JF4P)=X3UJ>!CY@U_zl$_A`~Lb24P2p}8RXcrtAX*&s##Ou zw#`?(Rcb;M9#>PnXMtb$TPNHp&-;n*c@_ELbr%jWj(Y6N$5c23XU=J;Wc#|A+nPI> z-zeT9>~x`SvOfI*igbQL-(D%P?>FC#y180AHWOD}fT0$Jwim^ytu5XiIqR;xiV`Ew zc0qYBo6ItHZDq}I0F0)&wMWS4DN}c8E&qwffN+XWylUyfja<9tn9QP;nzC8mPvwW#lvSDC(6J6%OuX z%0hI#38(NNWhHmlU#PJBHhe9{4MkYxdy zfzu23^6wzh*1XYs^AAA4LT3Jli{Mx~N}sRCKr)1Ny`hN|5u8y-$Drk7vzp7T4Bd9j zcwilhnMirrU6~t-)}# zn}!t-c5O!=bQ3%MLW%TJ)AL$e5r`QV@bp(HV`L;*#s{Nky{NzrXrSaT?kvKj#(I_| z<8KQd(~Ih=%c{bW)-aWWqP$#!!Ze-F7vqVXSJkMvD>fN=9O-(SjQvuZEGsPiI{V>$ zO6qG=9V~Ry{w1!~0p}T(P_kxTL*Ckd1bG(tj>G5f1Vmj0eLG3gKK_!Z88#oBG>mIo z#z!WTGaQd45h~s+G9B00)cDr+2JC>M%Zq}rX!)lu4PJXUQUFx>h41We((lRvt#l3T z4l9|ZX=R36g|%6E4KW@K@NUXAR7Gq+;htkf#3|p4`{^%vZl}6}yi9KDRBLE$JKj_w zb+oNd8kfKxQ&s5VrbH-EYui%PRe7s_5{oY2*>c47EXnQ}z_KO*2*VjaPYzx!slo?* zUY}44xT|&I)1Vfj9n`%DU=ILTXQWKjQw5Qy>MOb%Uk^?SXpLuCk=e?3yCuYY_3oPE zZ7sAE^ehS2O9UWds0DU>?e(eha$|pDw0E|%vkS*% zj^IW7?>Xo12I3v>yR*8FRcIbIFXYEY%gZFA`g*8qS8m8g8# zKrv=MNUye3D>*E^E)v|^nZFkjHc87EMex$MdD9=AB+3u+N{n8n3f-Znh#KRZf4--p zd%YcssD&!U6f-$DI?IZoMrI&Ef5X=bt`&h%8_QTD{bDoLRulcXW0W+h@XTMvIDrJv zLf4@wkdp^xO8=BP6Mf8dCf(#gE~bIMe$n{A0JWde3{zhdA85=kln70Mb;*Qi-W^ji z@sjhV4%gGpfJk3M$t$U9c{EG%mO!W&pW`od{s2ew8c|nm!MMY-yqg&Qj-{^=PZ+PR zJu`y1L-Eya6e08vJRAP>&eBzNj~VL6#vW9sbtUHeTRDik(~A6A zTc)Q*c_u*be_eN*gR?~UA6oaZo#i2H<@wj;_}lfcuHMp3)+lB`U(vgtn-Op7QgJ6q zZ9bN@S-@r-+^e@40@LfNxum|I0mTLn*j0hhbh~RdtVp9awypq_mH>-BAManOu&7@9 z2b~&{qNez#C6kL34f5mKT~u>42wIR@K|!oUtH!ze75Uc|Eyru9dbbwKm592Pt$83H zI#FMGa0G^O9B;ccG#0m+a}gBPWeX7(q@4vCp1jAv8vDH}wVmapCpwSClnMexL1K{J z4H9MdC+?enQY?gBDDhPS-ZH{1Kuub6l8NvuUSqMFu8E2lA` zNj^m=08GQH8;!1~FD*aQGSk>b7*eXc%NgG5Phh2VtU^7hWkIlOPs7_fUNk-)8ZX)o zO4ETI&o6-^8Pe$M)ljRt>$@w)o?Y8&dmFvKvTrhP?N}eN5NV|<(v;}S4Gw~DnM}j~ zkm#hj=^q6D-@uEh^Uorl><+B7Z-5N?lW9r~Y&)Vda?ih>OywQ2@ZJYIz!c5c3P^)# zP^=g9Cc!>sVk?9&9H9dn+DK+N50X?vxIbQJI6#EqK5aWycd{zdL3xxz^+m zN>v`O2ACp~2MHn;pIOu*W@!s8BKa2_127MKB4$pIWrF?$fx?DNLa&XpX_u@PdQuE+Gh^v_f)n7DR+`(wGobK@5 zAzH)W5fq)Z);3Bal!>6NZxmBd4~ud=e>_R3kbM^FD{d51ooiEkcSN@cA(y@w#A-<7 z_~8$BEMaz=(yPOg3HMlkSbScFw&W2tlp@->=tQzaSiknSrP<_R{07|}CRb1Q##c-D zU~W$SkwYCiNR778ipq$9P~HJl9I4aZpPd6FjBz-l**@U_&y0ibNI)joZ9R!m!stJL{uoQs1qo;vYFqodCWqJI-_&2@ro6${jjFi(#_cG;jToz@@*<&ScE zn!Tq~WA)s$<9k6+$9~)hityiBOnw#Q8Mkins2GcH9{AVosr-n@V0ch8dqQd-ubVblgDqQkKE8 zURIwr+(tipmk0x&WE;)kuFLW_ubwhrq!K`YFE>yaE{cFWzz;i3`imRjc0(Tra*r@1 zhyc&e^?v}DOW0{GM1EGpc+%Hu{FF*!ggwR4Ng9%39FH2r%l(lZ$F1yXh2T0gT~yEe zIabJ-EI5YcluZ~iLQ{1Vv&reNfMZxm6SkXXhMBdw`mGYOECA(p2f08}yI=k)ft?jB zDVONwlM+?1J7J8mZMOv*;M`#hBOM(YWBVHb0~%xO0rv{K%PO@>H!KKtdGkBA0nW<3 zTRdXQ?aczt!p+l!&eDL^K+eTQD)t=;Vy^lf!9y+b9SU!;R-G)5t0tjEwL#vP!zxA7BDqR@{FN0O8yZ+q_w=53$8E&jXZ0~ zR;t^aJQOht^~LcJdcT-Guj7D3x%L(@cg_6VP2$*jD=%bJK=fw2w&yNJJwvCq3mC3cdibHfVvwF7hk2e)Cph^m z8e<6Sed9RV3L}W85p(GQkKxlS_VU6o%xnzs%LJ86g)q%>; z0o|Sqvw7GE4LL5*er^0mH)9b#H?B7 zAftw+n+Ty>2rkeQLS869KO@L20#{)W5|`i|%>Ri01EvoBOm$AEkPoN~eZX#17_f2& zc;!cCKG`{+XF;)`5E*%4gvTC^q~A$IO0Bfs4AZVoxRpXMfQ{!ZBbQ#d@J}TC2h>VM z-0O_O*x}*sEI)sUCmqt-k;!;74O+0dK0Xw=%yS|e%N;UL)M=Oe(qdU3Y zV3MIJ4IKXhFag^HFppk1;89hA*%{~yx&&&|!Qrk$70h~e@ z57yB{LFZJ9ZQnWkM0JP84=fVhA5x}$gAu34m4F|wRQRAf7H5B$mQ2Qp=?oJmZyQX5FN_{;G!Uz_kNWd~F7|5d z>f+~mUvo#(L){hW8smBo_ltdx0x!E;S>2ZXxtp*hCEEteoI#%?h$c~+}9*6q4ZZu8Wwu^R~0W9qD!T1uL{Xj)2FBuHImpv9sD1CeNh zX7o{LgJE~S{NJ1>tDEbs6qM=$LrPa|5LmwnNo#2AL8KhS2|RcncXyD9tkXrkKOBBn z5DLHz@_Us9{Xx_bawE?dazoq~{vYvwz%v^JZ8$-{FArzr0g-SFIW8XE3&YPT?>Bre zm~qqy{ZwF1P@Y%H3`qdDbjYbZ!z9V0>Cflr4?!O?Dsvq0!#V<>nb=lxDGh8KoPkvL)ZX~FU(R?1pO0s6J&;g?biY^aB?bJ%vi6Tyt5PfoJB zycOphTaea+tkdy0AX_LYmzycf3xSOInZb801Kjdf84t;xEfUfb!@*QnE(nP%F^4Z?&tCuGUn^de}<3lGY) zjsqm^f^4?HJn7&zjoXw8D2+*45RQUL-ZWY{ck?&njyvV!uQYMZ(DUzX))zg&mt$ic z!gTI^gKhcia0K6=D1w~H$Fcm)r;bqV2xrv zL`T#Y3PMB_ae{|590-FT>To z=@o5a5*fFf&ExHqfKnL*mjp>+PJ>sjJyOB`M37Lp!jB+-fg@j5gHNP*jdoK}sAC>c zxCl$LAdJs$6a`VtN*Zz8ClMw7+#|+jStZ)3P=m#zJInz$3UtF{qD@bqK*@uV7h;Gh z6d#Y9_GDZ-zzjuOODoLjrRFHK&CsKy-iM75MFc^k#}HfqnUEVIFn-W_#+tQ>TktLv z#&l;ntt0TPQQmgt$^!su5{XTdt9$(ORhyso6%Yv7+5a ztFdBJTCZ^jZDS<{9baQDKNv@24PPYe*RD(oX1PrQA7$wH+iWXM{>QLYn&|kCYK(M2 zrH{!`a*Yu50!8lP|Jh9BHe7k{|x$Jhzqp(Y7GFM zHO>(^!=??tJmdzFK1cv3N!0HeiKFlD8p*@IUWQ|>Xh0@;d{4#4ChDvKO>V z5LNrU3`TcV67)4&!Eq{Y(nv+ZDdWQhBDq?dE}hUNAvMsEvnKj`?J1?{EV=fPmMMpK zeTe#ZSpnzy_1L6oH&fGtls$`WiFO+;-d%1Tqmp=l&Xd}-h|ZIXb^;eIn>_{>DXldD z7b*6x^3Ic9==#p4LP6w+B|@f>PA$J1*%x<>Z%x(UPf9Oi*7F&x?nweDubzinojxGI!kZ-tniFY(1Zj^K_OX;!(Ee_ zp>Z?JiBZNX!f1t9{Q20#5TCJc+ofcL7HYKx8GMVd`Q*8Id(|WsU_I0;Hq7)o4%?-O&@HPQ<;gJ^cKq@ zP>sP_m??%$IOv1ozwnH?-AJlYB3Z?F18x?xZv9##jz5)A(mh`O``&L1{{9DKdLY7> zsu&qUWh-q3)-5D3qW~@cHlyizqJ&W@fgGrbpg96E84M|0mrDedLu>rp(1cQj6^xdf z>ap5F^~&hP^&zxPN`0%rzw&ELRi&?#O7>X#6`Up8r52ts44f`HDy)>JD+DevoDwUb zDG(b+t~I-qS7BOuAELa=s!km012*AoY1=|iQL{^f|Zg1$vxXF=`fI(+@h(Fr64!JCN$0 z>YL$tG|}b@$~s!Or|-K&?MwyEW|9U~N9mu_jW24>BhnGu1`=~7bDKSOey@V@?B&JZ z_C%GL&W6)T%J36a*1M6klsM0XlM;Bq493ZWJ51{5rHrB~8QcMXDPh44Mla;K;F(3P z(6Za+!?Cj4o=sXOU=Kss=3XtpSWa~2v3CQ$dRlpDp_=B|Ex@*3+B;ckC6;%D{Hf^UFGGrFxxZ&Sgw1H%}fw(P|k@=U>|HdPKb@3`T@Ie zo1h`POps;C@qV#IhBMNhMCItDt>%mOQ0s&|?RoVBeb$`{=M`nAvQI~ZO|rV{cr^pI zh@GVfe`syd+pRlG+=*<)PjB=Iuh~IV&z8>Svdad{^ihVTl}<*Mw>o1KCn-WLnK4)} z1C%i>VG@p5x<0P*S|}%>jg}pFL4fTRcq*Gj@;=Y1*R)0H)S8z~Av~P)zn`A>Uc)%F z?7}cZ^d57brOK1Hx%%^KQH>j>d?HMg2yzrfGLnQKu>|&bBB2EA`Z%Ek1aSc($p6&; zf-a|oBf)WkvLjUbk7MKy+mieG!5YGS-x!R~M?5RkYD|;-oZ;E~(|<>;RXfGZzKL7< zl=R&J?Uaj@RZF*{b@V)n+oqq;s%mZg!bf> z{zbyrspXJMay@_L<$V~WRV+V`R3R>XQxA>DL~PgIN}07TA3jSROx?eMQ?~eZNH}Rl zIdhhK*=yl28ywsG9v4b6{eRqOr`5b(?K-D{Ip4=w!)Z6f*=zAHB-o-=+=)H{zi_-tBaXu6p^2_mzkp^%O1&`m)bAh zD`#!h6;Hq->h&aMGAU#}OPvf`bZIbxwr7=B{Vo(U$7r03(L}NZz#TGbJzZ6FkVhO_ zR5!#2g-_MNH<2x>>5)VU9j~iZm|N&GvCWt{e%QdbvO*feCY29(6iA`2%%xLQegD2l z6oU^jGv*2Mt5(W)HXFkJbR7>XpyKv#erv14U3t1aN~)5l+*G8n47LTmo&QJ zuvr$@RuPF!P1!v0b~;{=rIl}YqR%SOdb^|~O||K;7%x_K#cyxI5)rN$@&s~bx`kc&tK%O05=1M;EHDM)Mm|fwTQda$Gyn;6cIEd&{|^xViukR`zvBE4uL$oD@kIgDtN!i* zHbhhBAgwMdl(aX(K_0iphY9|wJ4r-!5kNp(YL66s+!pMRwc;ci?G&{xilQU&O%_UP zHc}TegHah$sDQQX1!41u)bbU49{alXPUjX|%?rB&>=Qcd*{84DB|4p60cNN{(y9?` zX4M`18iYStSS-XsRlb|&lAgUu1ku!`@-3C zxfJx3HL?493oZR*UVONNVxHzG_bFaJWbUQ@;EB*ZE=%1}eM6VIuEcp+ey8BoPVSkg z>YP!$>7 zq(Ps7vVCm94jhz3yEAofKZWAjST$)Dt{*tpb*k!!VtV3nIs?)pPqjN`^ahE`H3LTA zu59|D5CT{8R`kw~8dr_PD1`-kn8K%NWj>+)1L zRZa|k)oAIDU2~3;t3xCyVcz`tZqoGm-hLVv$B*tr%DA)I)s-%~+sff3>Du*Z)!?CGFh$Zz6^9B)W~A~6PnQmZGA7KWX@7=+eC=effqPvnG-Q5e_#MZ@(LYBo`ak!| zE+aj|i+kVLGkn9%abtEpvOe>I0SB3fCR(GT8AzBKQQZ zf2E1wke&EfAp>~9y?-#jAv*sXl&FIBT*8d6{(7v-fX$xsw-k4PPJX7-Zzr}*>EAu% zr1H}Q==E8Hwx|C4>`7QK(N#zt)_@Jff8X@~!O5^8>$49ut11TNtBF61I!dDjgP}Q$b5PfH}X4$Jz}Pixit2C`k;~D2|Q>7 z0aMTn=0Eknpv#Hr1gJ$#pJ7^!WTgsJ*2s!jF-jaG^J<(yvDa)rws9OI(3Bf_vCFS^ z?7gm-0kaV=A!%IGpOfdu@tu8yH*p-~=ka7Zlj3%|O{+O^kv;|vC)>-Wsd%<_LbuTL zpL6%nb8V$1yLOXcc|wR%s4^cG&v zwcW+%CwxnZHav*WATi)2Iemt<7vj^I2k}y?j?9J5G$omtf%SL=nrff$Wi6Ay?iufn_aoPyu_AxuSeX$y z*W9sVN#%qrr2TJ6fR_rz*^GK5y!EQg-OYZ3hHI=fdhft_Qya}YXfwJ-N8);T%1*&% z!c>>W^`N{WwWIE``q;)QG~RLJryaK7pvas(Dvs%#{qlmN{Ij1{V%L<&S-LSt=hK(z z%|Sjh?=i5bJb!`TvjWgM06ipAERK+hAGnXYvg8@w{x0t06EdO$TNr(AMP*nED;FCLIn3jRcumlX5- z#;|!piAZvq{|i*{5f&+D8$_@htr#Gbd0I}=9?K6GJEnrR?QsIOa@8#2N`WkLL*|Pl z)`aT0b>^Yt-jt!^+S-MTVEOIcS%i$(TVZ|keuV7Zv4*nS4#as=s#GZdIfjg`xUG7r zE%J%QVtTFv=SAuBd^&1P=nF%$PsM^fkQc-~*>viFaxXU3e72%21ZSoL$3d{jD>`eY z2;LJT^O7OBnN^EHx?g8<#P^i1__^IA(xe|dDZ)kTaYXa;Gnmj=Y{j5Aof|g2i4uvf zn0|}EocL`-Wnl$2uDpl|70)SrJ{u2;V?G-{ypX`@y<_~d-;U!9F~_o27}=0KHxoXW z`?ul_KP#^AQ^dY#j*q>;_OkrJD3{&8DNqgfjk*4F#NoZ;OF+lS@&_Q4G|IVyQdbR_ zM-#2n7TXpi+`544GfQ5f=>MY6S|N669D9sG6aS)b0-jc=75bm`AJFNfWkM%$H{
    TmF6dNvT(Qjm1EIPe~ktkZ< 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

    b=2BJt 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