Чек-лист по безопасности контейнеров

Чек-лист по безопасности контейнеров


1. Отделили ли вы сборки от продуктового кластера?


Сначала вы наверняка будете создавать образы контейнеров при помощи того или иного конвейера CI/CD. Это может быть служба хостинга или, скорее, self-hosted-решение, если мы говорим о корпоративном Kubernetes. 


Если ваши сборки запускаются на тех же хостах, что и продакшен-приложения, то они используют одно и то же ядро. Иначе будет только в том случае, если вы используете какую-то виртуализацию. И хотя уязвимости в ядре, которые позволяют выйти за пределы контейнера, возникают редко, такой риск есть. Такая ситуация может в итоге привести к несанкционированному доступу к вашим приложениям в проде. 


Помните: если вы запустили Docker-файл, то в нем можно выполнять любой произвольный код. То есть любой, кто меняет код в ваших Docker-файлах, может запускать в них что угодно. Поэтому всегда проверяйте, что Docker-файлы может редактировать только команда, которой вы доверяете. Иначе есть риск, что кто-то воспользуется уязвимостью ядра и получит несанкционированный доступ к продакшен-приложениям.


2. Весь ли исполняемый код добавлен в образ контейнера на момент сборки? Вы относитесь к контейнерам как к неизменной субстанции? Сканируете их на уязвимости?


На этапе создания образа контейнера вы с помощью Build Step конвертируете Docker-файл в образ, который храните в реестре. В какой-то момент вы выполните развертывание и запустите его. 


Возьмите контейнер приложения, который нужно проверить на уязвимости, и воспользуйтесь подходящим сканером. Сканер можно запустить как часть этапа сборки, так же, как интеграционные тесты в конвейере сборки. И если уязвимости не обнаружены, то можно развертывать в облаке.


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


3. Отказались ли вы от флага privileged?


Мы часто считаем, что у статуса root есть все разрешения, а у непривилегированных пользователей — нет. Отчасти это верно, но разрешения root на самом деле делятся на фрагментарный набор правил, которые в Linux называются привилегиями.


При запуске контейнера от root вы получаете не все привилегии — большинству контейнеров они всё равно не нужны. Например, ему не нужно устанавливать модули ядра, менять системное время или модифицировать произвольные процессы. А запуская контейнер с флагом -privileged, вы даете ему эти, по факту, ненужные права.


Некоторые считают, что -privileged означает «я работаю от имени пользователя root». Но это не так: вы работаете от root по умолчанию, без флага. Он добавляет только то, что вам не нужно.


4. Устанавливаете ли вы на хосты актуальные обновления безопасности?


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


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


5. Шифруете ли вы хранящиеся и перемещаемые секреты?


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


Часто нужно, чтобы секреты были доступны только одному виду контейнеров, в которых запущен определенный микросервис или приложение. В этих случаях необходимо применять шифрование, чтобы контейнеры были недоступны для посторонних людей и приложений как при хранении, так и при перемещении в контейнер.


Важно помнить, что если вы не шифруете секреты, то по умолчанию они остаются незашифрованными, даже если вы используете Kubernetes со встроенной реализацией секретов.


6. Можете ли вы предотвратить смещение контейнера?


Работающий контейнер должен содержать только тот исполняемый код, который был добавлен в образ во время сборки. Добавлять исполняемый код в контейнер во время выполнения — плохая идея по многим причинам. Но главная проблема — всё, чего не было в образе контейнера в момент создания, не прошло тестирование и не было просканировано. 


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

Report Page