TL;DR

Образ Docker содержит приложение и все его зависимости. Поскольку он также содержит многочисленные двоичные файлы и библиотеки ОС, важно убедиться, что в его корневой файловой системе нет уязвимостей - по крайней мере, нет критических или серьезных. Сканирование изображения в конвейере CI / CD может обеспечить этот дополнительный уровень безопасности.

Простой проект

В предыдущей статье я подробно описал, как настроить конвейер CI / CD для очень простого побочного проекта с использованием GitLab, Portainer и Docker Swarm.



В этом конвейере определены три этапа:

  • Первый запускает несколько тестов на коде Node.js.
  • Второй создает образ Docker и публикует его в реестре GitLab.
  • На последнем этапе новый образ развертывается в Docker Swarm с помощью функции веб-перехватчика Portainer.

TK * внутренности * Образ Docker, созданный во время процесса, основан на Nginx 1.14 и развертывается сразу же без какой-либо проверки его внутренностей. Это может быть опасно, поэтому давайте посмотрим, как мы можем это исправить.

Добавление этапа сканирования изображения в конвейер

Есть несколько решений для сканирования изображений; коммерческие и с открытым исходным кодом. В этой статье мы поговорим о Clair и clair-scanner; два инструмента с открытым исходным кодом.

Эта документация от GitLab содержит все инструкции по добавлению дополнительного этапа, посвященного сканированию изображений. По сути, он запускает сервер Clair, который предоставляет существующие CVE, а затем двоичный файл clair-scanner проверяет каждый слой изображения, созданного на предыдущем этапе конвейера.

Я добавил дополнительный контент в .gitlab-ci.yml файл проекта.

Примечание. Я внес лишь незначительные изменения в этап, определенный в документации, поэтому он соответствует версии моего бегуна GitLab (который необходим, когда дело касается загрузки artifact).

Добавив этот новый этап, давайте посмотрим, как он пойдет, запустив новый конвейер. На снимке экрана ниже показана часть результатов этого нового этапа image_sanning.

Вверху мы видим, что анализируется каждый слой изображения.

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



Возвращаясь к выходным данным GitLab, мы видим, что обнаружено 100 уязвимостей. Это много! Они опасны? Что ж, судя по некоторым записям в столбце Серьезность, критический / высокий, они могут быть.

У нас много уязвимостей… Что теперь?

Что ж, если вы не специалист по безопасности, скорее всего, эти уязвимости мало что вам скажут. Однако знание того, что в приложении есть уязвимости, может вызвать множество вопросов:

  • Можно ли запускать приложение как есть?
  • Какие уязвимости я могу игнорировать, а к каким отношусь серьезно?
  • Мое приложение не предназначено для пользователей, это должно быть безопасно для всех этих CVE, верно? Даже для критических?
  • Узнает ли мой начальник, если я просто проигнорирую все эти CVE?
  • Могу ли я сделать что-нибудь простое, чтобы снизить потенциальные риски?

В некоторых случаях на самом деле есть несколько простых шагов, которые могут очень помочь, как мы увидим ниже.

Сначала проверьте базовое изображение

В качестве примера я рассматриваю простой веб-сайт, опубликованный с официальным nginx:1.14 изображением - последней стабильной версией на момент написания этого сообщения. Поскольку Dockerfile использует многоступенчатую сборку, окончательный образ не содержит большого количества ненужных файлов Node.js, используемых для создания веб-ресурсов. Dockerfile следующий.

Многоступенчатая сборка уже является хорошей отправной точкой, поскольку помогает уменьшить поверхность атаки изображения. Но все же окончательный nginx:1.14 образ основан на Debian, поэтому давайте изменим его и вместо этого используем nginx:1.14-alpine.

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

Вторая часть нашего многоступенчатого файла Dockerfile теперь заменена следующей.

Давайте запустим новую сборку и посмотрим, как она пойдет.

Что ж, как видно на скриншоте выше, все прошло неплохо. На этапе сканирования теперь обнаружено… 0 уязвимостей!

Обновление: использование Aquasec Microscanner

Как отметил Лукаш Лах в ленте Twitter ниже, Aquasec предлагает собственный сканер CVE: Aqua Microscanner, и им очень легко пользоваться. Спасибо Łukasz!

Микросканер может сканировать изображение разными способами: во время создания изображения или после того, как оно было создано.

Сканирование при построении изображения

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

Две последние инструкции в этом Dockerfile посвящены сканированию:

  • Токен необходимо указать в инструкции по сборке (в официальной документации Aqua Microscanner подробно описано, как этот токен можно получить).
  • Двоичный файл микросканера загружается и запускается в файловой системе создаваемого изображения.

Здесь используются несколько дополнительных опций:

  • --html создает отчет о сканировании в формате html.
  • --continue-on-failure не возвращает код ошибки в случае обнаружения CVE и не останавливает конвейер инструмента CI.

Сканирование сразу после построения изображения

Это можно сделать, добавив Dockerfile, предназначенный для сканирования. Пример этого Dockerfile приведен ниже.

Инструкция FROM указывает имя изображения, которое будет сканироваться. Следующие 2 инструкции такие же, как и в первом подходе (сканирование при построении изображения).

Чтобы проиллюстрировать этот второй подход, мы добавим следующий шаг в наш конвейер CI.

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

Затем мы можем запустить новую сборку изображения, и Clair, и Microscanner будут сканировать изображение, как только оно будет построено.

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

Тут интересно: результаты сканирования разные. 4 CVE были обнаружены Clair, а 5 - с помощью Aqua Microscanner. Это показывает, что сканеры CVE не работают одинаково, например, они могут не работать с одной и той же версией базы данных CVE и могут работать не одинаково хорошо.

Примечание: чтобы упростить использование микросканера, мы можем использовать диспетчер клиентских плагинов Docker (CLIP).



Благодаря этому инструменту больше не нужно использовать специальный файл Docker для сканирования, так как его можно запустить с помощью простой команды «docker microscan» после установки подключаемого модуля microscan.

Резюме

Этот короткий пост иллюстрирует, что добавить простой этап сканирования изображения в существующий конвейер CI / CD не так уж и сложно. Это предоставляет дополнительную информацию, такую ​​как количество и идентификаторы уязвимостей, содержащихся в образе.

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