Цель этой статьи ― показать, как можно выполнять регуляторные требования по ИБ в средах контейнерной оркестрации, какие для этого есть подходы и инструменты.
Антон Гаврилов, руководитель направления DevSecOps Центра информационной безопасности компании «Инфосистемы Джет»
В качестве примера рассмотрим, как можно добиться выполнения стандарта ГОСТ Р 57580.1-2017 «Безопасность финансовых (банковских) операций. Защита информации финансовых организаций. Базовый набор организационных и технических мер». Мы выбрали этот ГОСТ, так как в нём содержится исчерпывающий список требований по ИБ (в том числе ― по повышению уровня ИБ виртуальных сред), которые в том или ином виде есть и в других стандартах. К тому же ГОСТ Р 57580.1-2017 актуален для финансовых организаций. А именно эти организации одними из первых начали использовать контейнеризацию, поэтому и выполнение требований регулятора в этой области может коснуться их в первую очередь.
Не стоит воспринимать эту статью как детальное руководство к действию. Во-первых, в разных организациях среды контейнерной оркестрации могут быть реализованы по-разному (отличаться могут оркестраторы и CNI, кто-то может использовать Service Mesh, кто-то ― нет, и т.д.). Во-вторых, нельзя создать универсальный для всех сред перечень мер по обеспечению безопасности: для каждой конкретной среды актуальным будет что-то своё. Поэтому в статье приведены примеры реализации определенных групп требований/мер и ссылки на дополнительные материалы, содержащие полезную информацию.
Статья состоит из следующих частей:
Контейнеры ― один из самых удобных способов упаковки программного обеспечения. Если упростить, то всё, что нужно для упаковки ― поместить в такой контейнер исходный код приложения, используемые зависимости и открыть необходимые порты. После этого использовать контейнер сможет любой, у кого есть Container Engine (например, Docker или CRI-O). При этом не нужно устанавливать интерпретаторы языков программирования, Java Runtime или другое «дополнительное» ПО, все это уже будет внутри контейнера.
С технической точки зрения, контейнер ― это виртуализация уровня операционной системы, которой не требуется гипервизор для работы. Контейнеры «легче» классических виртуальных машин. Хотя бы потому, что для контейнера не нужно устанавливать гостевую операционную систему.
Графически разница между «контейнеризацией» и «виртуализацией» представлена на рис. 11.
Рисунок 1: Общая разница между контейнеризацией и виртуализацией
Когда мы хотим «упаковать» приложение в контейнер, мы создаём образ этого контейнера. Образ (image) ― аналог шаблона виртуальной машины. Образ создается из Dockerfile ― конфигурационного файла, в котором мы описываем все необходимые параметры конфигурации (переменные окружения, порты, пользователей, установку и обновление пакетов, копирование файлов и т.д.). Пример образа приведен на рис. 2.
Рис. 2. Пример Dockerfile
Для того, чтобы выполнить централизованное хранение образов контейнеров, используются реестры. Грубо говоря, реестр представляет собой дерево папок. Кроме самих образов, в реестре хранятся и их более старые версии, к которым можно вернуться, если что-то пошло не по плану.
Обычно, если в организации используются контейнеры, рано или поздно встаёт вопрос о том, как ими эффективно управлять. Микросервисные архитектуры, постоянное наращивание функционала, запуск новых продуктов ― всё это ведёт к увеличению числа контейнеров, а значит, и к усложнению управления ими. Для преодоления «трудностей масштабирования» были созданы среды контейнерной оркестрации, которые еще называются оркестраторами (например, Kubernetes, Red Hat OpenShift, Rancher, VMware Tanzu, HashiCorp Nomad и т.д.). Они позволяют контролировать такие аспекты, как:
Далее мы будем рассматривать только один оркестратор ― Kubernetes ― без каких-либо дополнительных решений (например, без Service Mesh). Мы выбрали именно этот оркестратор по двум причинам.
Если упростить, то Kubernetes состоит из двух основных компонентов (каждый из которых также представляет из себя некий набор сервисов): Control Plane и Node Components. Как видно из названия, Control Plane отвечает за принятие решений и управление нагрузками кластера (например, scheduling, запуск новых pod2, миграция pod и т.д.). Node Components, в свою очередь, отвечает за запуск pod и их работоспособность на конкретной node.
Kubernetes устанавливается как кластер среды контейнерной оркестрации, представляющий из себя набор нод:
Node Components, в свою очередь, отвечают за запуск pod и их работоспособность на конкретной ноде кластера.
Общая схема кластера представлена на рис. 3
Рис. 3. Кластер среды контейнерной оркестрации, обобщенная схема
Общая схема кластера и развернутых на нем приложений будет выглядеть следующим образом (рис. 4):
Рис. 4. Кластер среды контейнерной оркестрации, расширенная схема
ГОСТ 57580.1-2017 устанавливает требования для следующих процессов (направлений) защиты информации:
Для того, чтобы выполнить регуляторные требования, необходимо провести подготовительную работу. Важно определить, какие меры нужно предпринять, чтобы обеспечить предусмотренный ГОСТ 57580.1-2017 уровень защиты. Также необходимо решить, какие их этих мер применимы к конкретной среде контейнерной оркестрации. После составления списка актуальных для организации мер важно определить их «точку приложения». Например, часть из них будет актуальна для нод, на которых установлен оркестратор, часть ― непосредственно для оркестратора, а часть ― для контейнеров.
Далее на примерах рассмотрим меры ГОСТ 57580.1-2017 и то, как их можно реализовать в среде контейнерной оркестрации.
Учетные записи (УЗ) в среде контейнерной оркестрации бывают нескольких типов: учетные записи субъектов (субъектами могут быть разработчики или эксплуатационный персонал) и сервисные учетные записи. Управление этими двумя типами УЗ осуществляется по-разному. Сервисные управляются средствами самого кластера, учетные записи субъектов (пользовательские) ― с использованием сторонних механизмов, файлов, X.509 сертификатов, посредством интеграции с внешними системами, например, LDAP (тут важно отметить, что интеграция Kubernetes с LDAP не является нативной, для её реализации потребуются дополнительные действия).
Что касается аутентификации пользователей, оптимальным способом управления паролями будет интеграция Kubernetes со службой каталогов (например, MS AD). В этом случае эксплуатационный персонал/разработчики будут использовать доменные учетные записи в соответствии с ролевой моделью на уровне кластера. А реализация требований ГОСТ 57580.1-2017 будет осуществляться на уровне MS AD.
Если говорить об аутентификации сервисных учетных записей, дело обстоит иначе. В Kubernetes можно создать объект Secret для хранения секретов (аутентификационных данных) в «закодированном» виде. Для создания таких объектов применяется base64. Поэтому хорошей практикой считается использование сторонней системы, которая будет управлять секретами, хранить их в зашифрованном виде и выдавать через REST-запросы. Примером таких систем могут быть HashiCorp Vault, CyberArk Conjur. При этом на уровне внешней системы могут задаваться ротация и требования к сервисным УЗ. А кластер и развернутые на нем приложения становятся «пользователями», которые обращаются за секретами во внешнюю систему и не хранят их локально.
Для корректной реализации принципа минимальных привилегий для доступа к кластеру можно воспользоваться механизмом RBAC (Role Based Access Control). Он позволяет настроить возможности пользователей и сервисов на основе ролевой модели как на уровне отдельно взятого пространства имен (namespace), так и на уровне кластера.
Создание ролей и последующее их распределение состоит из нескольких этапов:
Правильно выстроенная ролевая модель повысит общий уровень ИБ и может использоваться для реализации требований стандарта ГОСТ 57580.1-2017.
Важно помнить, что помимо создания ролей или контроля аутентификации/авторизации необходимо выстроить процессы регулярного пересмотра и контроля доступов. Например, важно постоянно проводить проверки, чтобы вовремя обнаруживать «мертвые учетные записи» или несвоевременный отзыв повышенных полномочий, которые были предоставлены пользователю/сервису временно для реализации определенной задачи. В качестве технической реализации для этого можно использовать либо встроенные механизмы Kubernetes, либо сторонние утилиты. Например, Open Source утилиту Kubi-Scan.
Управление сетевой безопасностью на уровне кластера среды контейнерной оркестрации незначительно отличается от управления сетевой безопасностью в целом.
Кластер важно разместить в безопасном сегменте сети, на границе которого нужно установить необходимые средства сетевой защиты, а доступ в интернет контролировать специализированными решениями. При этом нужно создать несколько окружений, например: Dev, Test, Prod. Количество окружений может быть разным в разных организациях. Рекомендуется использовать несколько кластеров: как минимум, отдельный кластер нужен будет для тестирования.
Оптимально ограничить возможность подключения к отдельным нодам напрямую и реализовать управление всем кластером через Master Node. Для взаимодействия компонентов Kubernetes, расположенных на Worker Node (например, kubelet, kube-proxy) с компонентами Master Node (например, kube-apiserver) можно использовать TLS, это повысит общий уровень защищенности кластера.
Ситуация несколько отличается, если посмотреть на сетевую безопасность на уровне оркестрации. По умолчанию в Kubernetes отсутствует какое-либо сегментирование, и любой pod может общаться с любым pod в любом namespace. Однако в Kubernetes можно реализовать Network Policy (сетевые политики), которые позволят реализовать достаточно гранулярное сегментирование сети. Главное ― при выборе Cluster Network Interface (CNI) убедитесь, что решение поддерживает такой функционал. К счастью, он есть у большинства представленных на рынке CNI (например, Calico, Cilium, Romana, Weave).
Кроме того, с помощью Network Policy можно контролировать Ingress (входящий трафик) и Egress (исходящий трафик) и реализовать подход «белого списка»: все, что не указано в Network Policies, по умолчанию будет считаться запрещенным.
Для того, чтобы подготовить Network Policy, которая не навредила бы работоспособности приложения, необходимо понять, как именно и с чем это приложение взаимодействует как внутри кластера, так и за его пределами. Такая информация, как правило, есть у разработчиков. Они могут помочь в составлении корректной модели сетевого взаимодействия приложения, на основе которой ИБ-специалисты подготовят Network Policy. Важно учитывать, что в работе приложений постоянно происходят изменения. Поэтому нужно чётко выстроить процесс актуализации Network Policy внутри организации и назначить ответственных за реализацию этого процесса.
Еще один способ обеспечить сетевую безопасность ― реализовать межсетевое экранирование между контейнерами. Для этого можно использовать внешние решения. Некоторые из таких решений позволяют использовать L3/L4 фильтрацию трафика при взаимодействии микросервисов приложений.
Дополнительно можно использовать Service Mesh (Istio, LinkerD), которые позволяют реализовать mTLS при взаимодействии между pods.
Рассмотрим ещё один, косвенный, способ сетевой защиты. По умолчанию Kubernetes выбирает, на какую node разместить pod/container в соответствии с внутренней логикой работы, явных ограничений/приоритетов нет (за исключением ограничения запуска контейнеров на Master Node, кроме системных). Однако есть возможности контроля запуска определенных pods/container на определенных node за счет NodeSelector, Taints/Tolerations и Affinity. Указанные способы явно не относятся к средствам контроля сетевого взаимодействия, но частично и их можно использовать, например, для выделения определенной node, на которой будут запускаться только критичные приложения.
Устранять уязвимости на нодах кластера можно в соответствии с выстроенным в компании процессом управления уязвимостями. По сути, ноды ― это обычные вычислительные мощности под управлением ОС семейства Linux. Это значит, что можно придерживаться стандартного подхода, то есть проводить сканирование, приоритизацию, постановку задач на устранение, тестирование обновлений, обновление.
То же самое может быть применимо и к оркестратору. Но стоит помнить, что Kubernetes обновляется на регулярной основе, в него постоянно добавляется новый функционал, исправляются недоработки. Поэтому будет особенно важно выстроить внутренний процесс по поддержке его актуальной версии.
Также важно отметить, что Kubernetes реализует концепт «неизменяемой инфраструктуры» (immutable infrastructure). Это означает, что любые изменения, которые совершались с pod/container напрямую, не будут сохранены в случае перезапуска контейнера. В случае перезапуска pod Kubernetes будет создавать новый pod/container на основе используемого в спецификации образа (image). Таким образом, единственный способ повлиять на конфигурацию pod/container ― модифицировать сам образ.
Контроль целостности образов по умолчанию в Kubernetes не реализован. Для решения этой задачи есть несколько подходов.
Таким образом создается «виртуальный» контроль целостности: образы сможет изменить только авторизированный пользователь, обладающий соответствующими правами. В примере, рассмотренном выше, таким пользователем является технологическая УЗ, которая используется в CI/CD-конвейере.
Можно комбинировать процессный и технический подходы к контролю целостности образов. Это позволит гарантировать, что «случайные» образы не будут использованы для запуска контейнеров.
Установка антивирусов ― не лучшая практика как с точки зрения нод, так и с точки зрения pod/container. Для нод ― антивирусы могут привести к нарушению в логике работы оркестратора, а в pod/container большинство «классических» решений попросту невозможно встроить.
Поэтому для защиты от вредоносного кода стоит использовать компенсирующие меры, применение которых допускается стандартом ГОСТ Р 57580.1-2017, например, SELinux и AppArmor (применительно к ОС семейства Linux). Однако стоит помнить, что SELinux/AppArmor не являются 100% заменой антивирусным решениям, так как не обладают функционалом идентификации вирусов и иного вредоносного ПО.
Обеспечить еще большую защиту на уровне pod/container можно с использованием Security Context3 . Security Context помогает проанализировать контейнеры и то, что они делают, для того, чтобы гранулярно дать им только те возможности и привилегии, которые им необходимы, и запретить все остальные. Благодаря такому подходу вирусы просто не могут осуществлять свои вредоносные действия.
С помощью Security Context можно реализовать:
Есть несколько вариантов формирования Security Context:
В дополнение к аналитике с использованием Security Context можно использовать внешние средства защиты информации. Во-первых, те, которые позволят автоматизировать процесс проверки настроек нод и pod/container на соответствие лучшим практикам (как правило, используются CIS Benchmarks). Во-вторых, те, которые помогают идентифицировать наличие вредоносных файлов, чтобы удалить их.
Такие средства защиты также позволяют обеспечить безопасность контейнеров в runtime, что не может быть сделано силами оркестратора. Большинство решений позволяет реализовать поведенческую аналитику и формировать правила контроля ИБ контейнеров на основании заранее разработанных моделей, которые описывают «нормальное поведение контейнера». Все, что будет отличаться от такой модели, будет расцениваться, как событие ИБ. А если выставить режим «enforce», любая «аномальная» активность будет заблокирована.
Kubernetes не предполагает каких-либо специальных возможностей/инструментов для контроля потенциальных каналов утечек.
Для многих таких каналов (например, электронная почта, машинные носители информации, внешние файлообменники) подход к защите не отличается от «классических» подходов, применяемых в организации.
На уровне нод процесс мониторинга ИБ аналогичен мониторингу ИБ классических элементов ИТ-инфраструктур: журналы нод просто перенаправляются в SIEM-систему для идентификации инцидентов.
Что касается уровня кластера, то для того, чтобы анализировать события, рекомендуется настроить Audit Policy (политику аудита). Эта политика позволяет «фильтровать» поток событий, который генерируется в кластере, чтобы идентифицировать подозрительные события, например:
Инструмент Audit Policy достаточно гибкий и может быть использован для фильтрации потока событий, который генерируется большим количеством сущностей Kubernetes. Эти события могут быть направлены в SIEM-систему и использоваться как для идентификации инцидентов ИБ, так и для проведения расследований. Для определения на уровне кластера перечня событий, которые необходимо передавать в SIEM, можно воспользоваться несколькими подходами:
В случае использования наложенных средств защиты рекомендуется направлять в SIEM-систему журналы о нарушении установленных политик безопасности, чтобы обогащать общую информацию о том, что происходит в кластере среды контейнерной оркестрации.
Кроме того, на рынке есть специализированные решения для идентификации инцидентов ИБ на основании анализа событий ИБ в кластере среды контейнерной оркестрации.
В настоящее время отсутствует позиция регуляторов, в том числе Банка России, относительно того, является ли контейнер виртуальной машиной или нет. Есть аргументы «за», есть аргументы «против».
Если допустить, что контейнер представляет собой виртуальную машину, то большинство требований ГОСТ Р 57580.1-2017 можно будет без труда выполнить. Давайте рассмотрим эти требования подробнее:
Главное отличие требований к защите контейнерной оркестрации в том, что среди них нет требований к защите гипервизора, так как он не используется.
В этой сфере ГОСТ Р 57580.1-2017 предусматривает меры, реализация которых не зависит от специфики сред контейнерной оркестрации. Поэтому эти меры могут быть реализованы в соответствии с общим подходом организации по управлению удаленным доступом и его защите при использовании мобильных (переносимых) устройств.
Если обобщить, то получается:
Табл. 1. Способы реализации мер Стандарта ГОСТ Р 57580.1-2017
Ниже приведены ссылки на упоминаемые в статье возможности Kubernetes, используемые для повышения уровня защищенности кластера, а также на материалы, подготовленные компанией Red Hat ― разработчика продукта OpenShift и одного из главных участников проекта Kubernetes:
1https://www.docker.com/resources/what-container
2Pod – базовый объект Kubernetes – группа из одного или нескольких контейнеров и совместно используемых ресурсов для этих контейнеров
3Security Context прописываются в YAML-конфигурацию pod’a приложения. Политики, позволяющие реализовать централизованное управление Security Context, были исключены из версии Kubernetes 1.21 (https://kubernetes.io/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/), однако в некоторых оркестраторах, например, RedHat OpenShift, они продолжают свое существование.
И мы тоже не спим, чтобы держать вас в курсе всех угроз