Skip to content

Commit

Permalink
replace certain terms with more inclusive language
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanpetrello committed Jun 30, 2020
1 parent 5b9c19d commit 78229f5
Show file tree
Hide file tree
Showing 24 changed files with 103 additions and 97 deletions.
4 changes: 2 additions & 2 deletions awx/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class FieldLookupBackend(BaseFilterBackend):

# A list of fields that we know can be filtered on without the possiblity
# of introducing duplicates
NO_DUPLICATES_WHITELIST = (CharField, IntegerField, BooleanField)
NO_DUPLICATES_ALLOW_LIST = (CharField, IntegerField, BooleanField)

def get_fields_from_lookup(self, model, lookup):

Expand Down Expand Up @@ -205,7 +205,7 @@ def value_to_python(self, model, lookup, value):
field_list, new_lookup = self.get_fields_from_lookup(model, lookup)
field = field_list[-1]

needs_distinct = (not all(isinstance(f, self.NO_DUPLICATES_WHITELIST) for f in field_list))
needs_distinct = (not all(isinstance(f, self.NO_DUPLICATES_ALLOW_LIST) for f in field_list))

# Type names are stored without underscores internally, but are presented and
# and serialized over the API containing underscores so we remove `_`
Expand Down
12 changes: 6 additions & 6 deletions awx/api/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ def initialize_request(self, request, *args, **kwargs):
self.queries_before = len(connection.queries)

# If there are any custom headers in REMOTE_HOST_HEADERS, make sure
# they respect the proxy whitelist
# they respect the allowed proxy list
if all([
settings.PROXY_IP_WHITELIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_WHITELIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_WHITELIST
settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_ALLOWED_LIST
]):
for custom_header in settings.REMOTE_HOST_HEADERS:
if custom_header.startswith('HTTP_'):
Expand Down Expand Up @@ -837,7 +837,7 @@ def _get_copy_return_serializer(self, *args, **kwargs):

@staticmethod
def _decrypt_model_field_if_needed(obj, field_name, field_val):
if field_name in getattr(type(obj), 'REENCRYPTION_BLACKLIST_AT_COPY', []):
if field_name in getattr(type(obj), 'REENCRYPTION_BLOCKLIST_AT_COPY', []):
return field_val
if isinstance(obj, Credential) and field_name == 'inputs':
for secret in obj.credential_type.secret_fields:
Expand Down Expand Up @@ -883,7 +883,7 @@ def copy_model_obj(old_parent, new_parent, model, obj, creater, copy_name='', cr
field_val = getattr(obj, field.name)
except AttributeError:
continue
# Adjust copy blacklist fields here.
# Adjust copy blocked fields here.
if field.name in fields_to_discard or field.name in [
'id', 'pk', 'polymorphic_ctype', 'unifiedjobtemplate_ptr', 'created_by', 'modified_by'
] or field.name.endswith('_role'):
Expand Down
2 changes: 1 addition & 1 deletion awx/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1936,7 +1936,7 @@ def get_related(self, obj):
def validate_source_vars(self, value):
ret = vars_validate_or_raise(value)
for env_k in parse_yaml_or_json(value):
if env_k in settings.INV_ENV_VARIABLE_BLACKLIST:
if env_k in settings.INV_ENV_VARIABLE_BLOCKED:
raise serializers.ValidationError(_("`{}` is a prohibited environment variable".format(env_k)))
return ret

Expand Down
19 changes: 19 additions & 0 deletions awx/conf/migrations/0007_v380_rename_more_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from awx.conf.migrations import _rename_setting


def copy_allowed_ips(apps, schema_editor):
_rename_setting.rename_setting(apps, schema_editor, old_key='PROXY_IP_WHITELIST', new_key='PROXY_IP_ALLOWED_LIST')


class Migration(migrations.Migration):

dependencies = [
('conf', '0006_v331_ldap_group_type'),
]

operations = [
migrations.RunPython(copy_allowed_ips),
]
5 changes: 2 additions & 3 deletions awx/main/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -1513,8 +1513,7 @@ def changes_are_non_sensitive(self, obj, data):
thus can be made by a job template administrator which may not have access
to the any inventory, project, or credentials associated with the template.
'''
# We are white listing fields that can
field_whitelist = [
allowed_fields = [
'name', 'description', 'forks', 'limit', 'verbosity', 'extra_vars',
'job_tags', 'force_handlers', 'skip_tags', 'ask_variables_on_launch',
'ask_tags_on_launch', 'ask_job_type_on_launch', 'ask_skip_tags_on_launch',
Expand All @@ -1529,7 +1528,7 @@ def changes_are_non_sensitive(self, obj, data):
if k not in [x.name for x in obj._meta.concrete_fields]:
continue
if hasattr(obj, k) and getattr(obj, k) != v:
if k not in field_whitelist and v != getattr(obj, '%s_id' % k, None) \
if k not in allowed_fields and v != getattr(obj, '%s_id' % k, None) \
and not (hasattr(obj, '%s_id' % k) and getattr(obj, '%s_id' % k) is None and v == ''): # Equate '' to None in the case of foreign keys
return False
return True
Expand Down
8 changes: 4 additions & 4 deletions awx/main/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@
)

register(
'PROXY_IP_WHITELIST',
'PROXY_IP_ALLOWED_LIST',
field_class=fields.StringListField,
label=_('Proxy IP Whitelist'),
label=_('Proxy IP Allowed List'),
help_text=_("If Tower is behind a reverse proxy/load balancer, use this setting "
"to whitelist the proxy IP addresses from which Tower should trust "
"to configure the proxy IP addresses from which Tower should trust "
"custom REMOTE_HOST_HEADERS header values. "
"If this setting is an empty list (the default), the headers specified by "
"REMOTE_HOST_HEADERS will be trusted unconditionally')"),
Expand Down Expand Up @@ -241,7 +241,7 @@ def _load_default_license_from_file():
field_class=fields.StringListField,
required=False,
label=_('Paths to expose to isolated jobs'),
help_text=_('Whitelist of paths that would otherwise be hidden to expose to isolated jobs. Enter one path per line.'),
help_text=_('List of paths that would otherwise be hidden to expose to isolated jobs. Enter one path per line.'),
category=_('Jobs'),
category_slug='jobs',
)
Expand Down
4 changes: 2 additions & 2 deletions awx/main/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
CAN_CANCEL = ('new', 'pending', 'waiting', 'running')
ACTIVE_STATES = CAN_CANCEL
CENSOR_VALUE = '************'
ENV_BLACKLIST = frozenset((
ENV_BLOCKLIST = frozenset((
'VIRTUAL_ENV', 'PATH', 'PYTHONPATH', 'PROOT_TMP_DIR', 'JOB_ID',
'INVENTORY_ID', 'INVENTORY_SOURCE_ID', 'INVENTORY_UPDATE_ID',
'AD_HOC_COMMAND_ID', 'REST_API_URL', 'REST_API_TOKEN', 'MAX_EVENT_RES',
Expand All @@ -41,7 +41,7 @@
))

# loggers that may be called in process of emitting a log
LOGGER_BLACKLIST = (
LOGGER_BLOCKLIST = (
'awx.main.utils.handlers',
'awx.main.utils.formatters',
'awx.main.utils.filters',
Expand Down
6 changes: 3 additions & 3 deletions awx/main/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
batch_role_ancestor_rebuilding, Role,
ROLE_SINGLETON_SYSTEM_ADMINISTRATOR, ROLE_SINGLETON_SYSTEM_AUDITOR
)
from awx.main.constants import ENV_BLACKLIST
from awx.main.constants import ENV_BLOCKLIST
from awx.main import utils


Expand Down Expand Up @@ -870,9 +870,9 @@ def validate_env_var_allowed(self, env_var):
'use is not allowed in credentials.').format(env_var),
code='invalid', params={'value': env_var},
)
if env_var in ENV_BLACKLIST:
if env_var in ENV_BLOCKLIST:
raise django_exceptions.ValidationError(
_('Environment variable {} is blacklisted from use in credentials.').format(env_var),
_('Environment variable {} is not allowed to be used in credentials.').format(env_var),
code='invalid', params={'value': env_var},
)

Expand Down
2 changes: 1 addition & 1 deletion awx/main/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ class AuthToken(BaseModel):
sensitive_data = prevent_search(models.CharField(...))
The flag set by this function is used by
`awx.api.filters.FieldLookupBackend` to blacklist fields and relations that
`awx.api.filters.FieldLookupBackend` to block fields and relations that
should not be searchable/filterable via search query params
"""
setattr(relation, '__prevent_search__', True)
Expand Down
4 changes: 2 additions & 2 deletions awx/main/models/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -1910,7 +1910,7 @@ def inventory_as_dict(self, inventory_update, private_data_dir):
# Compatibility content
legacy_regex = {
True: r"[^A-Za-z0-9\_]",
False: r"[^A-Za-z0-9\_\-]" # do not replace dash, dash is whitelisted
False: r"[^A-Za-z0-9\_\-]" # do not replace dash, dash is allowed
}[replace_dash]
list_replacer = 'map("regex_replace", "{rx}", "_") | list'.format(rx=legacy_regex)
# this option, a plugin option, will allow dashes, but not unicode
Expand Down Expand Up @@ -1943,7 +1943,7 @@ def inventory_as_dict(self, inventory_update, private_data_dir):
ret['boto_profile'] = source_vars['boto_profile']

elif not replace_dash:
# Using the plugin, but still want dashes whitelisted
# Using the plugin, but still want dashes allowed
ret['use_contrib_script_compatible_sanitization'] = True

if source_vars.get('nested_groups') is False:
Expand Down
52 changes: 26 additions & 26 deletions awx/main/models/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,25 +262,25 @@ class JobNotificationMixin(object):
'running': 'started',
'failed': 'error'}
# Tree of fields that can be safely referenced in a notification message
JOB_FIELDS_WHITELIST = ['id', 'type', 'url', 'created', 'modified', 'name', 'description', 'job_type', 'playbook',
'forks', 'limit', 'verbosity', 'job_tags', 'force_handlers', 'skip_tags', 'start_at_task',
'timeout', 'use_fact_cache', 'launch_type', 'status', 'failed', 'started', 'finished',
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
'approval_status', 'approval_node_name', 'workflow_url', 'scm_branch',
{'host_status_counts': ['skipped', 'ok', 'changed', 'failed', 'failures', 'dark'
'processed', 'rescued', 'ignored']},
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
'total_hosts', 'hosts_with_active_failures', 'total_groups',
'has_inventory_sources',
'total_inventory_sources', 'inventory_sources_with_failures',
'organization_id', 'kind']},
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
{'job_template': ['id', 'name', 'description']},
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
{'instance_group': ['name', 'id']},
{'created_by': ['id', 'username', 'first_name', 'last_name']},
{'labels': ['count', 'results']}]}]
JOB_FIELDS_ALLOWED_LIST = ['id', 'type', 'url', 'created', 'modified', 'name', 'description', 'job_type', 'playbook',
'forks', 'limit', 'verbosity', 'job_tags', 'force_handlers', 'skip_tags', 'start_at_task',
'timeout', 'use_fact_cache', 'launch_type', 'status', 'failed', 'started', 'finished',
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
'approval_status', 'approval_node_name', 'workflow_url', 'scm_branch',
{'host_status_counts': ['skipped', 'ok', 'changed', 'failed', 'failures', 'dark'
'processed', 'rescued', 'ignored']},
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
'total_hosts', 'hosts_with_active_failures', 'total_groups',
'has_inventory_sources',
'total_inventory_sources', 'inventory_sources_with_failures',
'organization_id', 'kind']},
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
{'job_template': ['id', 'name', 'description']},
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
{'instance_group': ['name', 'id']},
{'created_by': ['id', 'username', 'first_name', 'last_name']},
{'labels': ['count', 'results']}]}]

@classmethod
def context_stub(cls):
Expand Down Expand Up @@ -377,8 +377,8 @@ def context_stub(cls):

def context(self, serialized_job):
"""Returns a dictionary that can be used for rendering notification messages.
The context will contain whitelisted content retrieved from a serialized job object
(see JobNotificationMixin.JOB_FIELDS_WHITELIST), the job's friendly name,
The context will contain allowed content retrieved from a serialized job object
(see JobNotificationMixin.JOB_FIELDS_ALLOWED_LIST the job's friendly name,
and a url to the job run."""
job_context = {'host_status_counts': {}}
summary = None
Expand All @@ -395,22 +395,22 @@ def context(self, serialized_job):
'job_metadata': json.dumps(self.notification_data(), indent=4)
}

def build_context(node, fields, whitelisted_fields):
for safe_field in whitelisted_fields:
def build_context(node, fields, allowed_fields):
for safe_field in allowed_fields:
if type(safe_field) is dict:
field, whitelist_subnode = safe_field.copy().popitem()
field, allowed_subnode = safe_field.copy().popitem()
# ensure content present in job serialization
if field not in fields:
continue
subnode = fields[field]
node[field] = {}
build_context(node[field], subnode, whitelist_subnode)
build_context(node[field], subnode, allowed_subnode)
else:
# ensure content present in job serialization
if safe_field not in fields:
continue
node[safe_field] = fields[safe_field]
build_context(context['job'], serialized_job, self.JOB_FIELDS_WHITELIST)
build_context(context['job'], serialized_job, self.JOB_FIELDS_ALLOWED_LIST)

return context

Expand Down
2 changes: 1 addition & 1 deletion awx/main/models/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class WorkflowJobTemplateNode(WorkflowNodeBase):
'always_nodes', 'credentials', 'inventory', 'extra_data', 'survey_passwords',
'char_prompts', 'all_parents_must_converge', 'identifier'
]
REENCRYPTION_BLACKLIST_AT_COPY = ['extra_data', 'survey_passwords']
REENCRYPTION_BLOCKLIST_AT_COPY = ['extra_data', 'survey_passwords']

workflow_job_template = models.ForeignKey(
'WorkflowJobTemplate',
Expand Down
4 changes: 2 additions & 2 deletions awx/main/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1802,7 +1802,7 @@ def build_extra_vars_file(self, job, private_data_dir):

# By default, all extra vars disallow Jinja2 template usage for
# security reasons; top level key-values defined in JT.extra_vars, however,
# are whitelisted as "safe" (because they can only be set by users with
# are allowed as "safe" (because they can only be set by users with
# higher levels of privilege - those that have the ability create and
# edit Job Templates)
safe_dict = {}
Expand Down Expand Up @@ -2472,7 +2472,7 @@ def build_env(self, inventory_update, private_data_dir, isolated, private_data_f

if inventory_update.source in ['scm', 'custom']:
for env_k in inventory_update.source_vars_dict:
if str(env_k) not in env and str(env_k) not in settings.INV_ENV_VARIABLE_BLACKLIST:
if str(env_k) not in env and str(env_k) not in settings.INV_ENV_VARIABLE_BLOCKED:
env[str(env_k)] = str(inventory_update.source_vars_dict[env_k])
elif inventory_update.source == 'file':
raise NotImplementedError('Cannot update file sources through the task system.')
Expand Down
16 changes: 8 additions & 8 deletions awx/main/tests/functional/api/test_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@pytest.mark.django_db
def test_proxy_ip_whitelist(get, patch, admin):
def test_proxy_ip_allowed(get, patch, admin):
url = reverse('api:setting_singleton_detail', kwargs={'category_slug': 'system'})
patch(url, user=admin, data={
'REMOTE_HOST_HEADERS': [
Expand All @@ -23,37 +23,37 @@ def process_request(self, request):
def process_response(self, request, response):
self.environ = request.environ

# By default, `PROXY_IP_WHITELIST` is disabled, so custom `REMOTE_HOST_HEADERS`
# By default, `PROXY_IP_ALLOWED_LIST` is disabled, so custom `REMOTE_HOST_HEADERS`
# should just pass through
middleware = HeaderTrackingMiddleware()
get(url, user=admin, middleware=middleware,
HTTP_X_FROM_THE_LOAD_BALANCER='some-actual-ip')
assert middleware.environ['HTTP_X_FROM_THE_LOAD_BALANCER'] == 'some-actual-ip'

# If `PROXY_IP_WHITELIST` is restricted to 10.0.1.100 and we make a request
# If `PROXY_IP_ALLOWED_LIST` is restricted to 10.0.1.100 and we make a request
# from 8.9.10.11, the custom `HTTP_X_FROM_THE_LOAD_BALANCER` header should
# be stripped
patch(url, user=admin, data={
'PROXY_IP_WHITELIST': ['10.0.1.100']
'PROXY_IP_ALLOWED_LIST': ['10.0.1.100']
})
middleware = HeaderTrackingMiddleware()
get(url, user=admin, middleware=middleware, REMOTE_ADDR='8.9.10.11',
HTTP_X_FROM_THE_LOAD_BALANCER='some-actual-ip')
assert 'HTTP_X_FROM_THE_LOAD_BALANCER' not in middleware.environ

# If 8.9.10.11 is added to `PROXY_IP_WHITELIST` the
# If 8.9.10.11 is added to `PROXY_IP_ALLOWED_LIST` the
# `HTTP_X_FROM_THE_LOAD_BALANCER` header should be passed through again
patch(url, user=admin, data={
'PROXY_IP_WHITELIST': ['10.0.1.100', '8.9.10.11']
'PROXY_IP_ALLOWED_LIST': ['10.0.1.100', '8.9.10.11']
})
middleware = HeaderTrackingMiddleware()
get(url, user=admin, middleware=middleware, REMOTE_ADDR='8.9.10.11',
HTTP_X_FROM_THE_LOAD_BALANCER='some-actual-ip')
assert middleware.environ['HTTP_X_FROM_THE_LOAD_BALANCER'] == 'some-actual-ip'

# Allow whitelisting of proxy hostnames in addition to IP addresses
# Allow allowed list of proxy hostnames in addition to IP addresses
patch(url, user=admin, data={
'PROXY_IP_WHITELIST': ['my.proxy.example.org']
'PROXY_IP_ALLOWED_LIST': ['my.proxy.example.org']
})
middleware = HeaderTrackingMiddleware()
get(url, user=admin, middleware=middleware, REMOTE_ADDR='8.9.10.11',
Expand Down
2 changes: 1 addition & 1 deletion awx/main/tests/functional/api/test_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ def test_inventory_update_access_called(post, inventory_source, alice, mock_acce
@pytest.mark.django_db
def test_inventory_source_vars_prohibition(post, inventory, admin_user):
with mock.patch('awx.api.serializers.settings') as mock_settings:
mock_settings.INV_ENV_VARIABLE_BLACKLIST = ('FOOBAR',)
mock_settings.INV_ENV_VARIABLE_BLOCKED = ('FOOBAR',)
r = post(reverse('api:inventory_source_list'),
{'name': 'new inv src', 'source_vars': '{\"FOOBAR\": \"val\"}', 'inventory': inventory.pk},
admin_user, expect=400)
Expand Down
Loading

0 comments on commit 78229f5

Please sign in to comment.