summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Petrello <rpetrell@redhat.com>2018-01-15 17:38:02 +0100
committerRyan Petrello <rpetrell@redhat.com>2018-01-15 17:45:49 +0100
commite1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a (patch)
treef3ce9019b0e64c726842f7696cca3fb4641781ae
parentreplace our memcached-based fact cache implementation with local files (diff)
downloadawx-e1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a.tar.xz
awx-e1d50a43fd90983bbb385b5d7ad8aa8a9c63b29a.zip
only allow facts to cache in the proper file system location
-rw-r--r--awx/main/models/jobs.py6
-rw-r--r--awx/main/tests/unit/models/test_jobs.py11
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 = {}