Что-то было модно, что-то вышло из моды, а что-то вечно и вечность в нашей статье — это кибербезопасность. В рамках серии статей хотелось бы поговорить об этом и поделиться нашим опытом.  Во второй части я продолжу рассказ про проект, с которым мы уже познакомились ранее.  Напомню про требования: Замкнутый контур; Отсутствие CVE во всех используемых продуктах; Контроль безопасности уже имеющейся инфраструктуры; Контроль доступа до среды; Автоматизация процессов. Но как быть, если ваша инфраструктура располагается в рамках kubernetes оркестратора? Как быть, если вы используете managed решение? Какие подходы для организации безопасности будут применимы? Под катом — про это, а еще про Managed Service for Kubernetes и Yandex Cloud, Kyverno, Tetragon, Falco и многое другое.  Давайте посмотрим, что было дальше?  Приглашаю вас подписаться на наш блог Хабр, TG-канал DevOps FM и познакомиться с YouTube — мы всегда рады новым друзьям :) В последний раз мы разработали инфраструктуру, которая отвечала основным требованиям заказчика на момент этапа развития его бизнеса. Трудозатраты на разворачивание такого проекта были сравнительно небольшими, но в скором времени встает	потребность в развитии своего продукта. В любом контексте развитие подразумевается не только как устранение текущих неисправностей или мелких релизов, но и кардинальные изменения исходного функционала продукта.  Можно продолжать бесконечно переписывать ваш монолит, добавляя новые релизы, но с увеличением штата разработчиков возникает проблема контроля этого процесса, а значит вам придётся отказаться от старого уклада и переходить на микросервисную архитектуру. В этот момент каждый DevOps задаётся сразу вопросом: А что же это означает для меня?   Если ранее весь процесс заключался в деплое landing, frontend и backend, то в потенциальном будущем количество контейнеров в инфраструктуре может превысить 20 штук и это мы говорим только о prod среде, но нам ведь будет необходимы как минимум dev и test среды приближенные к проду, а возможно и динамические окружения — как быть? Выслушав планы по развитию бизнеса и согласовав первые требования, встал вопрос о подготовке новой инфраструктуры для проекта. Первое что приходит на ум при описанных выше условиях — это оркестратор контейнеров. В нашем же случае было принято, что его функции будет выполнять kubernetes. Когда появляется необходимость в использовании kubernetes, нужно сделать нелёгкий выбор: использовать готовые managed решения, предоставляемые облаками, или самостоятельно развернуть кластер через kubespray на ранее созданных нодах. У каждого из таких решений есть свои плюсы и свои минусы.  Явными плюсами любого managed решения являются сниженные трудозатраты на поддержку и продукта, но не надо забывать, что это также свяжет ваши руки в дальнейшем администрировании. В этом случае теряется возможность гибкого контроля исходных версий пакетов и ОС ваших master и worker нод, ведь, как правило, все облачные решения не всегда успевают соответствовать тенденциям обновлений. Отмечу, что на текущем высококонкурентном рынке каждый пытается максимально закрыть все основные потребности пользователей и именно поэтому нужно лишь внимательно выбирать облако и изучать его roadmap по развитию. К плюсами self-hosted разворачивания K8S можно отнести полный контроль всего, что имеется, со стороны администратора, однако это приводит к увеличению трудозатрат. В каждом случае правильное решение выбирать вам и универсального ответа на вопрос “Что будет правильно?” здесь нет. Главное помнить — выбор зависит не только от требований со стороны Кибербезопасности, но и от потребностей тонкого тюнинга по оптимизации использования ресурсов, например таких как GPU. Зная все плюсы и минусы, для нас вопрос выбора в условиях работы проекта не стоял. Напомню исходные требования описанные ранее: Замкнутый контур; Отсутствие CVE во всех используемых продуктах; Контроль безопасности уже имеющейся инфраструктуры; Контроль доступа до среды; Автоматизация процессов. Так как раннее наша инфраструктура уже была в Yandex Cloud, то было решено использовать Managed Service for Kubernetes. Развернуть его весьма просто, если не забывать про главный подход, которого мы начали придерживаться ранее. IaC или по другому говоря Infrastructure-as-Code. В ходе дальнейшего нашего разворачивания необходимо использовать Terraform и Yandex предлагает замечательный провайдер для этих средств, как и весьма хорошую документацию к нему. Итоговый результат можно описать визуально следующим образом. Для обеспечения отказоустойчивости нам по-прежнему необходимы 3 подсети, в 3-х различных зонах доступности. Тут же появляется возможность создать node-pools, в которых можно заложить возможности увеличения инфраструктуры, например, на время роста входящего трафика. В случае, если будет необходимость увеличить ресурсы,то можно воспользоваться как горизонтальным масштабированием (увеличение количества серверов в каждом пуле), так и вертикальным масштабированием (изменением конфигурации сервера в большую сторону). Вслед за этим и первые изменения со стороны безопасности, которые требуют перекрытия порта API K8S открытого на локальном ip адресе, доступ к которому будет идти через наш ранее развернутый OpenVPN. Сам кластер развернут и находится в замкнутом контуре и здесь возникает вариативность хода выполнения работ —  если бы мы работали с self-hosted инфраструктурой, то нас бы ожидали дополнительные объемные работы по сканированию безопасности ОС серверов и конфигураций настроек кластера. Для данного процесса подходит ПО, о котором мы уже упоминали ранее в другой статье kube-hunter и kube-bench (ссылка на статью), но в managed решении мы лишены подобных возможностей.  Следующим немаловажным шагом является настройка привилегий и прав доступа для пространств наших будущих приложений и это является пожалуй одним из самых ответственных этапов. Ведь если контур является закрытым по внутренней сети, мы всё равно будем открывать по сетевому протоколу L7 трафик до наших микросервисов для доступа внешних пользователей. Итак нам нужно настроить деплой нашего микросервиса. Как правило любой pipeline содержит 3 стадии: Build Dockerfile нашего образа Тестирование пакетов и кода Деплой микросервиса в инфраструктуру. В текущем вопросе нас интересует последний пункт и если мы говорим про деплой в kubernetes, то мы приходим к Helm Chart-у. Для автоматизации и ускорения процесса деплоя можно либо написать свой кастомизированный вариант, либо воспользоваться готовым чартом с целью экономии трудозатрат на подготовительные работы. На наших проектах мы используем nxs-universal-chart.  Пройдёмся по основным пунктам безопасности манифестов инфраструктуры. 1. Использование RBAC (Role-based access control) и ServiceAccount Каждый pod в рамках нашей инфраструктуры должен быть запущен не из-под default сервисного аккаунта. Если вы располагаете в рамках одного namespace несколько приложений, то в случае проникновения в оболочку одного контейнера, в потенциальной перспективе злоумышленник сможет получить доступ до рядом развернутых контейнеров. Также важно помнить, что если сервисный аккаунт обладает чрезмерными привилегиями RBAC, то появляется возможность получения доступа до любых сущностей и компонентов кластера, таких как deployment, ingress, namespace и т.д. 2. Context Security. Если мы говорим про безопасную инфраструктуру, то и речи быть не может о запуске init процесса контейнера из под root пользователя. Отсюда следует вывод, что нам необходимо будет предоставить приложению права для работы с файлами внутри контейнера и для этого решения лучше всего подойдёт Context Security, который выставит как нужные права на группу файлов, так и нужного владельца. Для особых системных приложений нуждающихся в расширенных привилегиях, необходимо будет выставить привилегии в индивидуальном порядке: 3. Контроль на уровне сети. Чтобы ограничить предоставление сетевого доступа вашего запущенного пода к другому необходимо воспользоваться сетевыми политиками (Network Policy). Выдача подобных привилегий может происходить по ряду параметров: Разрешение доступа по namespace. Разрешение доступа до конкретных pods. Ограничение по подсети ip адресов. 4. mTLS-шифрование входящего трафика. Использование mTLS обеспечивает аутентификацию как клиента, так и сервера, устанавливая двустороннее TLS‑шифрование между ними. Это гарантирует, что и клиент, и сервер являются теми, за кого себя выдают, обеспечивая дополнительный уровень безопасности соединения. Реализация подобного механизма с лёгкостью описывается через ingress annotations и заранее заготовленный secret в рамках нужного namespace. После чего все запросы с клиента к серверу должны содержать сертификаты для корректной аутентификации в конечной точке. 5. Блокирование запуска неподписанных контейнеров или по другому говоря: Kyverno — автоматизированное решение для проверки образов контейнера и повышения безопасности платформ kubernetes. Основные плюсы в следующем: Простая установка через Helm. (Также имеется нативная установка чарта в рамках Yandex Cloud) Создание политики, как CRD (CustomResourceDefinition) и описание её через YAML. Политики Kyverno способны работать с сопоставлением, используя селекторы типа ресурса, имени и метки, чтобы инициировать такие действия, как изменение, генерация, проверки и верификация образа для подписи контейнеров и сертификации цепочки программного обеспечения. Наличие GUI Наличие внутреннего эскпортера позволяющего настроить с лёгкостью интеграцию с Prometheus-ом и производить в дальнейшем мониторинг статуса отчётов. Пройдёмся кратко по примеру работы с Kyverno: 5.1. Добавляем репозиторий Kyverno Helm и обновляем список репозиториев, после чего устанавливаем чарт в нужны namespace: 5.2. Устанавливаем политики Kyverno Теперь, когда Kyverno установлен, вы можете заняться установкой политик. При первой установке рекомендуется настроить их на работу в режиме «аудита», чтобы ни один из запросов на подключение к кластеру не был заблокирован. Вы можете узнать, настроена ли политика на “audit”, просто проверив свойство validationFailureAction в манифесте политики. К примеру данная политика проверяет, что все запускаемые образы в подах в рамках namespace prod при сборке были подписаны нашим приватным ключом. Важно заметить, что политики применяются образам контейнеров, которые были созданы после запуска Kyverno, а это значит, что процесс не касается всех ресурсов существующих до запуска Kyverno.   Для установки типовых политик используйте команду: Далее проверяем корректность применяемых манифестов установленных глобально на весь кластер: Ожидаемый результат вывода: Так и в рамках нашего репозитория. Ожидаемый результат вывода: 5.3. Просматриваем результаты отчётов о нарушениях политик. Просмотреть результаты отчётов можно либо в рамках конкретного namespace: Либо в глобальных отчётах кластера: Либо можно настроить весьма простой dashboard в Grafana на основе имеющихся весьма полных metric kyverno с последующем пушем алертов в случае возникновения статуса Fail в итоговом отчёте. Отлично, если ознакомление с базовыми аспектами безопасности на уровне манифестов закончено, то можно идти дальше. Описание безопасной инфраструктуры не говорит о безопасности системы. Всегда важно не забывать как про человеческий фактор, так и про нелегитимные действия. Именно поэтому контроль инфраструктуры во время выполнения процессов в реальном времени является важным аспектом общей стратегии кибербезопасности проекта, но не стоит забывать и про стандартный мониторинг состояния системы, который также реализуется через Zabbix или Prometheus, Alertmanager, Grafana. В облачных средах безопасность выполнения становится еще более важной, поскольку приложения и рабочие нагрузки часто распределяются по нескольким сервисам и платформам. Для этого может подойти ряд технологий, о которых поговорим дальше. Tetragon и Falco —  обе технологии у многих на слуху, когда речь идёт про Run Time Security, но мы нуждались в другом важном аспекте  — блокировке нелегитимных действий и если Falco в двух словах можно описать, как механизм для аудита инфраструктуры, то про Tetragon так сказать нельзя. Так как помимо обнаружения потенциальных «дыр в безопасности» он способен  произвести завершение процесса, зафиксировав за ним нелегитимную активность, которая попадает под описанные правила. Здесь остановлюсь чуть подробнее и пройдусь по ряду функций и параметров. Что нужно сделать в первую очередь? Оценка среды запуска микросервисов - это включает в себя рассмотрение версии ядра и архитектуры. Определите цели обнаружения угроз. Что нужно сделать во вторую очередь? Необходимо произвести инсталляцию самого Tetragon. Сделать это можно простым способом используя заранее готовый Helm Chart из общедоступного registry. Что нужно сделать в третью очередь? Tetragon не имеет GUI, которое бы с лёгкостью помогло интегрировать новый процесс, но как и в продукте выше у него имеются свои CRD, в рамках которых можно произвести описание интересующих нас политик. После чего оператор Tetragon обработает описанные сущности и поды самого Tetragon развернутые в качестве daemonset на каждой ноде выполнят и запишут в логи описанную информацию. Звучит неплохо, но что может мониторить Tetragon?   Мониторинг жизненного цикла процесса Мониторинг произведения действий чтения/изменения с файлами наблюдения. Мониторинг tcp соединений на уровне сети в кластере. Мониторинг произведения изменений (монтирование, создание файловой системы) в хостовой части системы. Мониторинг учётных данных процесса (UID/GID) Мониторинг capabilities предоставляемых процессу контейнера. В целом подобный скоуп тестов и возможных вариаций уверенно покрывает большую часть потребностей со стороны КБ, но самое главное позволяет реализовывать функционал реакции на возникновение события мониторинга. К примеру политика запрещает какому-либо файлу производить операцию чтения с файлами /etc/shadow, /etc/passwd: Не смотря на элегантность этого решения в концепции контроля запущенных процессов у технологии имеется как ряд плюсов, так и ряд минусов: Плюсы: Манифесты политик описанные в yaml имеют гибкую и понятную схему описания условий. Инструмент постоянно развивается и выходят обновления, как основного продукта, так и Helm Chart. Поды Tetragon имеют возможность отдавать встроенные метрики на внешний порт, что позволяет интегрировать весь этот процесс с Grafana и Prometheus, описав push уведомления на критические события. Поды Tetragon имеют цельные логи экспортируемые в /dev/stdout контейнера, которые описывают поведение всех процессов попадающих под политики. Всё это позволяет в дальнейшем экспортировать эту информацию в любую систему анализа и хранения данных. Минусы: Так как инструмент ещё развивается, то у него имеются проблема в изучении из-за нехватки целостной информации в документации. Также, что явно бросается в глаза - это не полнота текущих возможностей политик, для покрытия всех возможных элементов инфраструктуры. Явным примером является работа только с TCP соединениями в Network Policy на уровне  L4. Существует проблема регулирования политик. На данный момент исключение namespace, которые не будут подпадать под условия созданных правил описывается глобально на уровне Tetragon агентов, что ограничивает в гибкости выстраивания процессов. И так, теперь когда мы интегрировали несколько инструментов в нашу инфраструктуру, посмотрим, что из этого получается? Итоговая форма кластера приобрела следующий вид, согласно описанным требованиям. В общих словах можно сказать, что процесс по повышению безопасности ещё в самом разгаре и текущий стек технологий закрывает лишь малую часть из  планируемых требований, но всегда лучше показать, чем рассказать. Пройдёмся по требованиям? Замкнутый контур;Требование выполнено и выдержано согласно описанному ранее регламенту. Отсутствие CVE во всех используемых продуктах; Требование выполнено так как тесты, описанные в первой части статьи, остаются неизменными и возможны при любых дальнейших действиях. Контроль безопасности уже имеющейся инфраструктуры; Требование нельзя назвать выполненным до конца, так как остаются неучтенные моменты и в будущем возможно придется производить корректировку технологий в зависимости от масштабирование системы клиента на уровне ПО. Контроль доступа до среды; Задача была также успешно реализована через Freeipa и OpenVPN как и ранее, а часть функционала по распределению доступов относительно сущностей k8s прекрасно решается на уровне распределения ролей IAM в Yandex Cloud. Автоматизация процессов. Была реализована посредством изменения текущих pipeline-ов и применением IaC. Но получается это конец и продолжать нет смысла? Как бы это ни звучало, не думаю, что это конец. Всё меняется, всё развивается и всё прогрессирует, как и смысл фразы «Всё, что нас не убивает, делает нас сильнее». Если раньше эта суть повествования говорила о профессиональном и эмоциональном росте бизнеса, то в текущих реальностях все хотят избежать тех самых моментов, которые могут «убить». Доступность и безопасность вашего ПО говорит в первую очередь о возможных репутационных рисках. Работая с данными реальных пользователей, все задумываются лишь о том, как избежать утечки и не попасть в очередные новостные заголовки, получив для своего продукта чёрный пиар и статус компании с безответственным отношением к своим пользователям и их конфиденциальности. Именно поэтому работая в любом продукте, а особенно в крупных компаниях, когда ваш бизнес находится в активной стадии роста, нужно продолжать работать дальше. А что будет дальше вы узнаете в следующей части.  DevOps Engineer