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

Оглавление

· 1. Что такое Dockerfile?
· 2. Используйте инструкцию USER
· 3. Использовать минимальный базовый образ Dockerfile
· 4. Используйте минимум портов
· 5. Используйте надежные и безопасные базовые образы
5.1. Проверка на наличие уязвимостей
5.2. Использовать подписанные изображения
· 6. Используйте линтер
· 7. Избегайте использования последних тегов
· 8. Групповые инструкции RUN, COPY и ADD
· 9. Многоэтажное строительство
· 10. Избегайте включения секретов или учетных данных
· 11. Используйте .dockerignore
· 12. Заключение
· Литература

1. Что такое Dockerfile?

Dockerfile в самых прискорбных терминах — это текстовый файл, содержащий необходимые команды, которые будут использоваться для создания образа Docker. Если вы не знакомы с образом Docker, я настоятельно рекомендую начать знакомство с контейнером с некоторой документации Docker. С учетом сказанного, что делает файл докеров? Что ж, dockerfile позволяет пользователям автоматизировать процесс сборки своих образов контейнеров повторяемым и согласованным образом без необходимости вручную выполнять каждую команду, что является большим бонусом. Итак, теперь, когда вы знаете, что такое dockerfile, следующие разделы познакомят вас с рекомендациями по безопасности при его написании.

2. Используйте инструкцию пользователя

Чтобы гарантировать, что контейнеры не запускаются от имени пользователя root, по возможности следует использовать инструкцию USER. Отказ от использования root поможет предотвратить атаки с повышением привилегий хоста, которые могут нанести ущерб безопасности системы. Чтобы помочь пользователям с этой задачей, некоторые образы включают встроенного пользователя. Например, Node.js включает своего пользователя узла, как показано ниже.

USER node

Если встроенный пользователь не нужен, его следует удалить. Используя тот же пример Node.js, что и выше, это можно сделать, добавив следующее в Dockerfile.

# For debian based images use:
RUN userdel -r node
# For alpine based images use:
RUN deluser --remove-home node

3. Используйте минимальный базовый образ Dockerfile

Образы должны быть минимальными и включать только необходимые пакеты для успешного запуска приложения. При этом поверхность атаки будет значительно уменьшена за счет удаления ненужных и потенциально уязвимых пакетов. Чтобы помочь разработчикам в этом, несколько источников разработали базовые образы, которые включают только самое необходимое. Distroless и Alpine — два наиболее распространенных и рекомендуемых базовых образа для создания минимальных контейнеров.

4. Используйте минимум портов

Помимо использования минимального количества образов, должны быть открыты только необходимые порты. Использование инструкции EXPOSE поможет пользователям указать, какие порты должны быть опубликованы. Однако важно отметить, что инструкция EXPOSE предназначена исключительно для комментариев и/или документации. Следовательно, это не предотвратит раскрытие дополнительных портов во время выполнения.

EXPOSE 80/tcp

5. Используйте надежные и безопасные базовые образы

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

5.1. Проверка на уязвимости

PS user> docker scan node:14
\ Analyzing container dependencies for node:14
\ Querying vulnerabilities database...
...
Package manager:   deb
Project name:      docker-image|node
Docker image:      node:14
Platform:          linux/amd64
Tested 413 dependencies for known vulnerabilities, found 548 vulnerabilities.

5.2. Используйте подписанные изображения

Образы Docker перед использованием должны быть подписаны из надежного источника. Один из способов убедиться, что используются только подписанные образы, — применить доверие к содержимому Docker. На клиенте его можно применить для каждого сеанса с помощью следующей команды.

$ export DOCKER_CONTENT_TRUST=1

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

$ docker pull node:14
No valid trust data for 14

Чтобы проверить уже загруженные образы, Docker предлагает команду docker trust inspect, как показано ниже.

PS user> docker trust inspect --pretty node:14
No signatures for node:14
Administrative keys for node:14
  Repository Key:       d3a0845e6d36c6c058ae6d2bc718b32ead4b51f2a6fa81b341ba2df72f1823c9
  Root Key:     be46625d7c6a0afe24bbbce6a92114d691e32ae921cf14f3feb2f970e7a77337

6. Используйте линтер

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

Рисунок 1

Пример хадолинта

7. Избегайте использования последнего тега

Как видно из раздела 1.4. Используйте линтер, Хадолинт рекомендует избегать использования последнего тега в Dockerfiles. Пользователям следует избегать использования последнего тега из-за возможности нарушения функциональности или внесения неизвестных данных в среду в будущем при обновлении образа. Вместо использования последнего тега пользователи должны указать явный тег выпуска.

FROM node:14

8. Групповые инструкции RUN, COPY и ADD

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

9. Многоэтапное строительство

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

Например, пользователь может захотеть иметь этап, который использует инструменты сборки, но не предъявлять требований к этим инструментам сборки в конечном образе. При многоступенчатом построении они начинали стадию с инструкции FROM «base_image» как «name_of_stage1», а затем копировали результат этой стадии в следующую стадию FROM, используя инструкцию COPY –from=»name_of_stage1». См. следующий Dockerfile для примера использования Node:10 в качестве среды сборки, а затем Google Distroless Node:10 для окончательного образа.

FROM node:10 as build-env
COPY ./app
WORKDIR /app
RUN npm ci --only=production
FROM gcr.io/distroless/nodejs:10
COPY --from=build-env /app /app
WORKDIR /app
CMD ["app.js"]

10. Избегайте включения секретов или учетных данных

Docker использует кэширование слоев, что, по сути, означает, что все слои по-прежнему присутствуют в конечном образе. Некоторые команды, такие как история докеров, покажут слои, присутствующие в изображении, и то, как они были построены. См. рисунок 2 ниже для примера использования Node:14.

docker history node:14

Рисунок 2

История Docker для Node:14

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

Вместо этого пользователям следует использовать такие инструменты, как Docker BuildKit с параметром командной строки –secret для передачи необходимой секретной информации.

Например, в Dockerfile пользователь может получить доступ к секрету с помощью команды RUN, как показано ниже.

RUN --mount=type=secret,id=secret cat /run/secrets/secret

Во время сборки секрет будет передаваться через флаг –secret.

docker build --no-cache --progress=plain --secret id=secret,src=secret.txt .

11. Используйте .dockerignore

Файл .dockerignore похож на .gitignore, с помощью которого разработчики могут указать файлы или каталоги, которые следует исключить из контекста сборки, тем самым предотвращая их включение в окончательный образ. Файлы .dockerignore особенно полезны для явного исключения конфиденциальных файлов и каталогов, таких как файлы учетных данных, резервные копии, журналы и т. д. В приведенном ниже примере гарантируется, что папка .git, папка журналов и все файлы, заканчивающиеся расширением .md, за исключением файла README.md, будут исключены из контекста сборки. Дополнительную информацию см. в Документации Docker по .dockerignore.

.git
logs
*.md
!README.md

12. Заключение

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

Рекомендации

Центр интернет-безопасности. (н.д.). Тестовые тесты Docker в СНГ. https://www.cisecurity.org/benchmark/docker/.

Докер. (н.д.-а). Рекомендации по написанию файлов Docker. https://docs.docker.com/develop/develop-images/dockerfile_best-practices/.

Докер. (nd-b). Создавайте образы с помощью BuildKit. https://docs.docker.com/develop/develop-images/build_enhancements/.

Докер. (nd-c). Доверие к содержимому в Docker https://docs.docker.com/engine/security/trust/.

Докер. (н.д.-г.). Сканирование уязвимостей для локальных образов Docker https://docs.docker.com/engine/scan/.

Гартманн, Д. (10 июля 2018 г.). Быстрые победы для защиты контейнеров Docker. https://www.equalexperts.com/blog/tech-focus/quick-wins-to-secure-your-docker-containers/.

GoogleContainerTools. (2020, 28 июля). Репозиторий GitHub.

https://github.com/GoogleContainerTools/distroless/blob/main/examples/nodejs/Dockerfile.

Ирадьер, А. (2021, 9 марта). 20 лучших рекомендаций по Dockerfile. https://sysdig.com/blog/docker-file-best-practices/.

узлы. (2020, 2 ноября). Рекомендации по использованию Docker и Node.js. https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md.

Готовы вывести свои навыки кибербезопасности на новый уровень? Подписывайтесь на меня, чтобы узнавать о передовых методах и рекомендациях по последним отраслевым стандартам.

Из статей Infosec: Каждый день в Infosec появляется много информации, за которой трудно уследить. Подпишитесь на нашу еженедельную рассылку, чтобы БЕСПЛАТНО получать все последние тенденции в области информационной безопасности в виде 5 статей, 4 тем, 3 видео, 2 репозиториев и инструментов GitHub и 1 оповещения о вакансиях!