From 72ba2bdc82944f904245a044a9c917a3bfad4c78 Mon Sep 17 00:00:00 2001 From: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> Date: Thu, 16 Sep 2021 13:54:52 -0400 Subject: [PATCH] ansible-galaxy - add a per-server validate_certs option (#75710) * Add a validate_certs option to galaxy server configuration * Add a unit test for cert validation * changelog --- .../75710-ansible-galaxy-validate-certs.yml | 2 + lib/ansible/cli/galaxy.py | 22 ++++++--- test/units/galaxy/test_collection.py | 45 ++++++++++++++++++- 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 changelogs/fragments/75710-ansible-galaxy-validate-certs.yml diff --git a/changelogs/fragments/75710-ansible-galaxy-validate-certs.yml b/changelogs/fragments/75710-ansible-galaxy-validate-certs.yml new file mode 100644 index 00000000000..d0458ad954f --- /dev/null +++ b/changelogs/fragments/75710-ansible-galaxy-validate-certs.yml @@ -0,0 +1,2 @@ +minor_changes: + - ansible-galaxy - Allow validate_certs to be configured for individual Galaxy servers (https://github.com/ansible/ansible/issues/75677). diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py index 3a24c0dbfa9..e57db6e7966 100644 --- a/lib/ansible/cli/galaxy.py +++ b/lib/ansible/cli/galaxy.py @@ -55,6 +55,16 @@ from ansible.utils.plugin_docs import get_versioned_doclink display = Display() urlparse = six.moves.urllib.parse.urlparse +SERVER_DEF = [ + ('url', True), + ('username', False), + ('password', False), + ('token', False), + ('auth_url', False), + ('v3', False), + ('validate_certs', False) +] + def with_collection_artifacts_manager(wrapped_method): """Inject an artifacts manager if not passed explicitly. @@ -466,11 +476,9 @@ class GalaxyCLI(CLI): ], 'required': required, } - server_def = [('url', True), ('username', False), ('password', False), ('token', False), - ('auth_url', False), ('v3', False)] - validate_certs = not context.CLIARGS['ignore_certs'] - galaxy_options = {'validate_certs': validate_certs} + validate_certs_fallback = not context.CLIARGS['ignore_certs'] + galaxy_options = {} for optional_key in ['clear_response_cache', 'no_cache']: if optional_key in context.CLIARGS: galaxy_options[optional_key] = context.CLIARGS[optional_key] @@ -482,7 +490,7 @@ class GalaxyCLI(CLI): for server_priority, server_key in enumerate(server_list, start=1): # Config definitions are looked up dynamically based on the C.GALAXY_SERVER_LIST entry. We look up the # section [galaxy_server.] for the values url, username, password, and token. - config_dict = dict((k, server_config_def(server_key, k, req)) for k, req in server_def) + config_dict = dict((k, server_config_def(server_key, k, req)) for k, req in SERVER_DEF) defs = AnsibleLoader(yaml_dump(config_dict)).get_single_data() C.config.initialize_plugin_configuration_definitions('galaxy_server', server_key, defs) @@ -494,6 +502,10 @@ class GalaxyCLI(CLI): username = server_options['username'] available_api_versions = None v3 = server_options.pop('v3', None) + validate_certs = server_options['validate_certs'] + if validate_certs is None: + validate_certs = validate_certs_fallback + server_options['validate_certs'] = validate_certs if v3: # This allows a user to explicitly indicate the server uses the /v3 API # This was added for testing against pulp_ansible and I'm not sure it has diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py index 8575a55c17f..3de2e89a0a2 100644 --- a/test/units/galaxy/test_collection.py +++ b/test/units/galaxy/test_collection.py @@ -17,8 +17,9 @@ from hashlib import sha256 from io import BytesIO from units.compat.mock import MagicMock, mock_open, patch +import ansible.constants as C from ansible import context -from ansible.cli.galaxy import GalaxyCLI +from ansible.cli.galaxy import GalaxyCLI, SERVER_DEF from ansible.errors import AnsibleError from ansible.galaxy import api, collection, token from ansible.module_utils._text import to_bytes, to_native, to_text @@ -198,6 +199,48 @@ def manifest(manifest_info): yield fake_file, sha256(b_data).hexdigest() +@pytest.fixture() +def server_config(monkeypatch): + monkeypatch.setattr(C, 'GALAXY_SERVER_LIST', ['server1', 'server2', 'server3']) + + default_options = dict((k, None) for k, v in SERVER_DEF) + + server1 = dict(default_options) + server1.update({'url': 'https://galaxy.ansible.com/api/', 'validate_certs': False}) + + server2 = dict(default_options) + server2.update({'url': 'https://galaxy.ansible.com/api/', 'validate_certs': True}) + + server3 = dict(default_options) + server3.update({'url': 'https://galaxy.ansible.com/api/'}) + + return server1, server2, server3 + + +@pytest.mark.parametrize('global_ignore_certs', [True, False]) +def test_validate_certs(global_ignore_certs, server_config, monkeypatch): + get_plugin_options = MagicMock(side_effect=server_config) + monkeypatch.setattr(C.config, 'get_plugin_options', get_plugin_options) + + cli_args = [ + 'ansible-galaxy', + 'collection', + 'install', + 'namespace.collection:1.0.0', + ] + if global_ignore_certs: + cli_args.append('--ignore-certs') + + galaxy_cli = GalaxyCLI(args=cli_args) + mock_execute_install = MagicMock() + monkeypatch.setattr(galaxy_cli, '_execute_install_collection', mock_execute_install) + galaxy_cli.run() + + assert galaxy_cli.api_servers[0].validate_certs is False + assert galaxy_cli.api_servers[1].validate_certs is True + assert galaxy_cli.api_servers[2].validate_certs is not global_ignore_certs + + def test_build_collection_no_galaxy_yaml(): fake_path = u'/fake/ÅÑŚÌβŁÈ/path' expected = to_native("The collection galaxy.yml path '%s/galaxy.yml' does not exist." % fake_path)