From c09039e9638736b6d533ff0f761d7e39a867e2dd Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Fri, 4 Oct 2019 13:24:39 -0400 Subject: [PATCH] Add setting for auth_url Also adjust public galaxy URL setting to allow using only the primary Galaxy server Include auth_url in token exclusivity validation --- awx/main/conf.py | 22 ++++++++++++---- awx/main/constants.py | 4 +++ awx/main/redact.py | 4 +-- awx/main/tasks.py | 26 ++++++++++++------- awx/settings/defaults.py | 15 ++++++++--- .../jobs-form/configuration-jobs.form.js | 4 +++ 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/awx/main/conf.py b/awx/main/conf.py index b95318685b..cacf577b24 100644 --- a/awx/main/conf.py +++ b/awx/main/conf.py @@ -496,6 +496,18 @@ register( category_slug='jobs' ) +register( + 'PRIMARY_GALAXY_AUTH_URL', + field_class=fields.CharField, + required=False, + allow_blank=True, + label=_('Primary Galaxy Authentication URL'), + help_text=_('For using a galaxy server at higher precedence than the public Ansible Galaxy. ' + 'The token_endpoint of a Keycloak server.'), + category=_('Jobs'), + category_slug='jobs' +) + register( 'STDOUT_MAX_BYTES_DISPLAY', field_class=fields.IntegerField, @@ -773,8 +785,8 @@ def galaxy_validate(serializer, attrs): """ prefix = 'PRIMARY_GALAXY_' - galaxy_fields = ('url', 'username', 'password', 'token') - if not any('{}{}'.format(prefix, subfield.upper()) in attrs for subfield in galaxy_fields): + from awx.main.constants import GALAXY_SERVER_FIELDS + if not any('{}{}'.format(prefix, subfield.upper()) in attrs for subfield in GALAXY_SERVER_FIELDS): return attrs def _new_value(field_name): @@ -785,7 +797,7 @@ def galaxy_validate(serializer, attrs): return getattr(serializer.instance, field_name, '') galaxy_data = {} - for subfield in galaxy_fields: + for subfield in GALAXY_SERVER_FIELDS: galaxy_data[subfield] = _new_value('{}{}'.format(prefix, subfield.upper())) errors = {} if not galaxy_data['url']: @@ -797,8 +809,8 @@ def galaxy_validate(serializer, attrs): 'Cannot provide field if PRIMARY_GALAXY_URL is not set.' )) - if (galaxy_data['password'] or galaxy_data['username']) and galaxy_data['token']: - for k in ('password', 'username', 'token'): + if (galaxy_data['password'] or galaxy_data['username']) and (galaxy_data['token'] or galaxy_data['auth_url']): + for k in ('password', 'username', 'token', 'auth_url'): setting_name = '{}{}'.format(prefix, k.upper()) if setting_name in attrs: errors.setdefault(setting_name, []) diff --git a/awx/main/constants.py b/awx/main/constants.py index eea1a55820..4c98d264dd 100644 --- a/awx/main/constants.py +++ b/awx/main/constants.py @@ -51,3 +51,7 @@ LOGGER_BLACKLIST = ( # loggers that may be called getting logging settings 'awx.conf' ) + +# these correspond to both AWX and Ansible settings to keep naming consistent +# for instance, settings.PRIMARY_GALAXY_AUTH_URL vs env var ANSIBLE_GALAXY_SERVER_FOO_AUTH_URL +GALAXY_SERVER_FIELDS = ('url', 'username', 'password', 'token', 'auth_url') diff --git a/awx/main/redact.py b/awx/main/redact.py index 1cdd997dbd..ae60684377 100644 --- a/awx/main/redact.py +++ b/awx/main/redact.py @@ -13,9 +13,9 @@ class UriCleaner(object): @staticmethod def remove_sensitive(cleartext): if settings.PRIMARY_GALAXY_URL: - exclude_list = (settings.PUBLIC_GALAXY_URL, settings.PRIMARY_GALAXY_URL) + exclude_list = [settings.PRIMARY_GALAXY_URL] + [server['url'] for server in settings.FALLBACK_GALAXY_SERVERS] else: - exclude_list = (settings.PUBLIC_GALAXY_URL,) + exclude_list = [server['url'] for server in settings.FALLBACK_GALAXY_SERVERS] redactedtext = cleartext text_index = 0 while True: diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 161f9181f9..eb2d48546d 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -52,7 +52,7 @@ import ansible_runner # AWX from awx import __version__ as awx_application_version -from awx.main.constants import CLOUD_PROVIDERS, PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV +from awx.main.constants import CLOUD_PROVIDERS, PRIVILEGE_ESCALATION_METHODS, STANDARD_INVENTORY_UPDATE_ENV, GALAXY_SERVER_FIELDS from awx.main.access import access_registry from awx.main.models import ( Schedule, TowerScheduleState, Instance, InstanceGroup, @@ -1883,18 +1883,24 @@ class RunProjectUpdate(BaseTask): env['TMP'] = settings.AWX_PROOT_BASE_PATH env['PROJECT_UPDATE_ID'] = str(project_update.pk) env['ANSIBLE_CALLBACK_PLUGINS'] = self.get_path_to('..', 'plugins', 'callback') + env['ANSIBLE_GALAXY_IGNORE'] = True + # Set up the fallback server, which is the normal Ansible Galaxy by default + galaxy_servers = list(settings.FALLBACK_GALAXY_SERVERS) # If private galaxy URL is non-blank, that means this feature is enabled if settings.PRIMARY_GALAXY_URL: - # set up the fallback server, which is the normal Ansible Galaxy - env['ANSIBLE_GALAXY_SERVER_GALAXY_URL'] = settings.PUBLIC_GALAXY_URL - for key in ('url', 'username', 'password', 'token'): - setting_name = 'PRIMARY_GALAXY_{}'.format(key.upper()) - value = getattr(settings, setting_name) + galaxy_servers = [{'id': 'primary_galaxy'}] + galaxy_servers + for key in GALAXY_SERVER_FIELDS: + value = getattr(settings, 'PRIMARY_GALAXY_{}'.format(key.upper())) if value: - env_key = 'ANSIBLE_GALAXY_SERVER_PRIMARY_GALAXY_{}'.format(key.upper()) - env[env_key] = value - # now set the precedence - env['ANSIBLE_GALAXY_SERVER_LIST'] = 'primary_galaxy,galaxy' + galaxy_servers[0][key] = value + for server in galaxy_servers: + for key in GALAXY_SERVER_FIELDS: + if not server.get(key): + continue + env_key = ('ANSIBLE_GALAXY_SERVER_{}_{}'.format(server.get('id', 'unnamed'), key)).upper() + env[env_key] = server[key] + # now set the precedence of galaxy servers + env['ANSIBLE_GALAXY_SERVER_LIST'] = ','.join([server.get('id', 'unnamed') for server in galaxy_servers]) return env def _build_scm_url_extra_vars(self, project_update): diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index 1a1dbed73e..8d8ba9f008 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -622,13 +622,22 @@ AWX_ROLES_ENABLED = True # Note: This setting may be overridden by database settings. AWX_COLLECTIONS_ENABLED = True -# Settings for private galaxy server, should be set in the UI +# Settings for primary galaxy server, should be set in the UI PRIMARY_GALAXY_URL = '' PRIMARY_GALAXY_USERNAME = '' PRIMARY_GALAXY_TOKEN = '' PRIMARY_GALAXY_PASSWORD = '' -# Public Galaxy URL, not configurable outside of file-based settings -PUBLIC_GALAXY_URL = 'https://galaxy.ansible.com' +PRIMARY_GALAXY_AUTH_URL = '' +# Settings for the fallback galaxy server(s), normally this is the +# actual Ansible Galaxy site. +# server options: 'id', 'url', 'username', 'password', 'token', 'auth_url' +# To not use any fallback servers set this to [] +FALLBACK_GALAXY_SERVERS = [ + { + 'id': 'galaxy', + 'url': 'https://galaxy.ansible.com' + } +] # Enable bubblewrap support for running jobs (playbook runs only). # Note: This setting may be overridden by database settings. diff --git a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js index 027afe9f4d..445b0864a2 100644 --- a/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js +++ b/awx/ui/client/src/configuration/forms/jobs-form/configuration-jobs.form.js @@ -85,6 +85,10 @@ export default ['i18n', function(i18n) { hasShowInputButton: true, reset: 'PRIMARY_GALAXY_TOKEN', }, + PRIMARY_GALAXY_AUTH_URL: { + type: 'text', + reset: 'PRIMARY_GALAXY_AUTH_URL', + }, AWX_TASK_ENV: { type: 'textarea', reset: 'AWX_TASK_ENV',