Автоматическое сканирование Docker-образа при загрузке
Примечание
Автоматическое сканирование Docker-образов на наличие уязвимостей при загрузке в Container Registry можно включить в настройках сканера уязвимостей без создания функций и триггеров Yandex Cloud Functions.
В этом руководстве вы создадите реестр Container Registry для хранения Docker-образа и настроите автоматическое сканирование на уязвимости, при загрузке образа в реестр. С помощью триггера Cloud Functions будут отслеживаться изменения в реестре и при загрузке Docker-образа в реестр, будет вызываться функция для запуска сканирования.
Чтобы настроить автоматическое сканирование Docker-образа при загрузке:
- Подготовьте облако к работе.
- Подготовьте окружение.
- Создайте функцию.
- Создайте триггер.
- Загрузите Docker-образ.
- Проверьте результат.
Если созданные ресурсы вам больше не нужны, удалите их.
Также инфраструктуру для автоматического сканирования Docker-образа при загрузке можно развернуть через Terraform с помощью готового файла конфигурации.
Перед началом работы
Зарегистрируйтесь в Yandex Cloud и создайте платежный аккаунт:
- Перейдите в консоль управления
, затем войдите в Yandex Cloud или зарегистрируйтесь. - На странице Yandex Cloud Billing
убедитесь, что у вас подключен платежный аккаунт, и он находится в статусеACTIVE
илиTRIAL_ACTIVE
. Если платежного аккаунта нет, создайте его.
Если у вас есть активный платежный аккаунт, вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура, на странице облака
Подробнее об облаках и каталогах.
Подготовьте окружение
Если у вас еще нет интерфейса командной строки Yandex Cloud, установите и инициализируйте его.
-
Установите
Docker. -
Создайте реестр для загрузки Docker-образа.
Консоль управленияCLITerraformAPI- В консоли управления
выберите каталог, в котором будет создан реестр. - В списке сервисов выберите Container Registry.
- Нажмите кнопку Создать реестр.
- Задайте имя реестра.
- Нажмите кнопку Создать реестр.
Выполните команду:
yc container registry create --name my-reg
Результат:
done id: crpd50616s9a******** folder_id: b1g88tflru0e******** name: my-reg status: ACTIVE created_at: "2019-01-09T14:34:06.601Z"
См. раздел Как создать инфраструктуру с помощью Terraform.
- В консоли управления
-
Создайте сервисный аккаунт с именем
scanner
и назначьте ему рольcontainer-registry.images.scanner
на каталог, в котором создали реестр.Консоль управленияCLITerraformAPI- В консоли управления
выберите каталог, в котором вы хотите создать сервисный аккаунт. - В верхней части экрана перейдите на вкладку Сервисные аккаунты.
- Нажмите кнопку Создать сервисный аккаунт.
- Введите имя сервисного аккаунта.
- Нажмите Добавить роль и выберите роль
container-registry.images.scanner
. - Нажмите кнопку Создать.
-
Создайте сервисный аккаунт:
yc iam service-account create --name service-acc
Результат:
id: ajelabcde12f******** folder_id: b0g12ga82bcv******** created_at: "2021-05-17T14:32:18.900092Z" name: service-acc
-
Назначьте роль сервисному аккаунту:
yc resource-manager folder add-access-binding <идентификатор_каталога> \ --role container-registry.images.scanner \ --subject serviceAccount:<идентификатор_сервисного_аккаунта>
См. раздел Как создать инфраструктуру с помощью Terraform.
Воспользуйтесь методами create для ресурса ServiceAccount и updateAccessBindings для ресурса Folder.
- В консоли управления
-
Аналогичным способом создайте сервисный аккаунт с именем
invoker
и назначьте ему рольfunctions.functionInvoker
на каталог, в котором создали реестр. -
Установите Docker.
Создайте функцию
Создайте функцию в сервисе Cloud Functions с именем scan-on-push
, которая будет запускать сканирование Docker-образа:
- В консоли управления
перейдите в каталог, в котором хотите создать функцию. - Выберите сервис Cloud Functions.
- Нажмите кнопку Создать функцию.
- Введите имя
scan-on-push
и описание функции. - Нажмите кнопку Создать.
- Перейдите в раздел Редактор и создайте версию функции:
- В блоке Код функции:
-
Выберите среду исполнения
Bash
и нажмите Продолжить. -
Выберите способ редактирования функции
Редактор кода
. -
В окне для редактирования функции нажмите Создать файл. В открывшемся окне введите имя файла
handler.sh
и нажмите Создать. -
Скопируйте в файл
handler.sh
следующий код:DATA=$(cat | jq -sr '.[0].messages[0].details') ID=$(echo $DATA | jq -r '.image_id') NAME=$(echo $DATA | jq -r '.repository_name') TAG=$(echo $DATA | jq -r '.tag') yc container image scan --id ${ID} --async 1>&2
-
Укажите точку входа —
handler.sh
.
-
- В блоке Параметры укажите:
- Таймаут, c –
60
. - Память –
128 МБ
. - Сервисный аккаунт –
scanner
.
- Таймаут, c –
- Нажмите кнопку Сохранить изменения.
- В блоке Код функции:
-
Создайте функцию с именем
scan-on-push
:yc serverless function create --name=scan-on-push
Результат:
id: d4ejb1799eko******** folder_id: aoek49ghmknn******** created_at: "2021-17-05T14:07:32.134Z" name: scan-on-push log_group_id: eolm8aoq9vcp******** http_invoke_url: https://functions.yandexcloud.net/d4ejb1799eko******** status: ACTIVE
-
Создайте файл
handler.sh
и скопируйте в него следующий код:DATA=$(cat | jq -sr '.[0].messages[0].details') ID=$(echo $DATA | jq -r '.image_id') NAME=$(echo $DATA | jq -r '.repository_name') TAG=$(echo $DATA | jq -r '.tag') yc container image scan --id ${ID} --async 1>&2
-
Создайте версию функции
scan-on-push
:yc serverless function version create \ --function-name=scan-on-push \ --runtime bash \ --entrypoint handler.sh \ --memory 128m \ --execution-timeout 60s \ --source-path handler.sh \ --service-account-id <идентификатор_сервисного_аккаунта>
Где:
--function-name
— имя функции, версию которой вы хотите создать.--runtime
— среда выполнения.--entrypoint
— точка входа, указывается в формате<имя_файла_с_функцией>.<имя_обработчика>
.--memory
— объем RAM.--execution-timeout
— максимальное время выполнения функции до таймаута.--source-path
— файл с кодом функции.--service-account-id
— идентификатор сервисного аккаунта.
Результат:
done (1s) id: d4egi3pmsd1q******** function_id: d4e275oj7jtp******** ... tags: - $latest log_group_id: ckg6nb0c7uf1********
См. раздел Как создать инфраструктуру с помощью Terraform.
Воспользуйтесь методами create и createVersion для ресурса Function.
Создайте триггер
Создайте триггер, который будет вызывать вашу функцию при создании тега](../concepts/docker-image.md#version) Docker-образа.
- В консоли управления
перейдите в каталог, в котором хотите создать триггер. - Выберите сервис Cloud Functions.
- Перейдите на вкладку Триггеры.
- Нажмите кнопку Создать триггер.
- В блоке Базовые параметры:
- Введите имя и описание триггера.
- В поле Тип выберите
Container Registry
.
- В блоке Настройки Container Registry:
- В поле Реестр выберите реестр, в который будете загружать Docker-образ.
- В поле Типы событий выберите событие
Создание тега Docker-образа
.
- В блоке Настройки функции:
- Выберите функцию
scan-on-push
. - Укажите тег версии функции
$latest
. - Укажите сервисный аккаунт
invoker
, от имени которого будет вызываться функция.
- Выберите функцию
- Нажмите кнопку Создать триггер.
Чтобы создать триггер, выполните команду:
yc serverless trigger create container-registry \
--name <имя_триггера> \
--registry-id <идентификатор_реестра> \
--events 'create-image-tag' \
--invoke-function-id <идентификатор_функции> \
--invoke-function-service-account-id <идентификатор_сервисного_аккаунта>
Где:
--name
— имя триггера.--registry-id
— идентификатор реестра, в который будете загружать Docker-образ.--events
— события, после наступления которых триггер запускается.--invoke-function-id
— идентификатор функции.--invoke-function-service-account-id
— идентификатор сервисного аккаунта с правами на вызов функции.
Результат:
id: a1spt834cjmk********
folder_id: b1g86q4m5vej********
created_at: "2021-05-18T20:42:54.898949653Z"
...
function_tag: $latest
service_account_id: aje1insoe23e********
status: ACTIVE
Загрузите Docker-образ
-
Запустите Docker Desktop.
-
Аутентифицируйтесь в реестре от своего имени:
С помощью Docker Credential helperС помощью OAuth-токенаС помощью Yandex Identity and Access Management-токена-
Сконфигурируйте Docker для использования
docker-credential-yc
:yc container registry configure-docker
Результат:
Credential helper is configured in '/home/<user>/.docker/config.json'
Настройки сохраняются в профиле текущего пользователя.
Важно
Credential helper работает только при использовании Docker без
sudo
. О том, как настроить запуск Docker от имени текущего пользователя без использованияsudo
читайте в официальной документации Docker . -
Проверьте, что Docker сконфигурирован.
В конфигурационном файле
/home/<user>/.docker/config.json
должна появиться строка:"cr.yandex": "yc"
-
Docker готов к использованию, например, для загрузки Docker-образов. При этом выполнять команду
docker login
не надо.
-
Если у вас еще нет OAuth-токена, получите его по ссылке
. -
Выполните команду:
echo <OAuth-токен> | docker login --username oauth --password-stdin cr.yandex
Результат:
Login Succeeded
Примечание
У IAM-токена короткое время жизни — не больше 12 часов. Поэтому такой способ подойдет для приложений, которые будут запрашивать IAM-токен автоматически.
-
Выполните команду:
yc iam create-token | docker login --username iam --password-stdin cr.yandex
Результат:
Login Succeeded
-
-
Скачайте Docker-образ с Docker Hub
:docker pull ubuntu:20.04
Результат:
20.04: Pulling from library/ubuntu Digest: sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88******** Status: Image is up to date for ubuntu:20.04 docker.io/library/ubuntu:20.04
-
Присвойте тег Docker-образу:
docker tag ubuntu:20.04 cr.yandex/<идентификатор_реестра>/ubuntu:20.04
-
Загрузите Docker-образ в Container Registry:
docker push cr.yandex/<идентификатор_реестра>/ubuntu:20.04
Результат:
The push refers to repository [cr.yandex/crpu20rpdc2f********/ubuntu] 2f140462f3bc: Layer already exists 63c99163f472: Layer already exists ccdbb80308cc: Layer already exists 20.04: digest: sha256:86ac87f73641c920fb42cc9612d4fb57b5626b56ea2a19b894d0673f******** size: 943
Проверьте результат
-
Просмотрите логи функции
scan-on-push
и убедитесь, что она выполнилась.Консоль управленияCLI- В консоли управления
выберите сервис Cloud Functions. - Перейдите в раздел Функции и выберите функцию
scan-on-push
. - В открывшемся окне перейдите в раздел Логи и укажите период. По умолчанию задан период за 1 час.
Чтобы узнать имя или уникальный идентификатор функции, получите список функций в каталоге.
Посмотрите журнал выполнения функции:
yc serverless function logs scan-on-push
Результат:
2021-05-18 09:27:43 START RequestID: 34dc9533-ed6e-4468-b9f2-2aa0******** Version: b09i2s85a0c1******** 2021-05-18 09:27:43 END RequestID: 34dc9533-ed6e-4468-b9f2-2aa0******** 2021-05-18 09:27:43 REPORT RequestID: 34dc9533-ed6e-4468-b9f2-2aa0******** Duration: 538.610 ms Billed Duration: 538.700 ms Memory Size: 128 MB Max Memory Used: 13 MB 2021-05-18 09:29:25 START RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f******** Version: b09i2s85a0c1******** 2021-05-18 09:29:26 END RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f******** 2021-05-18 09:29:26 REPORT RequestID: 5b6a3779-dcc8-44ec-8ee2-2e7f******** Duration: 554.904 ms Billed Duration: 555.000 ms Memory Size: 128 MB Max Memory Used: 13 MB ...
- В консоли управления
-
Проверьте, что при загрузке Docker-образа запустилось новое сканирование.
Консоль управленияCLI- В консоли управления
выберите каталог, которому принадлежит реестр, содержащий Docker-образ. - Выберите сервис Container Registry.
- Выберите реестр, в который загрузили Docker-образ.
- Откройте репозиторий, в котором находится Docker-образ.
- Выберите нужный Docker-образ и проверьте значение параметра Дата последнего сканирования.
Чтобы посмотреть запуски сканирования по Docker-образу, выполните команду:
yc container image list-scan-results --repository-name=<идентификатор_реестра>/<имя_Docker-образа>
Результат:
+----------------------+----------------------+---------------------+--------+--------------------------------+ | ID | IMAGE | SCANNED AT | STATUS | VULNERABILITIES | +----------------------+----------------------+---------------------+--------+--------------------------------+ | crpu20rpdc2f******** | crpqmsqp5mtb******** | 2021-05-18 14:34:02 | READY | medium:6, low:13, negligible:3 | +----------------------+----------------------+---------------------+--------+--------------------------------+
- В консоли управления
Как удалить созданные ресурсы
Чтобы перестать платить за созданные ресурсы:
- Удалите Docker-образ, который хранится в Yandex Container Solution и реестр.
- Удалите функцию Cloud Functions.
- Удалите триггер Cloud Functions.
Как создать инфраструктуру с помощью Terraform
Terraform
Подробную информацию о ресурсах провайдера смотрите в документации на сайте Terraform
При изменении файлов конфигураций Terraform автоматически определяет, какая часть вашей конфигурации уже развернута, что следует добавить или удалить.
Чтобы настроить автоматическое сканирование Docker-образа при загрузке с помощью Terraform:
-
Укажите источник для установки провайдера Yandex Cloud (раздел Настройте провайдер, шаг 1).
-
Подготовьте файлы с описанием инфраструктуры:
Готовый архивВручную- Создайте папку для файлов.
- Скачайте архив
(2 КБ). - Разархивируйте архив в папку. В результате в ней должны появиться конфигурационный файл
image-auto-scan.tf
, файл с пользовательскими даннымиimage-auto-scan.auto.tfvars
и zip-архив с кодом функцииfunction.zip
.
-
Создайте папку для конфигурационных файлов.
-
Создайте в папке конфигурационный файл
image-auto-scan.tf
:image-auto-scan.tf# Объявление переменных для пользовательских параметров variable "zone" { type = string } variable "folder_id" { type = string } # Добавление прочих переменных locals { sa_scanner_name = "scanner" sa_invoker_name = "invoker" registry_name = "my-registry" function_name = "scan-on-push" } # Настройка провайдера terraform { required_providers { yandex = { source = "yandex-cloud/yandex" version = ">= 0.47.0" } } } provider "yandex" { folder_id = var.folder_id } # Создание сервисных аккаунтов resource "yandex_iam_service_account" "scanner" { name = local.sa_scanner_name description = "SA for Container Registry" folder_id = var.folder_id } resource "yandex_iam_service_account" "invoker" { name = local.sa_invoker_name description = "SA for Cloud Functions" folder_id = var.folder_id } # Назначение ролей сервисным аккаунтам resource "yandex_resourcemanager_folder_iam_member" "sa-role-scanner" { folder_id = var.folder_id role = "container-registry.images.scanner" member = "serviceAccount:${yandex_iam_service_account.scanner.id}" } resource "yandex_resourcemanager_folder_iam_member" "sa-role-invoker" { folder_id = var.folder_id role = "functions.functionInvoker" member = "serviceAccount:${yandex_iam_service_account.invoker.id}" } # Создание реестра Container Registry resource "yandex_container_registry" "my-reg" { name = local.registry_name folder_id = var.folder_id } # Создание функции resource "yandex_function" "test-function" { name = local.function_name user_hash = "my-first-function" runtime = "bash" entrypoint = "handler.sh" memory = "128" execution_timeout = "60" service_account_id = yandex_iam_service_account.scanner.id content { zip_filename = "function.zip" } }
-
Создайте файл с пользовательскими данными
image-auto-scan.auto.tfvars
:image-auto-scan.auto.tfvarszone = "<зона_доступности>" folder_id = "<идентификатор_каталога>"
-
Подготовьте zip-архив с кодом функции.
-
Создайте файл
handler.sh
и скопируйте в него следующий код:handler.shВажно
Если вы создаете файл в Windows, убедитесь, что переносы строк имеют формат Unix:
\n
, а не\r\n
. Заменить переносы можно в текстовом редакторе, например Notepad++ , или с помощью утилиты dos2unix или Tofrodos .DATA=$(cat | jq -sr '.[0].messages[0].details') ID=$(echo $DATA | jq -r '.image_id') NAME=$(echo $DATA | jq -r '.repository_name') TAG=$(echo $DATA | jq -r '.tag') yc container image scan --id ${ID} --async 1>&2
-
Создайте zip-архив
function.zip
с файломhandler.sh
.
-
Более подробную информацию о параметрах используемых ресурсов в Terraform см. в документации провайдера:
-
В файле
image-auto-scan.auto.tfvars
задайте пользовательские параметры:zone
— зона доступности, в которой будет создана инфраструктура.folder_id
— идентификатор каталога, в котором будет создана инфраструктура.
-
Создайте ресурсы:
-
В терминале перейдите в папку, где вы отредактировали конфигурационный файл.
-
Проверьте корректность конфигурационного файла с помощью команды:
terraform validate
Если конфигурация является корректной, появится сообщение:
Success! The configuration is valid.
-
Выполните команду:
terraform plan
В терминале будет выведен список ресурсов с параметрами. На этом этапе изменения не будут внесены. Если в конфигурации есть ошибки, Terraform на них укажет.
-
Примените изменения конфигурации:
terraform apply
-
Подтвердите изменения: введите в терминале слово
yes
и нажмите Enter.
-