diff --git a/label_studio/core/settings/base.py b/label_studio/core/settings/base.py index 63c6e45f0e81..8648183e877d 100644 --- a/label_studio/core/settings/base.py +++ b/label_studio/core/settings/base.py @@ -74,8 +74,9 @@ if not logging.getLogger().hasHandlers(): logging.basicConfig(level=logging.DEBUG, format='%(message)s') -from label_studio.core.utils.io import get_data_dir, generate_key_if_missing +from label_studio.core.utils.io import get_data_dir from label_studio.core.utils.params import get_bool_env, get_env, get_env_list_int +from label_studio.core.utils.secret_key import generate_secret_key_if_missing logger = logging.getLogger(__name__) SILENCED_SYSTEM_CHECKS = [] @@ -104,9 +105,6 @@ INTERNAL_PORT = '8080' -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = generate_key_if_missing('SECRET_KEY') - # SECURITY WARNING: don't run with debug turned on in production! DEBUG = get_bool_env('DEBUG', True) DEBUG_MODAL_EXCEPTIONS = get_bool_env('DEBUG_MODAL_EXCEPTIONS', True) @@ -119,6 +117,9 @@ os.makedirs(BASE_DATA_DIR, exist_ok=True) logger.info('=> Database and media directory: %s', BASE_DATA_DIR) +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = generate_secret_key_if_missing(BASE_DATA_DIR) + # Databases # https://docs.djangoproject.com/en/2.1/ref/settings/#databases DJANGO_DB_MYSQL = 'mysql' diff --git a/label_studio/core/utils/io.py b/label_studio/core/utils/io.py index 476d792e3ebf..de2ec21f7c4e 100644 --- a/label_studio/core/utils/io.py +++ b/label_studio/core/utils/io.py @@ -16,9 +16,6 @@ from contextlib import contextmanager from tempfile import mkstemp, mkdtemp -from django.conf import settings -from django.core.management.utils import get_random_secret_key -from label_studio.core.utils.params import env, env_file from appdirs import user_config_dir, user_data_dir, user_cache_dir # full path import results in unit test failures @@ -210,20 +207,3 @@ def validate_upload_url(url, block_local_urls=True): for subnet in local_subnets: if ipaddress.ip_address(ip) in ipaddress.ip_network(subnet): raise InvalidUploadUrlError - -def generate_key_if_missing(key): - value = env.str(key, "") - - if value == "": - print(f'Warning: {key} not found in environment variables will generate a random key.') - value = get_random_secret_key() - try: - with open(env_file, 'a') as f: - f.write(f'\n{key}={value}\n') - except Exception as e: - print(f'Warning: failed to write {key} to .env file: {e}, new key will be regenerated on every server restart. If this key is used for signing, it will invalidate all existing sessions or tokens. Please set {key} in your environment variables to avoid this warning.') - - os.environ[key] = value - - return value - diff --git a/label_studio/core/utils/params.py b/label_studio/core/utils/params.py index 6305578621d7..b43796dd9a74 100644 --- a/label_studio/core/utils/params.py +++ b/label_studio/core/utils/params.py @@ -1,14 +1,8 @@ import os -import environ from rest_framework.exceptions import ValidationError -env = environ.Env() -data_dir = os.environ.get('LABEL_STUDIO_DATA_DIR', os.path.join(os.path.dirname(__file__), '..', '..', '..', 'data')) -env_file = os.path.join(data_dir, '.env') -environ.Env.read_env(env_file) - def cast_bool_from_str(value): if isinstance(value, str): if value.lower() in ['true', 'yes', 'on', '1']: diff --git a/label_studio/core/utils/secret_key.py b/label_studio/core/utils/secret_key.py new file mode 100644 index 000000000000..682655995264 --- /dev/null +++ b/label_studio/core/utils/secret_key.py @@ -0,0 +1,28 @@ +import logging +import os +import environ +from django.core.management.utils import get_random_secret_key + + +logger = logging.getLogger(__name__) + + +def generate_secret_key_if_missing(data_dir: str) -> str: + env_key = 'SECRET_KEY' + env = environ.Env() + env_filepath = os.path.join(data_dir, '.env') + environ.Env.read_env(env_filepath) + + if existing_secret := env.str(env_key, ""): + return existing_secret + + logger.warning(f'Warning: {env_key} not found in environment variables. Will generate a random key.') + new_secret = get_random_secret_key() + try: + with open(env_filepath, 'a') as f: + f.write(f'\n{env_key}={new_secret}\n') # nosec + except Exception as e: + logger.warning(f'Warning: failed to write {env_key} to .env file: {e}, new key will be regenerated on every server restart. If this key is used for signing, it will invalidate all existing sessions or tokens. Please set {key} in your environment variables to avoid this warning.') + + os.environ[env_key] = new_secret + return new_secret