SeniorPython Developer > Основы Python > Приватность и изоляция данных
Короткий ответ Нужно заранее спроектировать модель данных так, чтобы персональные данные были локализованы в ограниченном числе мест, а не размножены по кэшам, логам и аналитическим витринам без учёта этого, и предусмотреть явный процесс каскадного удаления/анонимизации по запросу пользователя, даже если это усложняет схему кэширования и снижает часть оптимизаций. Как это работает подробнее Право на удаление требует, чтобы при запросе пользователя система могла достоверно найти все места хранения его персональных данных — основную БД, резервные копии, кэши, аналитические агрегаты, логи — и либо удалить, либо анонимизировать данные там, где физическое удаление невозможно в разумный срок (например, в неизменяемых бэкапах) согласно политике хранения. Компромисс. Псевдонимизация и жёсткая локализация персональных данных снижают риск при compliance-аудите и упрощают удаление, но усложняют аналитические запросы (приходится джойнить данные через дополнительный слой) и могут снизить производительность некоторых горяч
cache-invalidationdata-retention
SeniorPython Developer > Основы Python > Архитектура веб-API
Короткий ответ Нужно явно перечислить разрешённые origin для каждого типа клиента (а не использовать wildcard-разрешение всех origin), развести механизмы защиты по типу аутентификации (CSRF актуален для cookie-based сессий из браузера, но не для API-ключей/токенов мобильного приложения или сервер-сервер интеграции партнёра) и решить, где физически применяется эта политика — на уровне API Gateway единообразно или по-разному на каждом отдельном сервисе за ним. Как это работает подробнее CORS защищает браузер пользователя от того, чтобы чужой сайт мог от имени пользователя читать ответы вашего API через JS без явного разрешения — это актуально именно для браузерных клиентов (веб-фронтенд, виджет, встраиваемый в сторонние сайты). CSRF актуален, когда аутентификация идёт через cookie, автоматически прикладываемый браузером к любому запросу на ваш домен, включая инициированные сторонним сайтом; для мобильного приложения или серверной интеграции партнёра, где аутентификация — явный токен в заголовке, а не cookie, кл
authenticationauthorization
SeniorPython Developer > Основы Python > Архитектура веб-API
Короткий ответ Нужно выбрать модель изоляции данных (отдельная БД/схема на tenant против общей таблицы с колонкой tenant_id и обязательной фильтрацией на каждом запросе) и способ определения tenant на входе запроса (поддомен, заголовок, JWT claim), причём определение tenant должно происходить как можно раньше в стеке middleware и передаваться явно во все последующие слои, включая запросы к БД. Как это работает подробнее Схема «общая таблица + tenant_id» проще в эксплуатации (одна БД, одни миграции) и дешевле для большого числа мелких tenant, но требует железной дисциплины — каждый запрос к БД должен фильтроваться по tenant_id (желательно на уровне, который невозможно случайно забыть, например через обязательный параметр в репозитории или row-level security в PostgreSQL), иначе утечка данных между tenant — вопрос времени. Схема «отдельная БД/схема на tenant» даёт более сильную изоляцию и проще для выполнения требований compliance отдельных крупных клиентов, но усложняет миграции (нужно прогонять на каждую БД/с
middlewaremulti-tenancy
SeniorPython Developer > Основы Python > Архитектура веб-API
Короткий ответ Нужно разделить флаги по времени жизни (временные флаги для постепенного релиза с обязательным планом удаления после полного раскатывания, и более долгоживущие операционные переключатели) и явно определить, где проверяется флаг — ближе к middleware/входу запроса для крупных изменений поведения или глубже в бизнес-логике для точечных веток, а также кто и как может менять значение флага в production (аудит изменений). Как это работает подробнее Feature flag, проверяемый в middleware/на входе запроса, удобен для изменений, затрагивающих весь путь обработки запроса (например, включение нового алгоритма маршрутизации целиком), но менее удобен для точечных изменений внутри бизнес-логики, где естественнее проверять флаг прямо в нужном месте кода. Несогласованность флага между несколькими сервисами (один сервис уже включил новое поведение, другой ещё нет) может создавать скрытые баги на границах интеграции. Проверка флага на уровне middleware проще для крупных переключений поведения всего запроса, но м
configurationfeature-flags
SeniorPython Developer > Основы Python > Приватность и изоляция данных
Короткий ответ Выбор зависит от числа и размера тенантов, требований к изоляции и операционной нагрузки: общая таблица с tenant_id дешевле в эксплуатации и проще масштабируется на много мелких тенантов, но требует дисциплины, чтобы ни один запрос не забыл фильтр по tenant_id; отдельная БД на тенанта даёт максимальную изоляцию ценой значительно более сложной эксплуатации при росте числа тенантов. Как это работает подробнее При общей таблице изоляция обеспечивается на уровне кода приложения и/или row-level security в самой БД (например, PostgreSQL RLS), которая принудительно добавляет условие по tenant_id к каждому запросу независимо от того, вспомнил ли об этом разработчик. Отдельная схема или БД физически разделяют данные, снижая риск «протекания» данных из-за ошибки в одном SQL-запросе, но увеличивают число объектов для миграций, мониторинга и резервного копирования пропорционально числу тенантов. Компромисс. Общая таблица с RLS дешевле и проще масштабируется на множество тенантов, но инцидент из-за одной ош
databasesdata-isolation
SeniorDevOps Engineer > Контейнеры и доставка > Безопасность и DevSecOps
Короткий ответ Конкретные шаги и приоритеты зависят от контекста организации, но типичная последовательность такова: немедленно деактивировать/отозвать утёкшие credentials и оценить реальную активность по ним за весь период возможной компрометации, а затем перейти от долгоживущих статических ключей к динамическим/короткоживущим credentials (OIDC-федерация, временные роли) везде, где это технически возможно, чтобы сам класс этой уязвимости перестал существовать. Как это работает подробнее статический долгоживущий ключ доступа, однажды утёкший, остаётся валидным до явного отзыва, и злоумышленник может использовать его неограниченное время без дальнейших усилий; обнаружение через сканирование GitHub обычно происходит быстро, но сам факт существования таких ключей — системный риск, не зависящий от скорости реакции. Временные credentials (AWS STS AssumeRole через OIDC, Workload Identity в GCP) ограничивают окно действия до минут/часов даже без явного инцидента. Сравнение Компромисс. полный переход на динамические
cloud-securitycredential-rotation
MiddlePython Developer > Основы Python > Управление памятью
Короткий ответ Нужно сопоставить рост памяти процесса во времени с ростом числа ключей в подозрительных структурах (кэши, реестры подписчиков, сессии), а не искать только циклические ссылки — неограниченный словарь-кэш растёт без всякого цикла, просто за счёт накопления новых уникальных ключей. Как это работает подробнее В отличие от утечки через циклические ссылки, здесь объекты абсолютно «легитимно» достижимы — они лежат в живом словаре кэша, на который есть обычная сильная ссылка из долгоживущего объекта приложения; сборщик мусора здесь не поможет, так как объекты не являются мусором с точки зрения интерпретатора. Пример кода Что использовать на практике Практика. Добавляют метрику len(cache) в мониторинг и смотрят на её рост во времени параллельно с RSS процесса; если метрика растёт линейно с числом уникальных запросов и никогда не уменьшается — это и есть причина. Решение — ограничить кэш по размеру и времени жизни записей (LRU с maxsize, TTL). Подводные камни Риски. Ищут исключительно циклические ссылки
garbage-collectionmemory-management
JuniorPython Developer > Основы Python > Функции и области видимости
Короткий ответ Функция не содержит инструкции return после цикла, поэтому она всегда неявно возвращает None, хотя внутри корректно строит список result — исправление: добавить явный return result после цикла. Как это работает подробнее Если функция доходит до конца тела без явного return value, Python автоматически завершает её, возвращая None. Это не вызывает ошибку интерпретатора — код "работает" в смысле не падает, но вызывающая сторона получает None вместо ожидаемого значения, и ошибка обнаруживается только там, где это None пытаются использовать как список. Пример кода Что использовать на практике Практика. Отлавливают такие баги через unit-тесты, проверяющие именно возвращаемое значение (assert result == [2, 4]), а не только отсутствие исключений. Также полезно включить проверку типов (type hints + статический анализатор типа mypy), который подскажет несоответствие аннотированного -> list[int] и фактического None в некоторых путях выполнения. Подводные камни Риски. Забывают return при рефакторинге, когд
debuggingfiltering
JuniorDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ `kubectl rollout history` показывает список предыдущих ревизий Deployment, а `kubectl rollout undo` откатывает Deployment к предыдущей (или указанной) ревизии, пересоздавая поды со старой версией образа. Как это работает подробнее Kubernetes Deployment хранит историю ревизий (ограниченную параметром `revisionHistoryLimit`). Каждая ревизия соответствует версии шаблона пода (образ, переменные окружения и т.д.). Команда `undo` запускает тот же механизм rolling update, но «в обратную сторону» — постепенно заменяет поды новой проблемной версии на поды из указанной ревизии. Пример кода Что использовать на практике На практике. откат через `kubectl rollout undo` быстрый и не требует пересборки образа, потому что использует уже существующий образ из реестра. Перед откатом полезно посмотреть `kubectl rollout history deployment/myapp` с `--revision=N`, чтобы убедиться, что откатываемся именно туда, куда нужно. Пример. Ожидаемое поведение: поды с `myapp:v1.5.0` постепенно заменяются на поды с `myapp:v1.4.
cicd-and-release-managementdevops
JuniorDevOps Engineer > Контейнеры и доставка > CI/CD и управление релизами
Короткий ответ Workflow запускается при push в любую ветку репозитория и при открытии/обновлении pull request в ветку `main`; при срабатывании он выполняет одну джобу `build`, которая скачивает код, устанавливает зависимости и запускает тесты на Ubuntu-раннере. Как это работает подробнее блок `on` определяет события-триггеры (`push`, `pull_request`), `jobs` описывает, какие задачи выполнять и на какой среде (`runs-on: ubuntu-latest`), а `steps` — последовательные шаги внутри джобы, включая готовые переиспользуемые actions (`actions/checkout`, `actions/setup-node`). Пример кода Что использовать на практике На практике. такой минимальный workflow — типичная отправная точка для CI: он не деплоит ничего, а только проверяет код. Для реального проекта к нему обычно добавляют кэширование зависимостей, линтер и отдельный workflow или джобу для деплоя, запускаемую по более узкому условию (например, только на `main`). Пример. Ожидаемое поведение: при любом push появляется новый workflow run на вкладке Actions; на вклад
artifactscicd-and-release-management