diff options
author | Ryan Petrello <rpetrell@redhat.com> | 2018-01-15 17:38:02 +0100 |
---|---|---|
committer | Ryan Petrello <rpetrell@redhat.com> | 2018-01-15 17:45:49 +0100 |
commit | e1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a (patch) | |
tree | f3ce9019b0e64c726842f7696cca3fb4641781ae | |
parent | replace our memcached-based fact cache implementation with local files (diff) | |
download | awx-e1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a.tar.xz awx-e1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a.zip |
only allow facts to cache in the proper file system location
-rw-r--r-- | awx/main/models/jobs.py | 6 | ||||
-rw-r--r-- | awx/main/tests/unit/models/test_jobs.py | 11 |
2 files changed, 17 insertions, 0 deletions
diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 4f5e549e04..07afd288ce 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -731,6 +731,9 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana hosts = hosts.filter(ansible_facts_modified__gte=timeout) for host in hosts: filepath = os.sep.join(map(six.text_type, [destination, host.name])) + if not os.path.realpath(filepath).startswith(destination): + system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) + continue with codecs.open(filepath, 'w', encoding='utf-8') as f: os.chmod(f.name, 0600) json.dump(host.ansible_facts, f) @@ -741,6 +744,9 @@ class Job(UnifiedJob, JobOptions, SurveyJobMixin, JobNotificationMixin, TaskMana destination = os.path.join(destination, 'facts') for host in self._get_inventory_hosts(): filepath = os.sep.join(map(six.text_type, [destination, host.name])) + if not os.path.realpath(filepath).startswith(destination): + system_tracking_logger.error('facts for host {} could not be cached'.format(smart_str(host.name))) + continue if os.path.exists(filepath): # If the file changed since we wrote it pre-playbook run... modified = os.path.getmtime(filepath) diff --git a/awx/main/tests/unit/models/test_jobs.py b/awx/main/tests/unit/models/test_jobs.py index f8949a0333..516a6f076f 100644 --- a/awx/main/tests/unit/models/test_jobs.py +++ b/awx/main/tests/unit/models/test_jobs.py @@ -47,6 +47,17 @@ def test_start_job_fact_cache(hosts, job, inventory, tmpdir): assert filepath in modified_times +def test_fact_cache_with_invalid_path_traversal(job, inventory, tmpdir, mocker): + job._get_inventory_hosts = mocker.Mock(return_value=[ + Host(name='../foo', ansible_facts={"a": 1, "b": 2},), + ]) + + fact_cache = str(tmpdir) + job.start_job_fact_cache(fact_cache, {}, 0) + # a file called "foo" should _not_ be written outside the facts dir + assert os.listdir(os.path.join(fact_cache, 'facts', '..')) == ['facts'] + + def test_finish_job_fact_cache_with_existing_data(job, hosts, inventory, mocker, tmpdir): fact_cache = str(tmpdir) modified_times = {} |