Гайд · SDLC · Secure SDLC

Практический гайд по SDLC в реальной жизни: от хаоса к Secure SDLC

Жизненный цикл разработки без розовых очков: честный разговор про компромиссы, внедрение ИБ и невыдуманные истории


ОГЛАВЛЕНИЕ

  1. SDLC в идеальном мире и в реальности
  2. Сбор требований и threat modeling «на салфетке»
  3. Проектирование и архитектурные компромиссы
  4. Написание кода и code review в горящих спринтах
  5. Интеграция безопасности: SAST, SCA и борьба с ложными срабатываниями
  6. Тестирование: динамический анализ, пентесты, иллюзия полного покрытия
  7. Сборка, деплой и управление секретами
  8. Эксплуатация: observability и быстрый rollback
  9. Технический долг и переговоры с бизнесом
  10. Практический роадмап: с чего начать
  11. Заключение

1. SDLC В ИДЕАЛЬНОМ МИРЕ И В РЕАЛЬНОСТИ

SDLC (Software Development Life Cycle) — это последовательность этапов, через которые проходит программное обеспечение: планирование, анализ требований, проектирование, разработка, тестирование, развёртывание и поддержка. В учебниках это выглядит как красивая диаграмма с чёткими стрелками.

В реальности эти стрелки часто идут назад, разветвляются и пересекаются снова. Требования меняются на ходу, бизнес торопит, а «классический Scrum» превращается в постоянные авралы.

«Идеальной архитектуры не существует. Есть архитектура, которая адекватна требованиям прямо сейчас, и та, срок годности которой уже истёк.»

Почему идеал недостижим

  • Бизнес не всегда знает, чего хочет. Заказчик может сформулировать задачу разными способами на разных встречах.
  • Ресурсы ограничены. Идеальное тестирование и идеальное проектирование требуют времени, которого нет.
  • Легаси никуда не денешь. Даже новый функционал привязывается к существующим базам данных и API.
  • Люди устают и ошибаются. Дедлайны, контекст-переключения и нехватка сна влияют на качество.

Secure SDLC (SSDLC) добавляет к этому ещё один фактор: безопасность должна быть встроена в каждый этап. Это не значит, что мы делаем всё идеально. Это значит, что мы хотя бы понимаем, где и что можем проверить.

Моя история: «правильный» Scrum, который встал

Мы однажды попытались внедрить «канонический» Scrum с двухчасовыми планированиями, ретроспективами и строгими ролями. Через два месяца стало ясно: команда тратит 30–40 % времени на митинги, а задачи всё равно приходят извне спринта. Мы отказались от религии и перешли к прагматичному Kanban с минимальной церемонией. Релизы ускорились, а люди перестали ненавидеть процессы.

Вывод: процесс нужен не для галочки, а чтобы помогать делать работу. Если процесс тормозит — он неправильный.


2. Сбор требований и threat modeling «на салфетке»

На этом этапе формально происходит самое важное: понимание, что вообще нужно сделать. В реальности требования часто приходят в виде короткого письма, голосового сообщения или обсуждения в коридоре.

Что важно зафиксировать

  • Что делает пользователь? Какую проблему решает?
  • Кто ещё взаимодействует с системой? Админы, партнёры, интеграции.
  • Какие данные обрабатываются? Персональные данные, платежи, конфиденциальная информация.
  • Какие требования комплаенса применяются? 152-ФЗ, PCI DSS, GDPR и другие.
  • Что может пойти не так? Это и есть начало threat modeling.

Threat modeling без формализма

Моделирование угроз звучит страшно, но на практике часто сводится к вопросам:

  • Кто может получить доступ к чему не должен?
  • Где проходит граница доверия между системами?
  • Что случится, если этот API окажется публичным?
  • Какие данные мы храним, и что будет при их утечке?

Иногда для первого разбора достаточно нарисовать схему на доске или в ExcalDraw. Главное — зафиксать результат, иначе разговор забудется.

Моя история: ИБ-требования за два дня до дедлайна

Крупный релиз был запланирован на пятницу. В среду вечером пришло письмо от информационной безопасности: нужно добавить двухфакторную аутентификацию и строгие парольные политики для админов. Мы честно сказали, что за два дня это нереально. Релиз перенесли на три недели, а я неделю вспоминал, почему не стоит ждать ИБ до последнего момента.

С тех пор в список вопросов на старте любого проекта входит: «Что скажет ИБ и комплаенс?»

«Безопасность должна быть удобной. Если безопасный путь сложнее небезопасного — инженеры найдут способ его обойти.»


3. ПРОЕКТИРОВАНИЕ И АРХИТЕКТУРНЫЕ КОМПРОМИССЫ

Проектирование — этап, где принимаются самые дорогие решения. Переделать архитектуру в десять раз сложнее, чем переделать отдельный модуль.

Микросервисы vs монолит: мой опыт

Я видел, как команде навязали микросервисы, потому что «так делают в Netflix». Проблема была в том, что DevOps-культура отставала: деплой оставался наполовину ручным, логирование было фрагментарным, а отладка распределённых запросов превращалась в детектив. То, что должно было добавить гибкости, превратило обновление системы в многочасовое мероприятие.

После этого я придерживаюсь правила: микросервисы нужны не тогда, когда они модные, а тогда, когда команда готова к операционной сложности.

Что реально проверяю на этапе дизайна

  • Границы доверия: что видит пользователь, что видит админ, что доступно между сервисами.
  • Минимальные привилегии: каждый компонент должен иметь доступ только к тому, что ему нужно.
  • Откат: можем ли мы быстро откатить изменения, если что-то пойдёт не так.
  • Мониторинг: как мы поймём, что система работает неправильно.

Моя история: легаси, которое никто не осмеливался трогать

Однажды нам нужно было добавить новый тип заказа. Существующая схема базы данных была такой запутанной, что добавить новый статус означало изменить код в семи разных местах. Мы спроектировали «правильное» решение, но бизнес не дал время на рефакторинг. Пришлось делать компромисс: минимальные изменения в легаси + отдельный сервис для новой логики. Через полтора года мы всё равно рефакторили, но проект запустился в срок.

Вывод: хороший дизайн иногда уступает работающему компромиссу. Главное — понимать цену этого компромисса.


4. НАПИСАНИЕ КОДА И CODE REVIEW В ГОРЯЩИХ СПРИНТАХ

Этап разработки — где теория превращается в код. Здесь возникает большинство рутинных ошибок, и здесь же можно их поймать, если выстроить процессы.

Практики, которые реально работают

  • Фича-бранчи и merge/pull requests. Даже в небольшой команде это снижает риск сломать основную ветку.
  • Линтеры и форматтеры. Споры о табах и пробелах должны умереть автоматически.
  • Pre-commit хуки. Проверка секретов, линтинг, базовые тесты до попадания в репозиторий.
  • Code review. Не для поиска опечаток, а для проверки дизайна, логики и безопасности.

Психология code review

Code review может стать конфликтной зоной. Если ревьюер ведёт себя как прокурор, разработчик начинает воспринимать процесс как личную атаку. Важно:

  • Объяснять, почему что-то нужно изменить, а не просто требовать.
  • Разделять критику кода и критику человека.
  • Быть готовым уступить в вопросах стиля, если линтер уже настроен.
  • Не блокировать PR из-за мелочей, которые можно исправить отдельно.

Моя история: «потом отрефакторим, заливай так»

Конец спринта, фича горела. Со словами «потом отрефакторим, заливай так», мы пропустили ревью для куска кода, который казался «временным». Этот «временный» костыль просуществовал год, врос в ядро архитектуры и в итоге потребовал два месяца работы целой команды, чтобы его заменить.

Вывод: технический долг, который вы берёте сознательно, и технический долг, который вы берёте в панике, — это разные вещи. Первый можно контролировать, второй контролирует вас.


5. ИНТЕГРАЦИЯ БЕЗОПАСНОСТИ: SAST, SCA И БОРЬБА С ЛОЖНЫМИ СРАБАТЫВАНИЯМИ

Secure SDLC требует встраивать проверки безопасности в процесс разработки. Но важно делать это так, чтобы инструменты помогали, а не мешали.

SAST — статический анализ

SAST сканирует исходный код на наличие известных уязвимых паттернов: SQL-инъекций, XSS, небезопасных функций, жёстко закодированных секретов и т.д. Плюсы: находит проблемы рано, до запуска. Минусы: ложные срабатывания.

SCA — анализ зависимостей

SCA проверяет используемые библиотеки на наличие известных уязвимостей (CVE). Это одна из самых полезных автоматических проверок, потому что уязвимости в зависимостях встречаются постоянно.

Моя история: 1000 ложных срабатываний

Мы внедрили SAST в блокирующем режиме. Утром получили больше тысячи срабатываний на старом легаси-коде. Пайплайны встали, разработчики возненавидели безопасность, а я понял, что так делать нельзя.

После этого мы настроили политику:

  • Сканируем только изменения в новых merge requests.
  • Блокируем только категории Critical и High.
  • Ложные срабатывания помечаем и заносим в исключения.
  • Для легаси — отдельный план постепенного исправления.

Вывод: инструмент безопасности, который блокирует работу команды, будет отключён. Задача — сделать так, чтобы проверки помогали писать безопасный код, а не мешали.

Сравнение подходов к тестированию безопасности

Подход Что проверяет Когда применять Ограничения
SAST Исходный код На этапе разработки, в MR/PR Ложные срабатывания, не видит runtime-логики
DAST Работающее приложение На стейджинге, после деплоя Не видит кода, требует настроенного окружения
IAST Код во время выполнения В тестовом окружении Требует инструментирования, влияет на производительность
SCA Зависимости На любом этапе, идеально в CI Не находит логические ошибки
Penetration testing Реальные пути атаки Перед важными релизами, раз в год/квартал Дорого, результат зависит от исследователя

6. ТЕСТИРОВАНИЕ: ДИНАМИЧЕСКИЙ АНАЛИЗ, ПЕНТЕСТЫ, ИЛЛЮЗИЯ ПОЛНОГО ПОКРЫТИЯ

Тестирование — то, что первым выключается под дедлайн. Это ошибка, но понятная. Важно понимать, какие виды тестов дают какой эффект.

Пирамида тестирования

Внизу — много дешёвых и быстрых unit-тестов. В середине — интеграционные тесты. На вершине — ручные проверки и пентесты. Это не означает, что unit-тесты заменяют всё остальное. Каждый уровень отлавливает свои классы ошибок.

DAST и пентесты

DAST проверяет работающее приложение извне. Пентест — это ручной анализ с применением методологий (OWASP WSTG и других). Ни один инструмент не заменяет человека, который может найти логическую ошибку в бизнес-процессе.

Моя история: 100 % автотестов и падение на проде

Проект проходил 100 % автотестов. На проде он упал через несколько часов. Причина: тестировали на мокнутых данных, а реальная база вернула null в поле, которое по нашей логике всегда было обязательным. Интеграционные тесты с реальным окружением тогда были минимальны.

Вывод: автотесты не гарантируют отсутствие ошибок. Они гарантируют, что проверенные сценарии работают. Важно проверять граничные условия и реальные данные.


7. СБОРКА, ДЕПЛОЙ И УПРАВЛЕНИЕ СЕКРЕТАМИ

CI/CD — это не только автоматизация, но и точка, где можно поймать много проблем: от утечки секретов до нестабильного окружения.

Правила, которые я проверяю в каждом проекте

  • Секреты не в коде. .env в репозитории — недопустимое решение.
  • Секреты не в образах. Docker-образ должен быть воспроизводимым и не содержать ключей.
  • Используйте хранилища секретов. HashiCorp Vault, облачные секрет-менеджеры, или как минимум переменные окружения CI/CD.
  • Проверка секретов в pre-commit. gitleaks, trufflehog и аналоги спасают от случайных коммитов.
  • Immutable артефакты. Один артефакт проходит через тестирование и устанавливается на прод. Не собирайте отдельно для продакшена.

Моя история: токен в публичном репозитории

Junior-разработчик случайно закоммитил токен от облачного S3 вместе с конфигом в публичный репозиторий. Хорошо, что мы уже прикрутили gitleaks в pre-commit хук. Пайплайн упал, коммит не прошёл, токен пришлось отзывать и перевыпускать, но в прод ничего не попало.

Без этого хука история могла закончиться иначе: публичный доступ к хранилищу, утечка данных, объяснения перед заказчиком.

Пример простого CI-шага со сканированием

stages:
  - lint
  - test
  - security
  - deploy

security_scan:
  stage: security
  image: aquasec/trivy:latest
  script:
    - trivy fs --severity HIGH,CRITICAL .
  allow_failure: true

Этот шаг не блокирует деплой (allow_failure: true), но создаёт видимость проблем. Когда комма привыкнет к сканеру, можно перейти к блокирующей политике.


8. ЭКСПЛУАТАЦИЯ: OBSERVABILITY И БЫСТРЫЙ ROLLBACK

После деплоя начинается самое интересное. Даже идеально протестированная система может вести себя неожиданно в продакшене.

Что важно иметь

  • Структурированные логи. JSON с корреляционным ID, timestamp, уровнем серьёзности и контекстом.
  • Метрики. CPU, память, задержки, ошибки, бизнес-метрики.
  • Трейсы. Для распределённых систем — OpenTelemetry, Jaeger или аналоги.
  • Алерты. По критическим ошибкам и метрикам, а не по «всему».
  • Rollback. Возможность откатить изменения быстрее, чем искать причину.

Моя история: try-catch, который глушил ошибки

У нас пошли 500-е ошибки на проде. Мы пошли в Kibana — логов нет. Оказалось, в коде был глобальный try-catch, который перехватывал исключения и писал строку уровня INFO. Мы часами дебажили «методом пристального взгляда», пока не переписали слой логирования.

Вывод: плохо настроенная observability хуже её отсутствия, потому что создаёт ложное ощущение контроля.

Пример плохого логирования

# Плохо
try:
    process_order(order)
except Exception as e:
    logger.info("Что-то пошло не так")
# Хорошо
try:
    process_order(order)
except Exception as e:
    logger.error("order_processing_failed", extra={
        "order_id": order.id,
        "user_id": order.user_id,
        "error": str(e)
    }, exc_info=True)
    raise

9. ТЕХНИЧЕСКИЙ ДОЛГ И ПЕРЕГОВОРЫ С БИЗНЕСОМ

Технический долг неизбежен. Вопрос — как с ним работать.

Подходы, которые я использую

  • Квота на стабильность. 10–20 % времени команды на рефакторинг, обновление зависимостей, улучшение инфраструктуры.
  • Видимость долга. Публичный список технических долгов с оценкой риска и трудоёмкости.
  • Связь с бизнес-рисками. Долг продаётся не как «разработчики хотят красивый код», а как «если не сделать, через полгода эта фича будет работать в 10 раз медленнее».
  • Постепенное погашение. Не рефакторить всё сразу, а трогать затронутые участки по мере работы над фичами.

Моя история: VIP-клиент, которого мы почти потеряли

Продакт-оунер отказывался давать время на рефакторинг, требуя только бизнес-фичи. Одна из витрин грузилась около 15 секунд из-за неоптимальных SQL-запросов. Мы предупреждали, но приоритет был у новых функций. После того как один из крупных клиентов начал рассматривать альтернативы, бизнес выделил нам 20 % capacity на стабильность и производительность.

Вывод: бизнес понимает язык денег и рисков, а не абстрактных уязвимостей. Наша задача — переводить технические проблемы в эти категории.


10. ПРАКТИЧЕСКИЙ РОУДМАП: С ЧЕГО НАЧАТ

Если вы хотите улучшить SDLC/SSDLC, но не знаете, с чего начать, вот пошаговый план.

Этап 1. Гигиена (неделя 1–2)

  • Запретите коммиты в main/master напрямую.
  • Настройте линтер и форматтер.
  • Добавьте pre-commit хук для проверки секретов.
  • Зафиксируйте процесс code review.

Этап 2. Автоматизация (неделя 3–4)

  • Настройте CI/CD с тестами.
  • Добавьте SCA для зависимостей.
  • Настройте базовые алерты на ошибки.

Этап 3. Безопасность (месяц 2–3)

  • Внедрите SAST в неблокирующем режиме.
  • Добавьте DAST на стейджинг.
  • Проведите первое threat modeling для критичных фич.
  • Проверьте управление секретами.

Этап 4. Наблюдаемость (месяц 3–4)

  • Стандартизируйте формат логов.
  • Добавьте ключевые метрики и дашборды.
  • Настройте трейсинг для межсервисных запросов.

Этап 5. Культура (постоянно)

  • Регулярные ретроспективы.
  • Обучение команды безопасности.
  • Документирование архитектурных решений.
  • Постепенное снижение технического долга.

11. ЗАКЛЮЧЕНИЕ

SDLC и Secure SDLC — это не коробка, которую можно купить и установить. Это культура, которая выстраивается итеративно, с учётом специфики команды, бизнеса и легаси.

Я не видел идеальных процессов. Я видел процессы, которые работали, несмотря на компромиссы. Главное — понимать, где вы делаете эти компромиссы, и какую цену они могут стоить.

Пять выводов, с которыми я ухожу

  1. SSDLC — это культура, не продукт. Нельзя купить сканер уязвимостей и сказать «у нас теперь Secure SDLC». Нужно встраивать проверки в ежедневную работу.
  2. Shift-left работает, если не ломает процессы. Перенос проверок на ранние этапы помогает, только если разработчик получает быструю и понятную обратную связь.
  3. Гибкость важнее идеального плана. Ошибки неизбежны. Важно уметь быстро откатить изменения и найти проблему.
  4. Правило 80/20. Линтинг, SCA, pre-commit хуки и базовая observability дают 80 % пользы за 20 % усилий.
  5. Бизнес понимает язык рисков. Продавайте безопасность и технический долг через деньги, штрафы и потери клиентов, а не через CVE и абстрактные метрики.

Не стремитесь к идеальному SDLC. Стремитесь к такому процессу, который позволяет команде уверенно делать изменения, зная, что большинство проблем будет поймано до продакшена.

Удачи в построении.