Браузер получал 404 на https://sarex.contour.infra.sarex.tech/media/state/previews/....png то есть backend отдавал АБСОЛЮТНЫЕ ссылки на чужой хост. Файлы при этом лежали у нас — уходил не тот домен. Источников оказалось три, и все в base: * django-configmap, HOST = "https://sarex.contour.infra.sarex.tech" — именно по нему строятся абсолютные ссылки на медиа; * там же CSRF_TRUSTED_ORIGINS с тем же доменом: без нашего домена django отклонял бы POST-формы админки по проверке Referer; * envs backend SERVER_API_HOST и SERVER_HOST. У celery те же две переменные я поправил раньше, а у backend пропустил. Конфигмап скопирован в оверлей целиком: все настройки лежат одним значением data.production.py на 331 строку, kustomize заменяет его только целиком — та же причина, что у nginx-configmap рядом. Изменены ровно две строки, остальное побайтно совпадает с base, так что diff остаётся читаемым. После правки домена sarex.contour.infra.sarex.tech в рендере clusters/aero/apps не остаётся ни одного вхождения.
349 lines
13 KiB
YAML
349 lines
13 KiB
YAML
# Копия django-configmap из base с заменой домена на домен контура.
|
||
#
|
||
# Патчем этого не сделать: все настройки лежат ОДНИМ значением data.production.py
|
||
# (331 строка python), kustomize умеет заменить его только целиком. Ровно та же
|
||
# причина, что у nginx-configmap.yaml рядом.
|
||
#
|
||
# ЧТО ИЗМЕНЕНО — две строки, обе про домен sarex.contour.infra.sarex.tech,
|
||
# принадлежащий ДРУГОМУ контуру:
|
||
#
|
||
# HOST — по нему backend строит АБСОЛЮТНЫЕ ссылки на медиа.
|
||
# Браузер получал
|
||
# https://sarex.contour.infra.sarex.tech/media/state/previews/....png
|
||
# и, разумеется, 404: чужой хост, наших файлов там нет.
|
||
# CSRF_TRUSTED_ORIGINS — без нашего домена django отклонял бы POST-формы
|
||
# админки с ошибкой проверки Referer.
|
||
#
|
||
# Больше в файле ничего не менялось: сравнивать с base удобно обычным diff.
|
||
apiVersion: v1
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: django-configmap
|
||
namespace: django
|
||
data:
|
||
production.py: |
|
||
import ast
|
||
import os
|
||
from .base import *
|
||
from logging.handlers import SysLogHandler
|
||
from datetime import timedelta
|
||
|
||
def _load_env_file(path):
|
||
try:
|
||
with open(path, "r", encoding="utf-8") as f:
|
||
for raw_line in f:
|
||
line = raw_line.strip()
|
||
if not line or line.startswith("#") or "=" not in line:
|
||
continue
|
||
key, value = line.split("=", 1)
|
||
key = key.strip()
|
||
value = value.strip()
|
||
if len(value) >= 2 and value[0] == value[-1] and value[0] in ("'", '"'):
|
||
try:
|
||
value = ast.literal_eval(value)
|
||
except (ValueError, SyntaxError):
|
||
value = value[1:-1]
|
||
if key and key not in os.environ:
|
||
os.environ[key] = value
|
||
except FileNotFoundError:
|
||
pass
|
||
|
||
def _read_secret_file(path, default=""):
|
||
try:
|
||
with open(path, "r", encoding="utf-8") as f:
|
||
return f.read().strip()
|
||
except FileNotFoundError:
|
||
return default
|
||
|
||
# Fallback for manage.py launched via `kubectl exec` (outside entrypoint),
|
||
# so Django can still read DB/JWT values from Vault-injected files.
|
||
_load_env_file("/vault/secrets/django-postgresql")
|
||
_load_env_file("/vault/secrets/django-rabbitmq")
|
||
_load_env_file("/vault/secrets/django-s3")
|
||
_load_env_file("/vault/secrets/django-kafka")
|
||
_load_env_file("/vault/secrets/django-common")
|
||
|
||
if not os.environ.get("JWT_PRIVATE_KEY"):
|
||
os.environ["JWT_PRIVATE_KEY"] = _read_secret_file("/vault/secrets/django-jwt-private")
|
||
if not os.environ.get("JWT_PUBLIC_KEY"):
|
||
os.environ["JWT_PUBLIC_KEY"] = _read_secret_file("/vault/secrets/django-jwt-public")
|
||
|
||
ALLOWED_HOSTS = ["*"]
|
||
FILE_UPLOAD_PERMISSIONS = 0o644
|
||
DEBUG = False
|
||
CSRF_COOKIE_SECURE = True
|
||
CSRF_TRUSTED_ORIGINS = ["https://sarex.local.lonsdaleites.ru", "http://sarex.local.lonsdaleites.ru"]
|
||
SESSION_COOKIE_SECURE = True
|
||
SECURE_SSL_REDIRECT = False
|
||
|
||
SECRET_KEY = 't2=9+($2f%7ptsdy4!rby$)mcfl1l%o2e@vs^d(g&(wwi&%k1v'
|
||
|
||
CORS_ORIGIN_ALLOW_ALL = True
|
||
SERVERSETTINGS.cache_enabled = True
|
||
INSTALLED_APPS = list(INSTALLED_APPS) + ['corsheaders']
|
||
|
||
CORS_ALLOW_METHODS = (
|
||
'DELETE',
|
||
'GET',
|
||
'OPTIONS',
|
||
'PATCH',
|
||
'POST',
|
||
'PUT',
|
||
)
|
||
BASIC_USER_ID = 2
|
||
|
||
CORS_ALLOW_HEADERS = (
|
||
'accept',
|
||
'accept-encoding',
|
||
'authorization',
|
||
'content-type',
|
||
'user-agent',
|
||
'x-csrftoken',
|
||
'x-requested-with',
|
||
'x-token',
|
||
'Bearer',
|
||
)
|
||
|
||
HOST = "https://sarex.local.lonsdaleites.ru"
|
||
|
||
POSTGRES_DATABASE = os.environ.get('DJANGO_POSTGRES_DATABASE')
|
||
POSTGRES_USER = os.environ.get('DJANGO_POSTGRES_USER')
|
||
POSTGRES_PASSWORD = os.environ.get('DJANGO_POSTGRES_PASSWORD')
|
||
POSTGRES_HOST = os.environ.get('DJANGO_POSTGRES_HOST')
|
||
POSTGRES_PORTS = os.environ.get('DJANGO_POSTGRES_PORTS', "5432")
|
||
|
||
DATABASES = {
|
||
'default': {
|
||
'ENGINE': 'django_prometheus.db.backends.postgresql',
|
||
'NAME': POSTGRES_DATABASE,
|
||
'USER': POSTGRES_USER,
|
||
'PASSWORD': POSTGRES_PASSWORD,
|
||
'HOST': POSTGRES_HOST,
|
||
'PORT': POSTGRES_PORTS,
|
||
}
|
||
}
|
||
|
||
MEASUREMENTSETTINGS = MeasurementSettings()
|
||
WORKFLOWSSETTINGS = WorkFlowsSettings()
|
||
S3SETTINGS = S3Settings()
|
||
GATEWAYSETTINGS = GateWaySetttings()
|
||
|
||
LOGGING = {
|
||
'version': 1,
|
||
'disable_existing_loggers': False,
|
||
'filters': {
|
||
'require_debug_false': {
|
||
'()': 'django.utils.log.RequireDebugFalse',
|
||
}
|
||
},
|
||
'formatters': {
|
||
'verbose': {
|
||
'format': '[contactor] %(levelname)s %(asctime)s %(message)s',
|
||
},
|
||
},
|
||
'handlers': {
|
||
'console': {
|
||
'level': 'DEBUG',
|
||
'class': 'logging.StreamHandler',
|
||
},
|
||
'sentry': {
|
||
'level': 'ERROR',
|
||
'filters': ['require_debug_false'],
|
||
'class': 'logging.StreamHandler',
|
||
},
|
||
},
|
||
'loggers': {
|
||
'': {
|
||
'handlers': ['console', 'sentry'],
|
||
'level': 'INFO',
|
||
'propagate': False,
|
||
},
|
||
}
|
||
}
|
||
|
||
COMPARATOR_JWT = os.environ.get("COMPARATOR_JWT", "default_jwt")
|
||
COMPARATOR_URL = os.environ.get("COMPARATOR_URL", "https://wb.sarex.io/comparator")
|
||
COMPARATOR_SECTION = os.environ.get("COMPARATOR_SECTION", "sarex-production-storage")
|
||
|
||
SIMPLE_JWT = {
|
||
'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
|
||
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
|
||
'ROTATE_REFRESH_TOKENS': False,
|
||
'BLACKLIST_AFTER_ROTATION': True,
|
||
'UPDATE_LAST_LOGIN': False,
|
||
'ALGORITHM': 'RS512',
|
||
'SIGNING_KEY': os.environ.get("JWT_PRIVATE_KEY", "").replace("\\n", "\n"),
|
||
'VERIFYING_KEY': os.environ.get("JWT_PUBLIC_KEY", "").replace("\\n", "\n"),
|
||
'AUDIENCE': None,
|
||
'ISSUER': os.environ.get('SIMPLE_JWT_ISSUER', 'default_issuer'),
|
||
'AUTH_HEADER_TYPES': ('Bearer',),
|
||
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
|
||
'USER_ID_FIELD': 'id',
|
||
'USER_ID_CLAIM': 'user_id',
|
||
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
|
||
'TOKEN_TYPE_CLAIM': 'token_type',
|
||
'JTI_CLAIM': 'jti',
|
||
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
|
||
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
|
||
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
|
||
}
|
||
|
||
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
|
||
DEFAULT_FILE_STORAGE = 'sarex.core.storages.CustomS3Boto3Storage'
|
||
DATA_UPLOAD_MAX_MEMORY_SIZE = 268435456
|
||
|
||
if not os.environ.get('ISOLATED', False):
|
||
import sentry_sdk
|
||
from sentry_sdk.integrations.django import DjangoIntegration
|
||
|
||
sentry_sdk.init(
|
||
dsn="https://3df2f4b8d3d14595a06c92e9d7c562cb@sentry.io/1501541",
|
||
integrations=[DjangoIntegration()],
|
||
environment=os.environ.get('SENTRY_ENVIRONMENT', 'production'),
|
||
send_default_pii=True,
|
||
)
|
||
|
||
COMPARISON_API_URL = f"{os.environ.get('WORKFLOWSSETTINGS_HOST')}/comparisons"
|
||
DOCUMENTATION_API_URL = f"{os.environ.get('WORKFLOWSSETTINGS_HOST')}/documentations"
|
||
PDM_FILES_API_URL = f"{os.environ.get('WORKFLOWSSETTINGS_HOST')}/files"
|
||
|
||
WORKFLOWS_TASKS = {
|
||
"update_orthomosaic_data": {
|
||
"image": f"{os.environ.get('WORKFLOWSSETTINGS_REGISTRY')}/update-orthomosaic-data:dev",
|
||
"service_requests": ["django-auth"],
|
||
"backoff_limit": 3,
|
||
},
|
||
}
|
||
|
||
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': (
|
||
'rest_framework.pagination.LimitOffsetPagination' ),
|
||
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
|
||
'PAGE_SIZE': 1000, 'DEFAULT_FILTER_BACKENDS': [
|
||
'django_filters.rest_framework.DjangoFilterBackend' ],
|
||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||
'sarex.authentication.backends.ZitadelJWTAuthentication',
|
||
'rest_framework.authentication.RemoteUserAuthentication',
|
||
'rest_framework_simplejwt.authentication.JWTAuthentication',
|
||
'rest_framework.authentication.BasicAuthentication',
|
||
'rest_framework.authentication.SessionAuthentication',
|
||
'sarex.authentication.backends.JWTAuthentication' ],
|
||
'DEFAULT_PERMISSION_CLASSES': [
|
||
'rest_framework.permissions.IsAuthenticated', ] }
|
||
|
||
AUTHENTICATION_BACKENDS = [
|
||
'sarex.authentication.backends.CustomRemoteUserBackend',
|
||
'django.contrib.auth.backends.ModelBackend',
|
||
'guardian.backends.ObjectPermissionBackend',
|
||
]
|
||
|
||
MIDDLEWARE = [
|
||
'django_prometheus.middleware.PrometheusBeforeMiddleware',
|
||
'django.middleware.security.SecurityMiddleware',
|
||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||
'django.middleware.common.CommonMiddleware',
|
||
'django.middleware.csrf.CsrfViewMiddleware',
|
||
#'django_keycloak.middlewares.AuthorizationHeaderMiddleware',
|
||
#'django_keycloak.middlewares.KeycloakSessionMiddleware',
|
||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||
#'django.contrib.auth.middleware.RemoteUserMiddleware',
|
||
'django.contrib.messages.middleware.MessageMiddleware',
|
||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||
'django_user_agents.middleware.UserAgentMiddleware',
|
||
'simple_history.middleware.HistoryRequestMiddleware',
|
||
'django_prometheus.middleware.PrometheusAfterMiddleware', ]
|
||
|
||
|
||
class KeyCloakSettings(BaseSettings):
|
||
client_id: str = "client_id"
|
||
client_secret: str = "client_secret"
|
||
discovery_url: str = "https://login.wb.sarex.io/realms/sarex/.well-known/openid-configuration"
|
||
staff: Optional[str] = "Sarex staff"
|
||
superuser: Optional[str] = "Sarex superusers"
|
||
sync_with_django: bool = True
|
||
sync_admin: bool = False
|
||
group_prefix: str = 'Sarex-Role'
|
||
company_prefix: str = 'Sarex-Company'
|
||
department_prefix: str = 'Sarex-Department'
|
||
position_prefix: str = 'Sarex-Position'
|
||
separator: str = '__'
|
||
sync_user_groups: bool = False
|
||
sync_user_positions: bool = False
|
||
sync_user_departments: bool = False
|
||
sync_user_companies: bool = False
|
||
use_redirect_logout: bool = False
|
||
logout_redirect_uri: str = "/"
|
||
default_group_name: Optional[str] = 'Тест'
|
||
default_company_name: Optional[str] = 'Брусника'
|
||
trusted_uri: List[str] = ['/api/core/orthophotos/', '/api/token', '/api/token/me']
|
||
trusted_uri: List[str] = []
|
||
|
||
class Config:
|
||
env_prefix = "KC_"
|
||
|
||
|
||
KEYCLOAKSETTINGS = KeyCloakSettings()
|
||
|
||
REMOTE_USER_DEFAULT_COMPANY_ID = 1
|
||
SAREX_MODULES = [
|
||
{
|
||
"name": "Замечания",
|
||
"uri": "/remarks"
|
||
},
|
||
# {
|
||
# "name": "Управление проектами",
|
||
# "uri": "/management/projects",
|
||
# },
|
||
{
|
||
"name": "Замечания V2",
|
||
"uri": "/issues"
|
||
},
|
||
{
|
||
"name": "Документация",
|
||
"uri": "/documentations",
|
||
},
|
||
{
|
||
"name": "Согласование документов",
|
||
"uri": "/reviews"
|
||
},
|
||
{
|
||
"name": "Рабочие процессы",
|
||
"uri": "/processes"
|
||
},
|
||
{
|
||
"name": "Запросы",
|
||
"uri": "/rfi"
|
||
},
|
||
{
|
||
"name": "Управление проектами",
|
||
"uri": "/management/projects"
|
||
},
|
||
|
||
# {
|
||
# "name": "Обзор",
|
||
# "uri": "/projects"
|
||
# },
|
||
{
|
||
"name": "Передача документации",
|
||
"uri": "/transmittal"
|
||
},
|
||
]
|
||
AUTH_SETTINGS = {
|
||
"refresh_token": False,
|
||
"refresh_token_uri": "/api/token/me",
|
||
"refresh_oauth_token": True,
|
||
"refresh_oauth_token_uri": "/oauth/token",
|
||
"refresh_time": 240,
|
||
}
|
||
|
||
|
||
DEBUG=True
|
||
WEB_APP_AUTH_MODE='jwt-session-based'
|
||
|
||
|
||
SAREX_MODULES_SETTINGS = {
|
||
"aero": {
|
||
"enable_new_media": True
|
||
},
|
||
"sso_logout_redirect": True
|
||
}
|