From 092c2be0e768da42cd17a6ad23c264d8b29a9507 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Wed, 14 Dec 2016 16:57:32 -0500 Subject: [PATCH] Make any settings read-only that have been modified in custom Python config files. --- awx/conf/settings.py | 16 ++++++++++++++++ awx/settings/development.py | 15 +++++++-------- awx/settings/production.py | 15 +++++++-------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/awx/conf/settings.py b/awx/conf/settings.py index c08b161237..de8c82e1c5 100644 --- a/awx/conf/settings.py +++ b/awx/conf/settings.py @@ -1,6 +1,7 @@ # Python import contextlib import logging +import sys import threading import time @@ -86,6 +87,7 @@ class SettingsWrapper(UserSettingsHolder): self.__dict__['_awx_conf_settings'] = self self.__dict__['_awx_conf_preload_expires'] = None self.__dict__['_awx_conf_preload_lock'] = threading.RLock() + self.__dict__['_awx_conf_init_readonly'] = False def _get_supported_settings(self): return settings_registry.get_registered_settings() @@ -110,6 +112,20 @@ class SettingsWrapper(UserSettingsHolder): return # Otherwise update local preload timeout. self.__dict__['_awx_conf_preload_expires'] = time.time() + SETTING_CACHE_TIMEOUT + # Check for any settings that have been defined in Python files and + # make those read-only to avoid overriding in the database. + if not self._awx_conf_init_readonly and 'migrate_to_database_settings' not in sys.argv: + defaults_snapshot = self._get_default('DEFAULTS_SNAPSHOT') + for key in self._get_writeable_settings(): + init_default = defaults_snapshot.get(key, None) + try: + file_default = self._get_default(key) + except AttributeError: + file_default = None + if file_default != init_default and file_default is not None: + logger.warning('Setting %s has been marked read-only!', key) + settings_registry._registry[key]['read_only'] = True + self.__dict__['_awx_conf_init_readonly'] = True # If local preload timer has expired, check to see if another process # has already preloaded the cache and skip preloading if so. if cache.get('_awx_conf_preload_expires', empty) is not empty: diff --git a/awx/settings/development.py b/awx/settings/development.py index f2d72a1113..ebe81260d1 100644 --- a/awx/settings/development.py +++ b/awx/settings/development.py @@ -82,14 +82,13 @@ PASSWORD_HASHERS = ( # Configure a default UUID for development only. SYSTEM_UUID = '00000000-0000-0000-0000-000000000000' -# Store a snapshot of default settings at this point (only for migrating from -# file to database settings). -if 'migrate_to_database_settings' in sys.argv: - DEFAULTS_SNAPSHOT = {} - this_module = sys.modules[__name__] - for setting in dir(this_module): - if setting == setting.upper(): - DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting)) +# Store a snapshot of default settings at this point before loading any +# customizable config files. +DEFAULTS_SNAPSHOT = {} +this_module = sys.modules[__name__] +for setting in dir(this_module): + if setting == setting.upper(): + DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting)) # If there is an `/etc/tower/settings.py`, include it. # If there is a `/etc/tower/conf.d/*.py`, include them. diff --git a/awx/settings/production.py b/awx/settings/production.py index 103f775d86..f056a4ea31 100644 --- a/awx/settings/production.py +++ b/awx/settings/production.py @@ -57,14 +57,13 @@ LOGGING['handlers']['fact_receiver']['filename'] = '/var/log/tower/fact_receiver LOGGING['handlers']['system_tracking_migrations']['filename'] = '/var/log/tower/tower_system_tracking_migrations.log' LOGGING['handlers']['rbac_migrations']['filename'] = '/var/log/tower/tower_rbac_migrations.log' -# Store a snapshot of default settings at this point (only for migrating from -# file to database settings). -if 'migrate_to_database_settings' in sys.argv: - DEFAULTS_SNAPSHOT = {} - this_module = sys.modules[__name__] - for setting in dir(this_module): - if setting == setting.upper(): - DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting)) +# Store a snapshot of default settings at this point before loading any +# customizable config files. +DEFAULTS_SNAPSHOT = {} +this_module = sys.modules[__name__] +for setting in dir(this_module): + if setting == setting.upper(): + DEFAULTS_SNAPSHOT[setting] = copy.deepcopy(getattr(this_module, setting)) # Load settings from any .py files in the global conf.d directory specified in # the environment, defaulting to /etc/tower/conf.d/.