diff --git a/.ci/ansible/settings.py.j2 b/.ci/ansible/settings.py.j2 index ab8ebb3dce0..0b8a1a16a4d 100644 --- a/.ci/ansible/settings.py.j2 +++ b/.ci/ansible/settings.py.j2 @@ -1,3 +1,4 @@ +SECRET_KEY = "{{ django_secret }}" CONTENT_ORIGIN = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}" ANSIBLE_API_HOSTNAME = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}" ANSIBLE_CONTENT_HOSTNAME = "{{ pulp_scheme }}://pulp:{{ 443 if pulp_scheme == 'https' else 80 }}/pulp/content" diff --git a/.ci/ansible/start_container.yaml b/.ci/ansible/start_container.yaml index e0891b7ab5d..4ef94c861cf 100644 --- a/.ci/ansible/start_container.yaml +++ b/.ci/ansible/start_container.yaml @@ -18,6 +18,8 @@ ansible.builtin.template: src: "settings.py.j2" dest: "settings/settings.py" + vars: + django_secret: "lookup('community.general.random_string', length=50, overwrite_all='abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)')" - name: "Setup docker networking" community.docker.docker_network: diff --git a/CHANGES/+django_secret.bugfix b/CHANGES/+django_secret.bugfix new file mode 100644 index 00000000000..571ee9046f7 --- /dev/null +++ b/CHANGES/+django_secret.bugfix @@ -0,0 +1 @@ +Stopped shipping an insecure default as DJANGO_SECRET. diff --git a/pulp_file/tests/functional/api/test_domains.py b/pulp_file/tests/functional/api/test_domains.py index 51869b8114e..c88eecc0048 100644 --- a/pulp_file/tests/functional/api/test_domains.py +++ b/pulp_file/tests/functional/api/test_domains.py @@ -2,8 +2,8 @@ import uuid import pytest +from django.conf import settings -from pulpcore.app import settings from pulpcore.tests.functional.utils import download_file, generate_iso pytestmark = pytest.mark.skipif(not settings.DOMAIN_ENABLED, reason="Domains not enabled.") diff --git a/pulp_file/tests/functional/api/test_filesystem_export.py b/pulp_file/tests/functional/api/test_filesystem_export.py index 5720840ca5a..da92c1b471b 100644 --- a/pulp_file/tests/functional/api/test_filesystem_export.py +++ b/pulp_file/tests/functional/api/test_filesystem_export.py @@ -2,8 +2,8 @@ import uuid import pytest +from django.conf import settings -from pulpcore.app import settings from pulpcore.client.pulpcore.exceptions import ApiException, BadRequestException from pulpcore.constants import TASK_STATES diff --git a/pulp_file/tests/functional/api/test_pulp_export.py b/pulp_file/tests/functional/api/test_pulp_export.py index 7a1078eede1..792c15812cb 100644 --- a/pulp_file/tests/functional/api/test_pulp_export.py +++ b/pulp_file/tests/functional/api/test_pulp_export.py @@ -3,8 +3,8 @@ from pathlib import Path import pytest +from django.conf import settings -from pulpcore.app import settings from pulpcore.client.pulpcore.exceptions import ApiException, BadRequestException from pulpcore.constants import TASK_STATES diff --git a/pulpcore/app/access_policy.py b/pulpcore/app/access_policy.py index 6cb41c02b7b..6654f5259c8 100644 --- a/pulpcore/app/access_policy.py +++ b/pulpcore/app/access_policy.py @@ -1,9 +1,9 @@ from copy import deepcopy +from django.conf import settings from rest_access_policy import AccessPolicy from rest_framework.exceptions import APIException -from pulpcore.app import settings from pulpcore.app.models import AccessPolicy as AccessPolicyModel from pulpcore.app.util import get_view_urlpattern, get_viewset_for_model diff --git a/pulpcore/app/authentication.py b/pulpcore/app/authentication.py index 0e42ec0871d..745e35e1ffa 100644 --- a/pulpcore/app/authentication.py +++ b/pulpcore/app/authentication.py @@ -5,6 +5,7 @@ from gettext import gettext as _ import jq +from django.conf import settings from django.contrib.auth import authenticate from django.contrib.auth.backends import RemoteUserBackend from rest_framework.authentication import ( @@ -16,8 +17,6 @@ ) from rest_framework.exceptions import AuthenticationFailed -from pulpcore.app import settings - _logger = logging.getLogger(__name__) diff --git a/pulpcore/app/redis_connection.py b/pulpcore/app/redis_connection.py index e612680cbd0..87270c11249 100644 --- a/pulpcore/app/redis_connection.py +++ b/pulpcore/app/redis_connection.py @@ -1,8 +1,7 @@ +from django.conf import settings from redis import Redis from redis.asyncio import Redis as aRedis -from pulpcore.app.settings import settings - _conn = None _a_conn = None diff --git a/pulpcore/app/serializers/exporter.py b/pulpcore/app/serializers/exporter.py index 8142853d196..fd8a98964fd 100644 --- a/pulpcore/app/serializers/exporter.py +++ b/pulpcore/app/serializers/exporter.py @@ -2,9 +2,10 @@ import re from gettext import gettext as _ +from django.conf import settings from rest_framework import serializers -from pulpcore.app import models, settings +from pulpcore.app import models from pulpcore.app.serializers import ( DetailIdentityField, DetailRelatedField, diff --git a/pulpcore/app/serializers/importer.py b/pulpcore/app/serializers/importer.py index e1a28ae60a9..5985e7fc5e3 100644 --- a/pulpcore/app/serializers/importer.py +++ b/pulpcore/app/serializers/importer.py @@ -1,10 +1,11 @@ import os from gettext import gettext as _ +from django.conf import settings from django.core.exceptions import ObjectDoesNotExist from rest_framework import serializers -from pulpcore.app import models, settings +from pulpcore.app import models from pulpcore.app.serializers import ( DetailIdentityField, DomainUniqueValidator, diff --git a/pulpcore/app/serializers/repository.py b/pulpcore/app/serializers/repository.py index fa6edde3e96..5569fcb7ba3 100644 --- a/pulpcore/app/serializers/repository.py +++ b/pulpcore/app/serializers/repository.py @@ -2,10 +2,11 @@ from gettext import gettext as _ from urllib.parse import urlparse +from django.conf import settings from rest_framework import fields, serializers from rest_framework_nested.serializers import NestedHyperlinkedModelSerializer -from pulpcore.app import models, settings +from pulpcore.app import models from pulpcore.app.serializers import ( DetailIdentityField, DetailRelatedField, diff --git a/pulpcore/app/settings.py b/pulpcore/app/settings.py index 4f77675fb7a..208ce539fcd 100644 --- a/pulpcore/app/settings.py +++ b/pulpcore/app/settings.py @@ -12,7 +12,6 @@ from contextlib import suppress from importlib import import_module from importlib.metadata import entry_points -from logging import getLogger from pathlib import Path from cryptography.fernet import Fernet @@ -88,9 +87,6 @@ # List of upload handler classes to be applied in order. FILE_UPLOAD_HANDLERS = ("pulpcore.app.files.HashingFileUploadHandler",) -# SECURITY WARNING: this should be set to a unique, unpredictable value -SECRET_KEY = "SECRET" - # Key used to encrypt fields in the database DB_ENCRYPTION_KEY = "/etc/pulp/certs/database_fields.symmetric.key" @@ -537,6 +533,49 @@ def otel_middleware_hook(settings): return data +def api_root_hook(settings): + # protocol://host:port/{API_ROOT}{domain}/api/{version}/ + # All of the below are DEPRECATED, and should be replaced by calling + # pulpcore.plugin.find_url.find_api_root() (q.v.) + if settings.API_ROOT_REWRITE_HEADER: + api_root = "//" + else: + api_root = settings.API_ROOT + return { + "V3_API_ROOT": api_root + "api/v3/", + "V3_DOMAIN_API_ROOT": api_root + "/api/v3/", + "V3_API_ROOT_NO_FRONT_SLASH": (api_root + "api/v3/").lstrip("/"), + "V3_DOMAIN_API_ROOT_NO_FRONT_SLASH": (api_root + "/api/v3/").lstrip("/"), + } + + +def forbidden_checksums_hook(settings): + return { + "FORBIDDEN_CHECKSUMS": sorted( + set(constants.ALL_KNOWN_CONTENT_CHECKSUMS).difference( + settings.ALLOWED_CONTENT_CHECKSUMS + ) + ), + } + + +def validate_db_encryption_key_hook(settings): + if Path(sys.argv[0]).name in ["pytest", "sphinx-build"] or ( + len(sys.argv) >= 2 and sys.argv[1] in ["collectstatic", "openapi"] + ): + return {} + try: + with open(settings.DB_ENCRYPTION_KEY, "rb") as key_file: + Fernet(key_file.read()) + except Exception as ex: + raise ImproperlyConfigured( + "Could not load DB_ENCRYPTION_KEY file '{file}': {err}".format( + file=settings.DB_ENCRYPTION_KEY, err=ex + ) + ) + return {} + + del preload_settings settings = DjangoDynaconf( @@ -557,36 +596,12 @@ def otel_middleware_hook(settings): authentication_json_header_openapi_security_scheme_validator, otel_pulp_api_histogram_buckets_validator, ], - post_hooks=(otel_middleware_hook,), -) - -_logger = getLogger(__name__) - - -if not ( - Path(sys.argv[0]).name in ["pytest", "sphinx-build"] - or (len(sys.argv) >= 2 and sys.argv[1] in ["collectstatic", "openapi"]) -): - try: - with open(DB_ENCRYPTION_KEY, "rb") as key_file: - Fernet(key_file.read()) - except Exception as ex: - raise ImproperlyConfigured( - ("Could not load DB_ENCRYPTION_KEY file '{file}': {err}").format( - file=DB_ENCRYPTION_KEY, err=ex - ) - ) - - -FORBIDDEN_CHECKSUMS = set(constants.ALL_KNOWN_CONTENT_CHECKSUMS).difference( - ALLOWED_CONTENT_CHECKSUMS + post_hooks=( + otel_middleware_hook, + api_root_hook, + forbidden_checksums_hook, + validate_db_encryption_key_hook, + ), ) -if settings.API_ROOT_REWRITE_HEADER: - api_root = "//" -else: - api_root = settings.API_ROOT -settings.set("V3_API_ROOT", api_root + "api/v3/") # Not user configurable -settings.set("V3_DOMAIN_API_ROOT", api_root + "/api/v3/") -settings.set("V3_API_ROOT_NO_FRONT_SLASH", settings.V3_API_ROOT.lstrip("/")) -settings.set("V3_DOMAIN_API_ROOT_NO_FRONT_SLASH", settings.V3_DOMAIN_API_ROOT.lstrip("/")) +# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line) diff --git a/pulpcore/app/views/importer.py b/pulpcore/app/views/importer.py index 5e5f104588a..e49aa43ba04 100644 --- a/pulpcore/app/views/importer.py +++ b/pulpcore/app/views/importer.py @@ -2,11 +2,11 @@ import os from gettext import gettext as _ +from django.conf import settings from drf_spectacular.utils import extend_schema from rest_framework.response import Response from rest_framework.views import APIView -from pulpcore.app import settings from pulpcore.app.serializers import PulpImportCheckResponseSerializer, PulpImportCheckSerializer diff --git a/pulpcore/cache/cache.py b/pulpcore/cache/cache.py index ec6ca80e6f6..6fcf470e14a 100644 --- a/pulpcore/cache/cache.py +++ b/pulpcore/cache/cache.py @@ -5,6 +5,7 @@ from aiohttp.web import FileResponse, HTTPSuccessful, Request, Response, StreamResponse from aiohttp.web_exceptions import HTTPFound +from django.conf import settings from django.http import FileResponse as ApiFileResponse from django.http import HttpResponse, HttpResponseRedirect from redis import ConnectionError @@ -16,7 +17,6 @@ get_async_redis_connection, get_redis_connection, ) -from pulpcore.app.settings import settings from pulpcore.metrics import artifacts_size_counter from pulpcore.responses import ArtifactResponse diff --git a/pulpcore/tasking/kafka.py b/pulpcore/tasking/kafka.py index 3f6f0fd447d..808e20d7bbf 100644 --- a/pulpcore/tasking/kafka.py +++ b/pulpcore/tasking/kafka.py @@ -6,7 +6,7 @@ from django.conf import settings -_bootstrap_servers = settings.get("KAFKA_BOOTSTRAP_SERVERS") +_bootstrap_servers = getattr(settings, "KAFKA_BOOTSTRAP_SERVERS") if _bootstrap_servers is None: diff --git a/pulpcore/tests/functional/api/test_auth.py b/pulpcore/tests/functional/api/test_auth.py index 4bf6478b7c8..3eeb616d6c8 100644 --- a/pulpcore/tests/functional/api/test_auth.py +++ b/pulpcore/tests/functional/api/test_auth.py @@ -8,8 +8,7 @@ from base64 import b64encode import pytest - -from pulpcore.app import settings +from django.conf import settings @pytest.mark.parallel diff --git a/pulpcore/tests/functional/api/using_plugin/test_pulpimport.py b/pulpcore/tests/functional/api/using_plugin/test_pulpimport.py index fbca0df5417..927e3830575 100644 --- a/pulpcore/tests/functional/api/using_plugin/test_pulpimport.py +++ b/pulpcore/tests/functional/api/using_plugin/test_pulpimport.py @@ -11,8 +11,8 @@ from pathlib import Path import pytest +from django.conf import settings -from pulpcore.app import settings from pulpcore.client.pulp_file import RepositorySyncURL from pulpcore.client.pulpcore.exceptions import ApiException diff --git a/pyproject.toml b/pyproject.toml index 8b83cd05ad0..e9029f0fef8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -267,7 +267,6 @@ filename = "./pyproject.toml" search = "version = \"{current_version}\"" replace = "version = \"{new_version}\"" - [tool.ruff] # This section is managed by the plugin template. Do not edit manually. line-length = 100 @@ -289,6 +288,7 @@ extend-select = [ [tool.ruff.lint.flake8-tidy-imports.banned-api] # This section is managed by the plugin template. Do not edit manually. "distutils".msg = "The 'distutils' module has been deprecated since Python 3.9." +"pulpcore.app.settings".msg = "Always import 'settings' from 'django.conf' instead." [tool.ruff.lint.isort] # This section is managed by the plugin template. Do not edit manually.