Практический гайд по SDLC в реальной жизни: от хаоса к Secure SDLC
Жизненный цикл разработки без розовых очков: честный разговор про компромиссы, внедрение ИБ и невыдуманные истории
ОГЛАВЛЕНИЕ
- SDLC в идеальном мире и в реальности
- Сбор требований и threat modeling «на салфетке»
- Проектирование и архитектурные компромиссы
- Написание кода и code review в горящих спринтах
- Интеграция безопасности: SAST, SCA и борьба с ложными срабатываниями
- Тестирование: динамический анализ, пентесты, иллюзия полного покрытия
- Сборка, деплой и управление секретами
- Эксплуатация: observability и быстрый rollback
- Технический долг и переговоры с бизнесом
- Практический роадмап: с чего начать
- Заключение
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 — это не коробка, которую можно купить и установить. Это культура, которая выстраивается итеративно, с учётом специфики команды, бизнеса и легаси.
Я не видел идеальных процессов. Я видел процессы, которые работали, несмотря на компромиссы. Главное — понимать, где вы делаете эти компромиссы, и какую цену они могут стоить.
Пять выводов, с которыми я ухожу
- SSDLC — это культура, не продукт. Нельзя купить сканер уязвимостей и сказать «у нас теперь Secure SDLC». Нужно встраивать проверки в ежедневную работу.
- Shift-left работает, если не ломает процессы. Перенос проверок на ранние этапы помогает, только если разработчик получает быструю и понятную обратную связь.
- Гибкость важнее идеального плана. Ошибки неизбежны. Важно уметь быстро откатить изменения и найти проблему.
- Правило 80/20. Линтинг, SCA, pre-commit хуки и базовая observability дают 80 % пользы за 20 % усилий.
- Бизнес понимает язык рисков. Продавайте безопасность и технический долг через деньги, штрафы и потери клиентов, а не через CVE и абстрактные метрики.
Не стремитесь к идеальному SDLC. Стремитесь к такому процессу, который позволяет команде уверенно делать изменения, зная, что большинство проблем будет поймано до продакшена.
Удачи в построении.