mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-05 07:51:51 -05:00
redact survey password type values w/ tests
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import hmac
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
|
||||
# Django
|
||||
from django.conf import settings
|
||||
@@ -23,6 +24,7 @@ from awx.main.models.base import * # noqa
|
||||
from awx.main.models.unified_jobs import * # noqa
|
||||
from awx.main.utils import decrypt_field, ignore_inventory_computed_fields
|
||||
from awx.main.utils import emit_websocket_notification
|
||||
from awx.main.redact import PlainTextCleaner
|
||||
|
||||
logger = logging.getLogger('awx.main.models.jobs')
|
||||
|
||||
@@ -220,7 +222,7 @@ class JobTemplate(UnifiedJobTemplate, JobOptions):
|
||||
if survey_element['variable'] not in data and \
|
||||
survey_element['required']:
|
||||
errors.append("'%s' value missing" % survey_element['variable'])
|
||||
elif survey_element['type'] in ["textarea", "text"]:
|
||||
elif survey_element['type'] in ["textarea", "text", "password"]:
|
||||
if survey_element['variable'] in data:
|
||||
if 'min' in survey_element and survey_element['min'] not in ["", None] and len(data[survey_element['variable']]) < survey_element['min']:
|
||||
errors.append("'%s' value %s is too small (must be at least %s)" %
|
||||
@@ -452,6 +454,31 @@ class Job(UnifiedJob, JobOptions):
|
||||
evars.update(extra_vars)
|
||||
self.update_fields(extra_vars=json.dumps(evars))
|
||||
|
||||
def _survey_search_and_replace(self, content):
|
||||
# Use job template survey spec to identify password fields.
|
||||
# Then lookup password fields in extra_vars and save the values
|
||||
jt = self.job_template
|
||||
if jt and jt.survey_enabled and 'spec' in jt.survey_spec:
|
||||
vars = []
|
||||
# Get variables that are type password
|
||||
for survey_element in jt.survey_spec['spec']:
|
||||
if survey_element['type'] == 'password':
|
||||
vars.append(survey_element['variable'])
|
||||
|
||||
# Use password vars to find in extra_vars
|
||||
for key in vars:
|
||||
if key in self.extra_vars_dict:
|
||||
content = PlainTextCleaner.remove_sensitive(content, self.extra_vars_dict[key])
|
||||
return content
|
||||
|
||||
def _result_stdout_raw_limited(self, *args, **kwargs):
|
||||
buff, start, end, abs_end = super(Job, self)._result_stdout_raw_limited(*args, **kwargs)
|
||||
return self._survey_search_and_replace(buff), start, end, abs_end
|
||||
|
||||
def _result_stdout_raw(self, *args, **kwargs):
|
||||
content = super(Job, self)._result_stdout_raw(*args, **kwargs)
|
||||
return self._survey_search_and_replace(content)
|
||||
|
||||
def copy(self):
|
||||
presets = {}
|
||||
for kw in self.job_template._get_unified_job_field_names():
|
||||
|
||||
@@ -625,16 +625,27 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
||||
else:
|
||||
return StringIO("stdout capture is missing")
|
||||
|
||||
def _escape_ascii(self, content):
|
||||
ansi_escape = re.compile(r'\x1b[^m]*m')
|
||||
return ansi_escape.sub('', content)
|
||||
|
||||
def _result_stdout_raw(self, redact_sensitive=True, escape_ascii=False):
|
||||
content = self.result_stdout_raw_handle().read()
|
||||
if redact_sensitive:
|
||||
content = UriCleaner.remove_sensitive(content)
|
||||
if escape_ascii:
|
||||
content = self._escape_ascii(content)
|
||||
return content
|
||||
|
||||
@property
|
||||
def result_stdout_raw(self):
|
||||
return self.result_stdout_raw_handle().read()
|
||||
return self._result_stdout_raw()
|
||||
|
||||
@property
|
||||
def result_stdout(self):
|
||||
ansi_escape = re.compile(r'\x1b[^m]*m')
|
||||
return ansi_escape.sub('', UriCleaner.remove_sensitive(self.result_stdout_raw))
|
||||
return self._result_stdout_raw(escape_ascii=True)
|
||||
|
||||
def result_stdout_raw_limited(self, start_line=0, end_line=None):
|
||||
def _result_stdout_raw_limited(self, start_line=0, end_line=None, redact_sensitive=True, escape_ascii=False):
|
||||
return_buffer = u""
|
||||
if end_line is not None:
|
||||
end_line = int(end_line)
|
||||
@@ -651,12 +662,19 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
||||
end_actual = min(int(end_line), len(stdout_lines))
|
||||
else:
|
||||
end_actual = len(stdout_lines)
|
||||
|
||||
if redact_sensitive:
|
||||
return_buffer = UriCleaner.remove_sensitive(return_buffer)
|
||||
if escape_ascii:
|
||||
return_buffer = self._escape_ascii(return_buffer)
|
||||
|
||||
return return_buffer, start_actual, end_actual, absolute_end
|
||||
|
||||
def result_stdout_raw_limited(self, start_line=0, end_line=None):
|
||||
return self._result_stdout_raw_limited(start_line, end_line)
|
||||
|
||||
def result_stdout_limited(self, start_line=0, end_line=None):
|
||||
ansi_escape = re.compile(r'\x1b[^m]*m')
|
||||
content, start, end, absolute_end = UriCleaner.remove_sensitive(self.result_stdout_raw_limited(start_line, end_line))
|
||||
return ansi_escape.sub('', content), start, end, absolute_end
|
||||
return self._result_stdout_raw_limited(start_line, end_line, escape_ascii=True)
|
||||
|
||||
@property
|
||||
def celery_task(self):
|
||||
@@ -729,9 +747,6 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
||||
|
||||
def signal_start(self, **kwargs):
|
||||
"""Notify the task runner system to begin work on this task."""
|
||||
# Sanity check: If we are running unit tests, then run synchronously.
|
||||
if getattr(settings, 'CELERY_UNIT_TEST', False):
|
||||
return self.start(None, **kwargs)
|
||||
|
||||
# Sanity check: Are we able to start the job? If not, do not attempt
|
||||
# to do so.
|
||||
@@ -747,6 +762,10 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
|
||||
if 'extra_vars' in kwargs:
|
||||
self.handle_extra_data(kwargs['extra_vars'])
|
||||
|
||||
# Sanity check: If we are running unit tests, then run synchronously.
|
||||
if getattr(settings, 'CELERY_UNIT_TEST', False):
|
||||
return self.start(None, **kwargs)
|
||||
|
||||
# Save the pending status, and inform the SocketIO listener.
|
||||
self.update_fields(start_args=json.dumps(kwargs), status='pending')
|
||||
self.socketio_emit_status("pending")
|
||||
|
||||
Reference in New Issue
Block a user