From 802f722e953aaba2e95bf102836d1d5d8a1923db Mon Sep 17 00:00:00 2001 From: Chris Meyers Date: Wed, 19 Jul 2017 11:30:00 -0400 Subject: [PATCH] do not accept array as extra_vars related to #5645 * Since we pass extra_vars to ansible as -e; we require that the top most data-structure be a key-value. NOT an array. --- .../tests/functional/api/test_job_template.py | 2 +- awx/main/tests/unit/test_validators.py | 32 +++++++++++++++++++ awx/main/validators.py | 12 +++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/awx/main/tests/functional/api/test_job_template.py b/awx/main/tests/functional/api/test_job_template.py index 3ef9775c13..e3898b2900 100644 --- a/awx/main/tests/functional/api/test_job_template.py +++ b/awx/main/tests/functional/api/test_job_template.py @@ -376,7 +376,7 @@ def test_edit_nonsenstive(patch, job_template_factory, alice): 'forks': 14, 'limit': 'something', 'verbosity': 5, - 'extra_vars': '--', + 'extra_vars': '---', 'job_tags': 'sometags', 'force_handlers': True, 'skip_tags': 'thistag,thattag', diff --git a/awx/main/tests/unit/test_validators.py b/awx/main/tests/unit/test_validators.py index ea47785ed0..bf08f6a0d5 100644 --- a/awx/main/tests/unit/test_validators.py +++ b/awx/main/tests/unit/test_validators.py @@ -3,6 +3,7 @@ from awx.main.validators import ( validate_private_key, validate_certificate, validate_ssh_private_key, + vars_validate_or_raise, ) from awx.main.tests.data.ssh import ( TEST_SSH_RSA1_KEY_DATA, @@ -12,6 +13,7 @@ from awx.main.tests.data.ssh import ( TEST_OPENSSH_KEY_DATA_LOCKED, TEST_SSH_CERT_KEY, ) +from rest_framework.serializers import ValidationError as RestValidationError import pytest @@ -96,3 +98,33 @@ def test_cert_with_key(): assert pem_objects[0]['type'] == 'CERTIFICATE' assert pem_objects[1]['key_type'] == 'rsa' assert not pem_objects[1]['key_enc'] + + +@pytest.mark.parametrize("var_str", [ + '{"a": "b"}', + '---\na: b\nc: d', + '', + '""', +]) +def test_valid_vars(var_str): + vars_validate_or_raise(var_str) + + +@pytest.mark.parametrize("var_str", [ + '["a": "b"]', + '["a", "b"]', + "('a=4', 'c=5')", + '"', + "''", + "5", + "6.74", + "hello", + "OrderedDict([('a', 'b')])", + "True", + "False", +]) +def test_invalid_vars(var_str): + with pytest.raises(RestValidationError): + vars_validate_or_raise(var_str) + + diff --git a/awx/main/validators.py b/awx/main/validators.py index 2acd970c15..e5b1568464 100644 --- a/awx/main/validators.py +++ b/awx/main/validators.py @@ -179,15 +179,21 @@ def vars_validate_or_raise(vars_str): job templates, inventories, or hosts are either an acceptable blank string, or are valid JSON or YAML dict """ - try: - json.loads((vars_str or '').strip() or '{}') + if isinstance(vars_str, dict) or (isinstance(vars_str, basestring) and vars_str == '""'): return vars_str + + try: + r = json.loads((vars_str or '').strip() or '{}') + if isinstance(r, dict): + return vars_str except ValueError: pass try: r = yaml.safe_load(vars_str) - if not (isinstance(r, basestring) and r.startswith('OrderedDict(')): + # Can be None if '---' + if isinstance(r, dict) or r is None: return vars_str except yaml.YAMLError: pass raise RestValidationError(_('Must be valid JSON or YAML.')) +