ansible-galaxy - fix turning off the ConcreteArtifactManager's validate certs at the global level (#79561) (#79696)

Fix ignoring certs when downloading tarballs

Fix ignoring certs when downloading a collection from a specific source that isn't in the configured servers list

(cherry picked from commit acbf4cc60e)
pull/79770/head
Sloane Hertel 2 years ago committed by GitHub
parent c297ee9b5d
commit c83669a83e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
bugfixes:
- Fix using ``GALAXY_IGNORE_CERTS`` when downloading tarballs from Galaxy servers (https://github.com/ansible/ansible/issues/79557).
- Fix using ``GALAXY_IGNORE_CERTS`` in conjunction with collections in requirements files which specify a specific ``source`` that isn't in the configured servers.

@ -79,15 +79,11 @@ SERVER_DEF = [
# config definition fields # config definition fields
SERVER_ADDITIONAL = { SERVER_ADDITIONAL = {
'v3': {'default': 'False'}, 'v3': {'default': 'False'},
'validate_certs': {'default': True, 'cli': [{'name': 'validate_certs'}]}, 'validate_certs': {'cli': [{'name': 'validate_certs'}]},
'timeout': {'default': '60', 'cli': [{'name': 'timeout'}]}, 'timeout': {'default': '60', 'cli': [{'name': 'timeout'}]},
'token': {'default': None}, 'token': {'default': None},
} }
# override default if the generic is set
if C.GALAXY_IGNORE_CERTS is not None:
SERVER_ADDITIONAL['validate_certs'].update({'default': not C.GALAXY_IGNORE_CERTS})
def with_collection_artifacts_manager(wrapped_method): def with_collection_artifacts_manager(wrapped_method):
"""Inject an artifacts manager if not passed explicitly. """Inject an artifacts manager if not passed explicitly.
@ -100,7 +96,8 @@ def with_collection_artifacts_manager(wrapped_method):
if 'artifacts_manager' in kwargs: if 'artifacts_manager' in kwargs:
return wrapped_method(*args, **kwargs) return wrapped_method(*args, **kwargs)
artifacts_manager_kwargs = {'validate_certs': context.CLIARGS['validate_certs']} # FIXME: use validate_certs context from Galaxy servers when downloading collections
artifacts_manager_kwargs = {'validate_certs': context.CLIARGS['resolved_validate_certs']}
keyring = context.CLIARGS.get('keyring', None) keyring = context.CLIARGS.get('keyring', None)
if keyring is not None: if keyring is not None:
@ -588,6 +585,8 @@ class GalaxyCLI(CLI):
# ensure we have 'usable' cli option # ensure we have 'usable' cli option
setattr(options, 'validate_certs', (None if options.ignore_certs is None else not options.ignore_certs)) setattr(options, 'validate_certs', (None if options.ignore_certs is None else not options.ignore_certs))
# the default if validate_certs is None
setattr(options, 'resolved_validate_certs', (options.validate_certs if options.validate_certs is not None else not C.GALAXY_IGNORE_CERTS))
display.verbosity = options.verbosity display.verbosity = options.verbosity
return options return options
@ -645,6 +644,8 @@ class GalaxyCLI(CLI):
token_val = server_options['token'] or NoTokenSentinel token_val = server_options['token'] or NoTokenSentinel
username = server_options['username'] username = server_options['username']
v3 = server_options.pop('v3') v3 = server_options.pop('v3')
if server_options['validate_certs'] is None:
server_options['validate_certs'] = context.CLIARGS['resolved_validate_certs']
validate_certs = server_options['validate_certs'] validate_certs = server_options['validate_certs']
if v3: if v3:
@ -680,9 +681,7 @@ class GalaxyCLI(CLI):
cmd_server = context.CLIARGS['api_server'] cmd_server = context.CLIARGS['api_server']
cmd_token = GalaxyToken(token=context.CLIARGS['api_key']) cmd_token = GalaxyToken(token=context.CLIARGS['api_key'])
# resolve validate_certs validate_certs = context.CLIARGS['resolved_validate_certs']
v_config_default = True if C.GALAXY_IGNORE_CERTS is None else not C.GALAXY_IGNORE_CERTS
validate_certs = v_config_default if context.CLIARGS['validate_certs'] is None else context.CLIARGS['validate_certs']
if cmd_server: if cmd_server:
# Cmd args take precedence over the config entry but fist check if the arg was a name and use that config # Cmd args take precedence over the config entry but fist check if the arg was a name and use that config
# entry, otherwise create a new API entry for the server specified. # entry, otherwise create a new API entry for the server specified.
@ -848,7 +847,7 @@ class GalaxyCLI(CLI):
name=coll_req['name'], name=coll_req['name'],
), ),
coll_req['source'], coll_req['source'],
validate_certs=not context.CLIARGS['ignore_certs'], validate_certs=context.CLIARGS['resolved_validate_certs'],
), ),
) )

@ -201,24 +201,6 @@ def manifest(manifest_info):
yield fake_file, sha256(b_data).hexdigest() 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, t 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( @pytest.mark.parametrize(
'required_signature_count,valid', 'required_signature_count,valid',
[ [
@ -340,8 +322,18 @@ def test_validate_certs(global_ignore_certs, monkeypatch):
assert galaxy_cli.api_servers[0].validate_certs is not global_ignore_certs assert galaxy_cli.api_servers[0].validate_certs is not global_ignore_certs
@pytest.mark.parametrize('global_ignore_certs', [True, False]) @pytest.mark.parametrize(
def test_validate_certs_with_server_url(global_ignore_certs, monkeypatch): ["ignore_certs_cli", "ignore_certs_cfg", "expected_validate_certs"],
[
(None, None, True),
(None, True, False),
(None, False, True),
(True, None, False),
(True, True, False),
(True, False, False),
]
)
def test_validate_certs_with_server_url(ignore_certs_cli, ignore_certs_cfg, expected_validate_certs, monkeypatch):
cli_args = [ cli_args = [
'ansible-galaxy', 'ansible-galaxy',
'collection', 'collection',
@ -350,8 +342,10 @@ def test_validate_certs_with_server_url(global_ignore_certs, monkeypatch):
'-s', '-s',
'https://galaxy.ansible.com' 'https://galaxy.ansible.com'
] ]
if global_ignore_certs: if ignore_certs_cli:
cli_args.append('--ignore-certs') cli_args.append('--ignore-certs')
if ignore_certs_cfg is not None:
monkeypatch.setattr(C, 'GALAXY_IGNORE_CERTS', ignore_certs_cfg)
galaxy_cli = GalaxyCLI(args=cli_args) galaxy_cli = GalaxyCLI(args=cli_args)
mock_execute_install = MagicMock() mock_execute_install = MagicMock()
@ -359,34 +353,62 @@ def test_validate_certs_with_server_url(global_ignore_certs, monkeypatch):
galaxy_cli.run() galaxy_cli.run()
assert len(galaxy_cli.api_servers) == 1 assert len(galaxy_cli.api_servers) == 1
assert galaxy_cli.api_servers[0].validate_certs is not global_ignore_certs assert galaxy_cli.api_servers[0].validate_certs == expected_validate_certs
@pytest.mark.parametrize('global_ignore_certs', [True, False]) @pytest.mark.parametrize(
def test_validate_certs_with_server_config(global_ignore_certs, server_config, monkeypatch): ["ignore_certs_cli", "ignore_certs_cfg", "expected_server2_validate_certs", "expected_server3_validate_certs"],
[
# test sidesteps real resolution and forces the server config to override the cli option (None, None, True, True),
get_plugin_options = MagicMock(side_effect=server_config) (None, True, True, False),
monkeypatch.setattr(C.config, 'get_plugin_options', get_plugin_options) (None, False, True, True),
(True, None, False, False),
(True, True, False, False),
(True, False, False, False),
]
)
def test_validate_certs_server_config(ignore_certs_cfg, ignore_certs_cli, expected_server2_validate_certs, expected_server3_validate_certs, monkeypatch):
server_names = ['server1', 'server2', 'server3']
cfg_lines = [
"[galaxy]",
"server_list=server1,server2,server3",
"[galaxy_server.server1]",
"url=https://galaxy.ansible.com/api/",
"validate_certs=False",
"[galaxy_server.server2]",
"url=https://galaxy.ansible.com/api/",
"validate_certs=True",
"[galaxy_server.server3]",
"url=https://galaxy.ansible.com/api/",
]
cli_args = [ cli_args = [
'ansible-galaxy', 'ansible-galaxy',
'collection', 'collection',
'install', 'install',
'namespace.collection:1.0.0', 'namespace.collection:1.0.0',
] ]
if global_ignore_certs: if ignore_certs_cli:
cli_args.append('--ignore-certs') cli_args.append('--ignore-certs')
if ignore_certs_cfg is not None:
monkeypatch.setattr(C, 'GALAXY_IGNORE_CERTS', ignore_certs_cfg)
monkeypatch.setattr(C, 'GALAXY_SERVER_LIST', server_names)
with tempfile.NamedTemporaryFile(suffix='.cfg') as tmp_file:
tmp_file.write(to_bytes('\n'.join(cfg_lines), errors='surrogate_or_strict'))
tmp_file.flush()
monkeypatch.setattr(C.config, '_config_file', tmp_file.name)
C.config._parse_config_file()
galaxy_cli = GalaxyCLI(args=cli_args) galaxy_cli = GalaxyCLI(args=cli_args)
mock_execute_install = MagicMock() mock_execute_install = MagicMock()
monkeypatch.setattr(galaxy_cli, '_execute_install_collection', mock_execute_install) monkeypatch.setattr(galaxy_cli, '_execute_install_collection', mock_execute_install)
galaxy_cli.run() galaxy_cli.run()
# server cfg, so should match def above, if not specified so it should use default (true) # (not) --ignore-certs > server's validate_certs > (not) GALAXY_IGNORE_CERTS > True
assert galaxy_cli.api_servers[0].validate_certs is server_config[0].get('validate_certs', True) assert galaxy_cli.api_servers[0].validate_certs is False
assert galaxy_cli.api_servers[1].validate_certs is server_config[1].get('validate_certs', True) assert galaxy_cli.api_servers[1].validate_certs is expected_server2_validate_certs
assert galaxy_cli.api_servers[2].validate_certs is server_config[2].get('validate_certs', True) assert galaxy_cli.api_servers[2].validate_certs is expected_server3_validate_certs
def test_build_collection_no_galaxy_yaml(): def test_build_collection_no_galaxy_yaml():

Loading…
Cancel
Save