From 09f4c9fbbe127c97da63828c49840dd7a95fa9ce Mon Sep 17 00:00:00 2001 From: Matthew Jones Date: Mon, 31 Aug 2015 16:24:38 -0400 Subject: [PATCH] Fixed job redaction for projects and unit tests --- awx/main/models/projects.py | 10 ++++-- awx/main/models/unified_jobs.py | 2 +- awx/main/tests/base.py | 9 ++++-- awx/main/tests/views.py | 54 ++++++++++++++++++++++++++------- 4 files changed, 57 insertions(+), 18 deletions(-) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 289c40cf79..b90e29cd85 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -357,11 +357,15 @@ class ProjectUpdate(UnifiedJob, ProjectOptions): def result_stdout(self): return self._result_stdout_raw(redact_sensitive=True, escape_ascii=True) - def result_stdout_raw_limited(self, start_line=0, redact_sensitive=True, end_line=None): - return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive) + @property + def result_stdout_raw(self): + return self._result_stdout_raw(redact_sensitive=True) + + def result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=True): + return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive=redact_sensitive) def result_stdout_limited(self, start_line=0, end_line=None, redact_sensitive=True): - return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive, escape_ascii=True) + return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive=redact_sensitive, escape_ascii=True) def get_absolute_url(self): return reverse('api:project_update_detail', args=(self.pk,)) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 0471079656..ade655c47f 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -670,7 +670,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique return return_buffer, start_actual, end_actual, absolute_end - def result_stdout_raw_limited(self, start_line=0, redact_sensitive=False, end_line=None): + def result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=False): return self._result_stdout_raw_limited(start_line, end_line, redact_sensitive) def result_stdout_limited(self, start_line=0, end_line=None, redact_sensitive=False): diff --git a/awx/main/tests/base.py b/awx/main/tests/base.py index 84bbb8082d..90209bffb6 100644 --- a/awx/main/tests/base.py +++ b/awx/main/tests/base.py @@ -623,7 +623,7 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin): msg += '"%s" found in: "%s"' % (substr, string) self.assertEqual(count, 0, msg) - def check_found(self, string, substr, count, description=None, word_boundary=False): + def check_found(self, string, substr, count=-1, description=None, word_boundary=False): if word_boundary: count_actual = len(re.findall(r'\b%s\b' % re.escape(substr), string)) else: @@ -632,8 +632,11 @@ class BaseTestMixin(QueueTestMixin, MockCommonlySlowTestMixin): msg = '' if description: msg = 'Test "%s".\n' % description - msg += 'Found %d occurances of "%s" instead of %d in: "%s"' % (count_actual, substr, count, string) - self.assertEqual(count_actual, count, msg) + if count == -1: + self.assertTrue(count_actual > 0) + else: + msg += 'Found %d occurances of "%s" instead of %d in: "%s"' % (count_actual, substr, count, string) + self.assertEqual(count_actual, count, msg) def check_job_result(self, job, expected='successful', expect_stdout=True, expect_traceback=False): diff --git a/awx/main/tests/views.py b/awx/main/tests/views.py index 629b1e1fbc..691dacd0e2 100644 --- a/awx/main/tests/views.py +++ b/awx/main/tests/views.py @@ -4,6 +4,7 @@ from django.core.urlresolvers import reverse # Reuse Test code from awx.main.tests.base import BaseLiveServerTest, QueueStartStopTestMixin from awx.main.tests.base import URI +from awx.main.models.projects import * __all__ = ['UnifiedJobStdoutRedactedTests'] @@ -32,12 +33,20 @@ class UnifiedJobStdoutRedactedTests(BaseLiveServerTest, QueueStartStopTestMixin) self.setup_instances() self.setup_users() self.test_cases = [] + self.negative_test_cases = [] + + proj = self.make_project() for e in TEST_STDOUTS: - e['job'] = self.make_job() - e['job'].result_stdout_text = e['text'] - e['job'].save() + e['project'] = ProjectUpdate(project=proj) + e['project'].result_stdout_text = e['text'] + e['project'].save() self.test_cases.append(e) + for d in TEST_STDOUTS: + d['job'] = self.make_job() + d['job'].result_stdout_text = d['text'] + d['job'].save() + self.negative_test_cases.append(d) # This is more of a functional test than a unit test. # should filter out username and password @@ -49,7 +58,13 @@ class UnifiedJobStdoutRedactedTests(BaseLiveServerTest, QueueStartStopTestMixin) # Ensure the host didn't get redacted self.check_found(response['content'], uri.host, test_data['occurrences'], test_data['description']) - def _get_url_job_stdout(self, job, format='json'): + def check_sensitive_not_redacted(self, test_data, response): + uri = test_data['uri'] + self.assertIsNotNone(response['content']) + self.check_found(response['content'], uri.username, description=test_data['description']) + self.check_found(response['content'], uri.password, description=test_data['description']) + + def _get_url_job_stdout(self, job, url_base, format='json'): formats = { 'json': 'application/json', 'ansi': 'text/plain', @@ -57,22 +72,39 @@ class UnifiedJobStdoutRedactedTests(BaseLiveServerTest, QueueStartStopTestMixin) 'html': 'text/html', } content_type = formats[format] - job_stdout_url = reverse('api:job_stdout', args=(job.pk,)) + "?format=" + format - return self.get(job_stdout_url, expect=200, auth=self.get_super_credentials(), accept=content_type) + project_update_stdout_url = reverse(url_base, args=(job.pk,)) + "?format=" + format + return self.get(project_update_stdout_url, expect=200, auth=self.get_super_credentials(), accept=content_type) def _test_redaction_enabled(self, format): for test_data in self.test_cases: - response = self._get_url_job_stdout(test_data['job'], format=format) + response = self._get_url_job_stdout(test_data['project'], "api:project_update_stdout", format=format) self.check_sensitive_redacted(test_data, response) - def test_redaction_enabled_json(self): + def _test_redaction_disabled(self, format): + for test_data in self.negative_test_cases: + response = self._get_url_job_stdout(test_data['job'], "api:job_stdout", format=format) + self.check_sensitive_not_redacted(test_data, response) + + def test_project_update_redaction_enabled_json(self): self._test_redaction_enabled('json') - def test_redaction_enabled_ansi(self): + def test_project_update_redaction_enabled_ansi(self): self._test_redaction_enabled('ansi') - def test_redaction_enabled_html(self): + def test_project_update_redaction_enabled_html(self): self._test_redaction_enabled('html') - def test_redaction_enabled_txt(self): + def test_project_update_redaction_enabled_txt(self): self._test_redaction_enabled('txt') + + def test_job_redaction_disabled_json(self): + self._test_redaction_disabled('json') + + def test_job_redaction_disabled_ansi(self): + self._test_redaction_disabled('ansi') + + def test_job_redaction_disabled_html(self): + self._test_redaction_disabled('html') + + def test_job_redaction_disabled_txt(self): + self._test_redaction_disabled('txt')