Стадия жизненного цикла модуля: Общедоступная версия

У модуля есть требования для установки

В кластере Deckhouse Platform (DP) сканирование на уязвимости выполняется с помощью Trivy Operator. Он генерирует Software Bill of Materials (SBOM) для рабочих нагрузок в неймспейсах с лейблом security-scanning.deckhouse.io/enabled и сканирует их на уязвимости. Если такого лейбла нет ни у одного неймспейса, сканируется неймспейс default.

Поддерживаемые типы объектов для сканирования

Сканирование поддерживается для следующих типов объектов:

  • образы контейнеров, размещённые в реестре;
  • файловые системы узлов кластера.

Архитектура анализа

Независимо от типа объекта сканирование состоит из следующих этапов:

Этап Описание
1. Сканирование Сканер обходит целевой объект и применяет анализаторы для извлечения установленных пакетов, манифестов зависимостей и конфигурационных файлов, формируя SBOM
2. Фильтрация Собранные данные сопоставляются с базами данных уязвимостей и политиками. Применяются фильтры по серьёзности, статусу исправления и типу пакетных зависимостей
3. Отчёт Результаты сохраняются в VulnerabilityReport в неймспейсе целевого объекта. При сканировании файловых систем узлов отчёт сохраняется в NodeVulnerabilityReport, а при сканировании реестров — в RegistryImageVulnerabilityReport; оба являются cluster-wide-ресурсами

Механизм сканирования уязвимостей

Сканер уязвимостей является центральным компонентом Trivy: он выявляет известные уязвимости на основе специализированных баз данных. Модуль operator-trivy сканирует пакеты и компоненты операционной системы (исполняемые файлы, библиотеки) и зависимости приложений (библиотеки, модули и прочие зависимости).

Оператор автоматически запускает сканирование при обнаружении новых или изменённых рабочих нагрузок в неймспейсах с лейблом security-scanning.deckhouse.io/enabled. Отчёты пересоздаются, когда их возраст превышает scanPeriods.workloadRescanPeriod (по умолчанию 24h). Установите параметр в "", чтобы отключить периодическое повторное сканирование.

Пакеты операционной системы

Сканер определяет дистрибутив ОС объекта и сопоставляет его пакеты с базой уязвимостей этого дистрибутива. Источники данных описаны в разделе «Источники данных об уязвимостях».

Зависимости приложений

В образах контейнеров сканер находит зависимости приложений по метаданным установленных пакетов и по исполняемым файлам. Lock-файлы и манифесты сборки, например package-lock.json, requirements.txt или pom.xml, в образах не анализируются. Для каждой экосистемы сканер использует специализированные базы уязвимостей, преимущественно GitLab Advisory Database и GitHub Advisory Database.

Анализируются следующие файлы:

Язык / экосистема Анализируемые файлы
Node.js Файлы package.json установленных пакетов (node_modules)
Python Метаданные установленных пакетов egg и wheel (*.egg-info, *.egg, *.dist-info/METADATA)
Java *.jar, *.war, *.par, *.ear
Go Исполняемые файлы Go
.NET (NuGet) packages.lock.json, packages.config, *.deps.json, Directory.Packages.props, Packages.props
Ruby (RubyGems) Файлы *.gemspec установленных gem-пакетов
PHP (Composer) installed.json
Rust (Cargo) Cargo.lock, исполняемые файлы, собранные с помощью cargo-auditable
Julia Manifest.toml

Результаты сканирования и ресурс VulnerabilityReport

Результаты сканирования уязвимостей сохраняются в кластере в объектах VulnerabilityReport группы trivy.deckhouse.io (aquasecurity.github.io, если параметр securityStorageForReports равен false). Каждый отчёт создаётся в неймспейсе рабочей нагрузки и именуется по схеме <KIND>-<WORKLOAD_NAME>-<CONTAINER_NAME>, где <KIND> — вид рабочей нагрузки в нижнем регистре. Отчёт содержит перечень обнаруженных уязвимостей с указанием серьёзности, статуса исправления, затронутого пакета и ссылок на источники.

Отчёт привязывается к родительскому объекту через поле ownerReferences. При обновлении образа или удалении рабочей нагрузки устаревший VulnerabilityReport удаляется механизмом сборки мусора Kubernetes и при необходимости пересоздаётся.

По умолчанию в отчёт попадают все уровни критичности. Параметр severities оставляет в отчёте только выбранные уровни. Дополнительные поля из базы уязвимостей добавляются параметром additionalVulnerabilityReportFields. Чтобы скопировать лейблы сканируемой нагрузки на отчёт, используйте reportResourceLabels.

Метрики динамики уязвимостей

Модуль записывает в Prometheus агрегированные ряды по уязвимостям. По ним Deckhouse Console строит графики динамики уязвимостей. Ряды рассчитываются из метрики оператора trivy_vulnerability_id, поэтому охватывают неймспейсы, в которых включено сканирование образов.

Доступны следующие ряды:

  • trivy:workload_vulnerabilities:count — количество уникальных уязвимостей контроллера, с лейблами namespace, controller_kind, controller_name и severity;
  • trivy:workload_vulnerability_id:present — идентификаторы уязвимостей, присутствующих в контроллере, с лейблами namespace, controller_kind, controller_name, severity и vuln_id; значение всегда равно 1.

Уязвимость учитывается один раз для каждого контроллера, сколько бы его контейнеров, образов или пакетов её ни содержало. Если пакеты дают ей разный уровень критичности, в рядах остаётся наивысший; пустой уровень записывается как Unknown. Остальные ряды семейства trivy:workload_ — промежуточные.

Отчёт Deployment относится к его ReplicaSet, который меняется при каждой выкатке. Ряды сопоставляют ReplicaSet с его Deployment по метрике kube_replicaset_owner, поэтому у Deployment остаётся одна история для всех ревизий.

Отчёт удаляется, когда становится старше scanPeriods.workloadRescanPeriod, и отсутствует до повторного сканирования нагрузки. В большом кластере повторное сканирование занимает часы, поэтому, пока у нагрузки нет отчёта, ряды сохраняют уязвимости её последнего отчёта в течение шести часов. Без этого каждое повторное сканирование выглядело бы как исправление и последующее появление уязвимостей. Перерыв дольше шести часов, например при повторяющейся ошибке сканирования, по-прежнему выглядит так же. Окно проверяется для нагрузки целиком, а не для отдельного контейнера. Если у одного контейнера нагрузки отчёт есть, а у другого нет, уязвимости второго контейнера отсутствуют в рядах до его повторного сканирования. Все контейнеры нагрузки сканирует одно задание, поэтому срок их отчётов обычно истекает одновременно.

Окно действует, только пока у нагрузки нет отчёта, поэтому ряды следуют за самой нагрузкой:

  • как только отчёт есть, ряды содержат ровно его уязвимости: обновление образа, VEX-заявление или обновление базы уязвимостей меняют их сразу, а отчёт без уязвимостей очищает их;
  • удалённая нагрузка уходит из рядов в течение десяти минут, когда kube-state-metrics перестаёт её описывать;
  • Deployment учитывает только текущую ревизию — ReplicaSet, который работал последним: пока идёт выкатка или откат, работают обе ревизии и учитываются обе; предыдущая ревизия уходит из рядов, как только её ReplicaSet уменьшен до нуля реплик, даже если её отчёт пережил выкатку;
  • Deployment, уменьшенный до нуля реплик, сохраняет уязвимости текущей ревизии, пока её отчёт не истечёт через scanPeriods.workloadRescanPeriod, и ещё шесть часов: оператор не сканирует повторно ReplicaSet без подов.

Следующий запрос возвращает количество критических уязвимостей в неймспейсе:

sum(trivy:workload_vulnerabilities:count{namespace="<NAMESPACE>", severity="Critical"})

Следующий запрос возвращает уязвимости, которые есть в контроллере сейчас и которых не было семь дней назад:

trivy:workload_vulnerability_id:present{namespace="<NAMESPACE>", controller_kind="<KIND>", controller_name="<NAME>"}
  unless trivy:workload_vulnerability_id:present{namespace="<NAMESPACE>", controller_kind="<KIND>", controller_name="<NAME>"} offset 7d

У рядов есть лейбл job="operator-trivy", поэтому их забирает и longterm Prometheus. Каждый Prometheus хранит историю в течение своего срока хранения: основной — по умолчанию 15 дней, longterm — дольше.

Генерация и обработка SBOM

Сгенерированный SBOM сохраняется в кластере в объекте SbomReport той же группы. Каждый отчёт создаётся в неймспейсе рабочей нагрузки и содержит:

  • метаданные контейнерного образа (репозиторий, тег, дайджест);
  • компонентный состав в формате CycloneDX (пакеты ОС и зависимости приложений с идентификаторами PURL, лицензиями и информацией о поставщике);
  • граф зависимостей между компонентами;
  • сводку по количеству компонентов и зависимостей.

Оператор отслеживает рабочие нагрузки в кластере. При создании или изменении рабочей нагрузки автоматически запускается задание сканирования, по результатам которого одновременно формируются SbomReport и VulnerabilityReport. Оба отчёта именуются по схеме <KIND>-<WORKLOAD_NAME>-<CONTAINER_NAME> и привязываются к родительскому объекту через поле ownerReferences. При удалении рабочей нагрузки отчёты удаляются автоматически через механизм сборки мусора Kubernetes.

SbomReport и VulnerabilityReport дополняют друг друга: VulnerabilityReport содержит выявленные уязвимости, а SbomReport фиксирует полный состав компонентов образа.

Чтобы отключить генерацию SBOM, установите disableSBOMGeneration в true. При включении этого параметра существующие объекты SbomReport однократно удаляются из кластера.

Сканирование узлов

Модуль может сканировать хостовую файловую систему каждого узла Kubernetes на уязвимости в пакетах ОС и, при необходимости, на секреты в файлах узла. Результаты сохраняются в объектах NodeVulnerabilityReport (cluster-wide-ресурс).

Функция по умолчанию отключена. Включите её в ModuleConfig operator-trivy:

spec:
  settings:
    nodeScanning:
      enabled: true

Сканирование узлов задаётся параметром nodeScanning:

Параметр По умолчанию Описание
enabled false Включить сканирование файловой системы узлов
scanners ["Vuln"] Сканеры: Vuln (поиск CVE) и Secret (учётные данные в файлах узла)
pkgTypes ["OS"] Типы пакетов: OS (rpm, deb, apk) и Library (библиотеки приложений на узле)
skipDirs Пути контейнерных runtime и виртуальных ФС Директории, которые пропускаются при сканировании
timeout 5m Тайм-аут заданий сканирования узлов
concurrentLimit 1 Максимальное число одновременных заданий сканирования узлов
nodeSelector Все узлы Сканировать только узлы с указанными лейблами
severities ["CRITICAL", "HIGH"] Уровни критичности, которые попадают в отчёт
hideUnfixedCVEs false Включать в отчёт только уязвимости, для которых есть исправление
resources Запросы 100m/256Mi, лимиты 1/2Gi Ресурсы заданий сканирования узлов; каждое незаданное поле сохраняет значение по умолчанию

Пример конфигурации:

spec:
  settings:
    nodeScanning:
      enabled: true
      scanners:
        - Vuln
      pkgTypes:
        - OS
      severities:
        - CRITICAL
        - HIGH
      concurrentLimit: 1

Уровни LOW и MEDIUM могут на порядок увеличить объём отчётов.

Ресурсы заданий сканирования узлов

Каждый узел сканирует задание scan-noderootfs-*, которое запускается на этом же узле. Его запросы и лимиты задаются параметром nodeScanning.resources, каждое незаданное поле сохраняет значение по умолчанию: запросы 100m/256Mi и лимиты 1/2Gi.

Значения, не соответствующие потребностям сканирования, влияют на него следующим образом:

  • Лимит памяти. Сканирование всей файловой системы узла может занимать до 2 ГиБ памяти. Задание, превысившее лимит, завершается с причиной OOMKilled, и ресурс NodeVulnerabilityReport для узла не создаётся. Меньший лимит не уменьшает объём памяти, нужный сканированию, поэтому каждая попытка завершается так же.
  • Лимит CPU. Меньший лимит замедляет сканирование, но не прерывает его. Задание останавливается с причиной DeadlineExceeded, если работает дольше nodeScanning.timeout. Если параметр не задан, действует таймаут заданий сканирования 5m. Вместе с низким лимитом CPU увеличьте и таймаут.
  • Запросы. Задание привязано к своему узлу, поэтому планировщик его не размещает: kubelet узла принимает задание, если запросы помещаются в свободные выделяемые ресурсы узла. Если запрос не помещается, задание завершается с причиной OutOfmemory или OutOfcpu. При маленьком запросе задание запустится и на узле, где свободной памяти меньше, чем нужно сканированию.

Если запрос по умолчанию больше заданного лимита, он уменьшается до лимита. ModuleConfig, в котором явно заданный запрос больше лимита — заданного или по умолчанию, — не сохраняется. Проверяется только изменение nodeScanning.resources, поэтому ModuleConfig, сохранённый с такими значениями раньше, принимает другие изменения. Например, requests.memory: 3Gi без limits.memory отклоняется, потому что лимит по умолчанию — 2Gi.

Чтобы не сканировать узлы, на которых столько памяти нет, отметьте подходящие узлы лейблом и укажите его в nodeSelector:

spec:
  settings:
    nodeScanning:
      enabled: true
      nodeSelector:
        <LABEL_KEY>: "<LABEL_VALUE>"
      resources:
        limits:
          memory: 3Gi

Сканируются только узлы с лейблом <LABEL_KEY>: <LABEL_VALUE>, и каждое задание может использовать до 3 ГиБ памяти.

Неудачное сканирование узлов

Сканирование узла, завершившееся без отчёта, повторяется через пять минут. После трёх неудачных попыток подряд оператор прекращает сканировать узел, и срабатывает алерт NodeVulnerabilityScanFailed. В алерте указаны узел и причина последней неудачи, например OOMKilled, DeadlineExceeded, OutOfmemory или JobRejected (API-сервер или политика admission отклонили задание сканирования). Недоступность API-сервера или admission-вебхука попытки не расходует: такие ошибки оператор повторяет сам. Задание сканирования, отклонённое admission-вебхуком, например движком политик кластера, считается неудачей JobRejected, но оператор продолжает повторять его каждые пять минут и после третьей попытки. Алерт срабатывает, пока длится отказ, и перестаёт срабатывать, как только вебхук пропускает задание.

Оператор хранит счётчик попыток в памяти и сбрасывает его в следующих случаях:

  • оператор перезапускается, например после изменения nodeScanning или другой настройки, которую он читает;
  • аннотация повторного сканирования узла получает новое значение;
  • для узла создаётся отчёт.

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

d8 k annotate node <NODE_NAME> trivy-operator.aquasecurity.github.io/node-rootfs-scan="$(date +%s)" --overwrite

Узел получает три новые попытки, а алерт перестаёт срабатывать.

Сканирование реестров

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

Включите функцию в ModuleConfig operator-trivy:

spec:
  settings:
    registryScanning:
      enabled: true
      concurrentScans: 5

Параметр registryScanning.concurrentScans ограничивает число одновременных сканирований образов по всем целям. Значение по умолчанию — 5.

Настройка сканирования репозиториев в реестрах

Цель сканирования описывается объектом RegistryScanTarget (cluster-wide-ресурс):

apiVersion: deckhouse.io/v1alpha1
kind: RegistryScanTarget
metadata:
  name: preprod-myapp
spec:
  registry: preprod.registry.example.com
  repositories:
    - myapp/backend
    - myapp/frontend
  rescanPeriod: 1d
  # Необязательно. Сканировать только теги, соответствующие регулярному выражению.
  tagFilter: "^v[0-9]+"
  # Необязательно. Сканировать не более 50 тегов на репозиторий (по умолчанию 100).
  maxTags: 50
  # Необязательно. Учётные данные для приватного реестра.
  registrySecretRef:
    name: image-pull-credentials-secret
    namespace: myapp
Поле Обязательное Описание
registry Да Хост реестра (например, registry.example.com).
repositories Нет Список путей репозиториев для сканирования. Не указывайте параметр или укажите пустой список, чтобы просканировать все репозитории, которые реестр отдаёт через catalog API.
rescanPeriod Да Период повторного сканирования каждого тега образа. Допустимые значения: 12h, 1d, 2d, 7d.
tagFilter Нет Регулярное выражение. Сканируются только теги, совпадающие с шаблоном.
maxTags Нет Максимальное количество тегов на репозиторий после фильтрации. По умолчанию: 100. Выбираются первые N тегов в лексикографическом порядке.
maxRepositories Нет Максимальное количество репозиториев, получаемых из каталога, если параметр repositories пуст. По умолчанию: 100. Выбираются первые N репозиториев в лексикографическом порядке, отчёты по остальным сохраняются.
registrySecretRef Нет Ссылка на секрет типа kubernetes.io/dockerconfigjson с учётными данными реестра.
insecure Нет Разрешает использовать HTTP или отключает проверку TLS для данного реестра.

Если реестр требует CA-сертификат, отсутствующий в системном хранилище доверенных сертификатов, добавьте его с помощью параметра additionalRegistryCA.

Результаты сканирования

Результаты сохраняются в объектах RegistryImageVulnerabilityReport (cluster-wide-ресурс), по одному на каждый сканируемый тег образа. Каждый отчёт принадлежит своему RegistryScanTarget. При удалении RegistryScanTarget связанные с ним отчёты автоматически удаляются механизмом сборки мусора Kubernetes.

Чтобы получить список всех отчётов, выполните:

d8 k get registryimagevulnerabilityreport

Чтобы просмотреть конкретный отчёт, выполните:

d8 k describe registryimagevulnerabilityreport <REPORT_NAME>

Вместо <REPORT_NAME> укажите имя отчёта из списка.

Отчёт хранится в etcd, поэтому его размер ограничен. Если отчёт образа превышает 1 МиБ, сканер удаляет из него данные в следующем порядке, пока отчёт не поместится:

  1. Удаляются списки links, поле primaryLink сохраняется.
  2. Удаляются описания уязвимостей.
  3. Удаляются векторы CVSS, поле score сохраняется.
  4. Удаляются уязвимости самых низких уровней критичности.

Счётчики summary всегда описывают полный результат сканирования. Аннотация отчёта registry-scanner.deckhouse.io/trimmed перечисляет удалённые данные, например links,description или links,description,cvss,vulnerabilities=1200/3400.

Отчёт пересоздаётся по истечении периода, заданного параметром rescanPeriod. Чтобы запустить внеплановое сканирование, удалите аннотацию registry-scanner.deckhouse.io/last-scan-time у RegistryScanTarget. Контроллер сразу запускает новый цикл сканирования, не дожидаясь следующего запуска по расписанию.

Сканер запускает цикл раньше этого периода в следующих случаях:

  • изменилась спецификация RegistryScanTarget — добавленный репозиторий или исправленный фильтр тегов сканируются сразу;
  • предыдущий цикл завершился до начала сканирования, например из-за некорректного регулярного выражения в фильтре тегов, — повтор через пять минут;
  • предыдущий цикл просканировал только часть образов — повтор через час, а пока ошибка сохраняется, интервал растёт до периода, заданного параметром rescanPeriod.

Первый цикл после запуска компонента ожидает загрузки индексной базы Java. До её завершения цель, которая ещё ни разу не сканировалась, сообщает состояние Ready=False с причиной WaitingForJavaDB, а цель с прошлым результатом сохраняет его.

Состояние сканирования

Статус RegistryScanTarget показывает время последнего цикла и его результат.

Чтобы получить список объектов RegistryScanTarget, выполните:

d8 k get registryscantarget

Чтобы просмотреть статус одного из них, например my-registry, выполните:

d8 k describe registryscantarget my-registry

Условие Ready появляется при запуске первого цикла цели или раньше, с причиной WaitingForJavaDB, пока загружается индексная база Java. Оно принимает значение True после успешного завершения цикла и False во всех остальных состояниях. Различить состояния позволяет поле reason:

Причина Значение Следующий цикл
ScanCompleted Все выбранные образы просканированы. Через период, заданный параметром rescanPeriod.
ScanInProgress Цикл выполняется или был прерван перезапуском. Через период, заданный параметром rescanPeriod, от последнего завершённого цикла.
ScanFailed Часть репозиториев не прочитана или часть образов не просканирована. Они перечислены в сообщении. Через час, далее с увеличением интервала, пока ошибка сохраняется, но не реже периода, заданного параметром rescanPeriod. Повтор пересканирует цель целиком.
DiscoveryFailed Цикл прекращён до начала сканирования: некорректный tagFilter, нечитаемый секрет с учётными данными или каталог, который реестр не отдал. Через пять минут.
WaitingForJavaDB Индексная база Java ещё загружается. Цель с прошлым результатом сохраняет его, пока загрузка коротка, и сообщает об ожидании, когда оно превысит 15 минут. В течение 30 секунд после готовности базы.

Пока загружается индексная база Java, не сканируется ни одна цель. До завершения загрузки компонент сообщает о неготовности, поэтому при остановке циклов проверяйте готовность его пода.

Если задан параметр tagFilter, в поле status.targets перечисляются совпавшие теги не более чем 50 репозиториев.

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

Отчёты без лейбла registry-scanner.deckhouse.io/target удаляет первый цикл, который прочитал все репозитории своей цели и просканировал все её образы. Цель, у которой каталог постоянно длиннее maxRepositories или всегда есть репозиторий, который не удаётся прочитать, или образ, который не удаётся просканировать, сохраняет их, пока это не изменится; об этом сообщает её условие Ready. Репозиторий, вернувший пустой список тегов, уборку не задерживает: пустой список — это полный ответ.

Отчёты удаляются, когда образ выходит из цели: тег удалён из репозитория или репозиторий больше не выбран. Сохраняются следующие отчёты:

  • отчёты репозитория, который цикл не смог прочитать: репозиторий ответил ошибкой, реестр не отдал список тегов целиком или репозиторий не попал в лимит maxRepositories. Репозиторий, список тегов которого пришёл частично, сканируется в пределах показанного, а число таких репозиториев указывается в условии Ready;
  • отчёты репозитория, вернувшего пустой список тегов. Они сохраняются, пока репозиторий не выйдет из цели.

Теги за пределом maxTags исключены осознанно, поэтому их отчёты удаляются.

Запрет запуска уязвимых контейнеров

Для работы механизма должен быть включён модуль admission-policy-engine (включён по умолчанию в наборах модулей Default и Managed).

Модуль реализует принудительный контроль над запуском контейнеров с уязвимыми образами на уровне admission-контроля Kubernetes. Механизм основан на связке OPA Gatekeeper (модуль admission-policy-engine) и Trivy: Trivy предоставляет результаты сканирования, а Gatekeeper принимает решение о допуске объекта.

Ограничение применяется при создании и изменении Pod, Deployment, StatefulSet и DaemonSet в неймспейсах с лейблом security.deckhouse.io/trivy-provider: "".

Политика применяется только в момент admission при создании или обновлении объекта. Режим аудита Gatekeeper данное ограничение не оценивает.

Конфигурация

Управление блокировкой осуществляется через параметр denyVulnerableImages в настройках модуля:

Параметр Значение по умолчанию Описание
enabled false Включить запрет на использование уязвимых образов в помеченных неймспейсах.
allowedSeverityLevels — Образы, содержащие уязвимости только указанных уровней серьёзности, не блокируются. Допустимые значения: UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL.
registrySecrets [] Список дополнительных секретов типа kubernetes.io/dockerconfigjson, содержащих учётные данные для скачивания образов при admission-проверке. Секрет с учётными данными реестра, из которого установлена DP, добавляется автоматически. Укажите здесь секреты для рабочих нагрузок, использующих образы из других приватных реестров, доступ к которым не обеспечивается этим секретом.

Пример конфигурации

spec:
  settings:
    denyVulnerableImages:
      enabled: true
      allowedSeverityLevels:
        - UNKNOWN
        - LOW
        - MEDIUM
      registrySecrets:
        - name: my-private-registry-pull-secret
          namespace: my-app

В приведённом примере блокируются образы с уязвимостями уровня HIGH или CRITICAL. Образы с уязвимостями уровней UNKNOWN, LOW, MEDIUM допускаются к запуску. Секрет my-private-registry-pull-secret используется, чтобы trivy-provider мог скачивать образы из этого реестра при admission-проверке.

registrySecrets влияет только на учётные данные, используемые в admission-проверке. Параметр не затрагивает плановые задания сканирования рабочих нагрузок и сканирование реестров. Секрет должен существовать в кластере до включения denyVulnerableImages.

Подавление уязвимостей с помощью VEX-аттестаций

VEX (Vulnerability Exploitability eXchange) — машиночитаемое утверждение о том, является ли известная CVE реально эксплуатируемой в конкретной версии продукта. Например, VEX-утверждение может указывать, что уязвимость присутствует в библиотеке, поставляемой с образом, однако недостижима, потому что затронутый участок кода никогда не вызывается.

При включённом параметре useVEXFromOCI Trivy получает VEX-аттестации, прикреплённые к сканируемым образам в OCI-реестре (как OCI referrers), и использует их для фильтрации найденных уязвимостей. Уязвимость исключается из VulnerabilityReport или RegistryImageVulnerabilityReport, если VEX-утверждение помечает её как not_affected или fixed для данного образа.

Это работает при сканировании рабочих нагрузок (образов, запущенных в кластере), при сканировании реестров (RegistryScanTarget) и при admission-проверке (denyVulnerableImages), где подавленная уязвимость не блокирует запуск образа.

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

Требования

  • Реестр должен поддерживать OCI Referrers API (OCI Distribution Spec v1.1+). Большинство современных реестров (Harbor, Quay, GHCR, ECR) поддерживают его.
  • VEX-аттестации должны храниться как OCI referrers образа.
  • Если сертификат реестра выпущен частным центром сертификации (CA), добавьте сертификат CA в параметр additionalRegistryCA. Trivy получает аттестации с теми же сертификатами, что и сам образ.
  • Реестр не должен быть указан в параметре insecureRegistries, а при сканировании реестров у ресурса RegistryScanTarget не должно быть insecure: true. Trivy получает аттестации только по HTTPS с проверкой сертификата, поэтому образ из такого реестра сканируется без VEX-аттестаций.

Включение

Добавьте следующий параметр в ModuleConfig operator-trivy:

spec:
  settings:
    useVEXFromOCI: true

Сопоставление идентификаторов CVE с БДУ

При включённом параметре linkCVEtoBDU модуль заменяет идентификаторы CVE в объектах VulnerabilityReport идентификаторами из Банка данных угроз безопасности информации ФСТЭК России (БДУ), например BDU-2021-01234. Заменяется только поле vulnerabilityID уязвимости. CVE без соответствующей записи в БДУ сохраняет свой идентификатор CVE. Объекты NodeVulnerabilityReport и RegistryImageVulnerabilityReport не изменяются.

Чтобы включить сопоставление, задайте параметр в ModuleConfig operator-trivy:

spec:
  settings:
    linkCVEtoBDU: true

Отчёты соответствия (compliance)

Модуль создаёт объекты ClusterComplianceReport для выбранных фреймворков соответствия. Каждый отчёт обновляется по расписанию scanPeriods.complianceRescanCron (по умолчанию 0 */6 * * *, каждые 6 часов) и сопоставляет меры контроля фреймворка с проверками конфигурации и нагрузок, выполняемыми Trivy.

Набор развёртываемых отчётов задаётся параметром complianceReports.enabled.

Фреймворк По умолчанию Описание
CIS включён CIS Kubernetes Benchmark v1.12.
PCI-DSS включён PCI DSS v4.0 — ключевые меры контроля для защиты данных платёжных карт.
NSA включён NSA-CISA Kubernetes Hardening Guidance v1.0.
GDPR отключён Общий регламент по защите данных — ключевые статьи (ст. 5, 25, 32).
HIPAA отключён HIPAA Security Rule — ключевые технические меры защиты (§164.308 и §164.312).
FSTEC-21 включён Приказ ФСТЭК России № 21 — защита персональных данных в ИСПДн.
FZ-187 включён Приказ ФСТЭК России № 239 — значимые объекты КИИ (187-ФЗ).

Пример конфигурации

Следующий фрагмент ModuleConfig operator-trivy развёртывает четыре отчёта:

spec:
  settings:
    complianceReports:
      enabled:
        - CIS
        - NSA
        - FSTEC-21
        - FZ-187

Чтобы получить список отчётов соответствия, выполните:

d8 k get clustercompliancereports

Чтобы просмотреть отчёт, например fstec-21, выполните:

d8 k describe clustercompliancereport fstec-21

Что попадает в отчёты соответствия

По умолчанию параметр complianceReports.skipSystemResources включён, поэтому отчёты соответствия сфокусированы на нагрузках, которые владелец кластера может исправить. Модуль исключает из отчётов соответствия следующие объекты:

  • объекты в неймспейсах, попадающих под шаблоны d8-*, kube-* и default;
  • cluster-wide-объекты с лейблом heritage=deckhouse, которые принадлежат DP и её модулям;
  • встроенные объекты RBAC (kubernetes.io/bootstrapping=rbac-defaults).

Сам control plane при этом продолжает проверяться по соответствующим инфраструктурным мерам контроля (например, раздел 1.x CIS Kubernetes Benchmark для параметров kube-apiserver, etcd, kube-scheduler). Отсекаются только общие проверки рабочих нагрузок для платформенных подов.

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

Чтобы исключить отдельный неймспейс из отчётов соответствия, например экспериментальный или временный, добавьте к неймспейсу лейбл security.deckhouse.io/skip-compliance=true. Лейбл действует независимо от значения параметра complianceReports.skipSystemResources:

d8 k label namespace my-namespace security.deckhouse.io/skip-compliance=true

События безопасности

Если включён модуль security-events-manager, модуль отправляет ему событие безопасности каждый раз, когда сканирование сохраняет отчёт с находками. Ресурсы SecurityEventDefinition и ресурс PodSecurityEventShipper operator-trivy в неймспейсе d8-operator-trivy поставляются вместе с модулем, поэтому дополнительная настройка не требуется.

События формируются по логам трёх компонентов:

  • operator — отчёты о рабочих нагрузках, узлах, аудите конфигурации, RBAC, инфраструктуре и соответствии стандартам;
  • registry-scanner — отчёты об образах из реестров, перечисленных в ресурсах RegistryScanTarget;
  • trivy-provider — образы, отклонённые политикой из раздела «Запрет запуска уязвимых контейнеров».

Список событий

В таблице перечислены события, которые создаёт модуль. Отчёт создаёт одно событие независимо от количества находок в нём.

Код события Уровень Условие
D8_TRIVY_WORKLOAD_VULNERABILITIES_FOUND По находкам В отчёте VulnerabilityReport рабочей нагрузки есть уязвимости
D8_TRIVY_WORKLOAD_EXPOSED_SECRETS_FOUND По находкам В отчёте ExposedSecretReport есть секреты
D8_TRIVY_NODE_VULNERABILITIES_FOUND По находкам В отчёте NodeVulnerabilityReport есть уязвимости
D8_TRIVY_REGISTRY_IMAGE_VULNERABILITIES_FOUND По находкам В отчёте RegistryImageVulnerabilityReport есть уязвимости
D8_TRIVY_MISCONFIGURATION_FOUND По находкам В отчёте ConfigAuditReport или InfraAssessmentReport есть непройденные проверки
D8_TRIVY_RBAC_ISSUES_FOUND По находкам В отчёте RbacAssessmentReport есть непройденные проверки
D8_TRIVY_VULNERABLE_IMAGE_REJECTED По находкам trivy-provider сообщил об уязвимостях в образе, и создание объекта было запрещено
D8_TRIVY_REGISTRY_SCAN_FAILED Low registry-scanner не удалось получить доступ к реестру, список его репозиториев или тегов либо просканировать образ
D8_TRIVY_COMPLIANCE_CHECKS_FAILED Low В отчёте ClusterComplianceReport есть невыполненные требования

События по узлам и по реестрам создаются, только если включены сканирование узлов и сканирование реестров, описанные в разделах «Сканирование узлов» и «Сканирование реестров».

Уровень события

Событие с уровнем «По находкам» получает уровень наиболее критичной находки в отчёте: CRITICAL соответствует Critical, HIGH — High, MEDIUM — Medium, LOW и UNKNOWN — Low.

Параметр securityEvents.minimumSeverity задаёт наименьший уровень, при котором создаётся событие. При значении по умолчанию HIGH отчёт создаёт событие, только если в нём есть находки уровней CRITICAL или HIGH. Отклонённые образы, ошибки сканирования реестров и невыполненные требования стандартов соответствия всегда создают событие.

Чтобы получать события и об отчётах с находками уровней MEDIUM и LOW, задайте параметру значение LOW:

apiVersion: deckhouse.io/v1alpha1
kind: ModuleConfig
metadata:
  name: operator-trivy
spec:
  version: 1
  settings:
    securityEvents:
      minimumSeverity: LOW

Почти в каждом образе есть уязвимости уровней MEDIUM или LOW, поэтому при этом значении событие создаётся почти для каждой просканированной рабочей нагрузки. Параметр отбрасывает находки ещё на узле кластера, а параметр defaultSeverityThreshold ресурса ClusterSecurityEventConfig фильтрует уже собранные события отдельно для каждого приёмника.

Содержимое события

Событие описывает просканированный объект, а не отчёт. Для рабочей нагрузки поле object содержит тип, имя и неймспейс рабочей нагрузки, например ReplicaSet, для узла — имя узла, для образа из реестра или отклонённого образа — ссылку на образ.

Поле metadata.extra содержит остальные данные:

  • critical, high, medium, low, unknown и total — количество находок каждого уровня;
  • reportKind, reportName и reportNamespace — отчёт, в котором перечислены находки, причём reportNamespace есть только у отчёта, размещённого в неймспейсе;
  • container, image и imageDigest — контейнер и образ рабочей нагрузки;
  • component — компонент модуля, создавший событие.

Список уязвимостей в событие не копируется. Чтобы его просмотреть, откройте отчёт, указанный в reportName.

Частота событий

Событие создаётся при каждом сохранении отчёта, а не только при появлении новых находок. Отчёты рабочих нагрузок пересоздаются с периодом scanPeriods.workloadRescanPeriod, поэтому уязвимая рабочая нагрузка создаёт событие не реже одного раза за этот период.

Событие D8_TRIVY_REGISTRY_SCAN_FAILED, напротив, следует за состоянием ресурса RegistryScanTarget. registry-scanner повторяет сканирование цели со сбоем каждые несколько минут, но событие создаётся только тогда, когда цель переходит в состояние сбоя или меняется причина либо текст её условия Ready, поэтому цель, которая продолжает сбоить одинаково, создаёт одно событие.

Источник событий — podSecurityEventShipper/d8-operator-trivy/operator-trivy/operator-trivy. Чтобы перестать получать события, исключите этот источник из параметра enabledSources или enabledSourcesMasks ресурса ClusterSecurityEventConfig.

Оценка безопасности

Модуль сводит состояние безопасности кластера к единой оценке от 0 до 100 и рассчитывает такую же оценку для каждого пользовательского неймспейса. Обе величины публикуются в объектах и отображаются в Deckhouse Console.

Оценка кластера хранится в ClusterSecurityScore cluster, оценка неймспейса — в SecurityScore security-score в самом неймспейсе. Данные в обоих объектах хранятся в блоке score.

Разделение сделано ради прав доступа: оценка неймспейса выдаётся вместе с самим неймспейсом, ролью d8:use:capability:module:operator-trivy:view, а оценка кластера — ролью d8:manage:permission:module:operator-trivy:view. Пользователь проекта видит оценку своих неймспейсов и не получает вместе с ней картину слабых мест всего кластера.

Оценка пересчитывается при изменении Namespace или NetworkPolicy, при изменении ModuleConfig admission-policy-engine, operator-trivy или runtime-audit-engine, а также по расписанию раз в 10 минут. Отчёты читаются при каждом пересчёте, поэтому все составляющие отражают текущее состояние кластера.

Изменения неймспейсов с лейблами heritage=deckhouse и heritage=upmeter пересчёт не запускают. Изменения остальных исключённых неймспейсов — попадающих под шаблоны d8-*, kube-* и default, а также помеченных security.deckhouse.io/skip-compliance=true — пересчёт запускают, но в саму оценку эти неймспейсы не входят.

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

Составляющие оценки

Оценка кластера — это взвешенное среднее семи составляющих, каждая из которых нормируется к значению от 0 до 1. Сумма весов равна 100, поэтому кластер, у которого все составляющие равны 1, получает ровно 100.

Составляющая Вес Что оценивает
coverage 20 Доля пользовательских неймспейсов с лейблом security-scanning.deckhouse.io/enabled
cve 20 Нагрузка по уязвимостям из отчётов VulnerabilityReport и NodeVulnerabilityReport
psa 15 Строгость стандарта безопасности подов, применённого к неймспейсам, с учётом режима применения
network 15 Доля пользовательских неймспейсов, в которых есть хотя бы один объект NetworkPolicy
misconfig 15 Нагрузка по ошибкам конфигурации из отчётов ConfigAuditReport и ClusterConfigAuditReport
secrets 10 Нагрузка по раскрытым учётным данным из отчётов ExposedSecretReport
compliance 5 Доля успешных проверок по всем развёрнутым отчётам соответствия

Учитываются только пользовательские неймспейсы. Модуль исключает неймспейсы, попадающие под шаблоны d8-*, kube-* и default, неймспейсы с лейблами heritage=deckhouse или heritage=upmeter, а также неймспейсы с лейблом security.deckhouse.io/skip-compliance=true.

На оценку влияют не все виды отчётов. RbacAssessmentReport и InfraAssessmentReport не входят ни в одну составляющую: они используются в отчётах соответствия и попадают в оценку только через составляющую compliance. Поэтому проверки управляющего контура в kube-system, которые модуль продолжает выполнять, составляющую misconfig не меняют.

Исключение неймспейса из оценки не исключает его из сканирования. Конфигурационные сканеры работают по всему кластеру, а сканер уязвимостей охватывает каждый неймспейс с лейблом security-scanning.deckhouse.io/enabled, в том числе системный. Исключение определяет только то, по каким неймспейсам считается оценка.

Составляющие по находкам

Составляющие cve, misconfig и secrets переводят количество находок в нагрузку по степени критичности, а нагрузку — в оценку по формуле 1 / (1 + нагрузка / k). С ростом числа находок оценка стремится к 0, но не достигает его, поэтому одна составляющая не может обнулить всю оценку.

Нагрузка и константа k различаются по составляющим:

Составляющая Нагрузка Константа k
cve 10 × critical + 3 × high + 1 × medium 50
misconfig 5 × critical + 2 × high + 1 × medium 30
secrets 10 × critical + 5 × high + 2 × medium 10

Находки со степенью критичности low и unknown на оценку не влияют. Строже всего оцениваются раскрытые секреты: одна критическая находка уже уменьшает составляющую secrets вдвое.

Составляющая по стандартам безопасности подов

Составляющая psa объединяет строгость политики, применённой к неймспейсу, и режим её применения модулем admission-policy-engine. Политика берётся из лейбла security.deckhouse.io/pod-policy неймспейса. Если лейбл не задан, политика берётся из параметра podSecurityStandards.defaultPolicy модуля admission-policy-engine, если модуль включён, а иначе равна Privileged.

Строгость политик:

  • Restricted — 1;
  • Baseline — 0,6;
  • Privileged — 0.

Полученное значение умножается на коэффициент режима применения:

  • Deny — 1;
  • Warn — 0,5;
  • Dryrun — 0,2;
  • модуль admission-policy-engine отключён — 0,1.

Поэтому политика Restricted в режиме Dryrun оценивается существенно ниже, чем та же политика в режиме Deny. Итоговое значение и значение до умножения публикуются в полях value и raw самой составляющей, а режим применения и его коэффициент — один раз, в блоке modules.admissionPolicyEngine.

Оценка неймспейса

Оценка неймспейса использует те же составляющие, веса и константы, что и оценка кластера, за исключением compliance: отчёты соответствия относятся к кластеру целиком, поэтому их результат нельзя отнести к отдельному неймспейсу. По той же причине не учитываются уязвимости узлов. Константы общие, поэтому неймспейс, в котором сосредоточены все находки кластера, получает те же значения составляющих, что и кластер.

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

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

Составляющая, рассчитываемая по отчётам, помечается полем notMeasured, если отчётов соответствующего типа нет. Правило одинаково для кластера и для неймспейса: без отчётов составляющая исключается из расчёта, а не считается безупречным результатом. Поэтому кластер, в котором ничего не сканируется, не получает полный вес составляющих cve и secrets за отсутствие находок.

Составляющая compliance — исключение из этого правила: если в кластере нет ни одного отчёта соответствия, она равна 1 и сохраняет свой вес. Отчёты соответствия включаются по требованию параметром complianceReports.enabled, поэтому их отсутствие — выбор конфигурации, а не неохваченная область. Это ещё одна причина не сравнивать оценку кластера со средней оценкой неймспейсов.

Неймспейс без лейбла для сканирования, по которому нет ни одного отчёта, ограничен значением 60: coverage равна 0, и в расчёте остаются только веса psa и network.

Обычно у несканируемого неймспейса отчёты всё же есть. Объекты ConfigAuditReport создаются независимо от лейбла security-scanning.deckhouse.io/enabled, поэтому у несканируемого неймспейса обычно есть известная составляющая misconfig и более широкий набор применимых весов. Такой неймспейс всегда теряет весь вес составляющей coverage, и уже поэтому не может получить 100.

То же правило даёт и обратный случай. Неймспейс, помеченный для сканирования, с сетевой политикой и стандартом Restricted, но пока без единого отчёта, получает 100: три составляющие по отчётам исключаются из расчёта, а оставшиеся находятся на максимуме. Сразу после включения сканирования и до появления первых отчётов такой неймспейс выглядит безупречным.

Читайте оценку вместе с полем notMeasured у составляющих: значение 100 при cve, misconfig или secrets в состоянии «не измерено» означает, что неймспейс хорошо настроен и ещё не проверен, а не что в нём нет находок.

Оценки неймспейсов хранятся в отдельных объектах, поэтому их количество ничем не ограничено. В блоке score.namespaceScores ClusterSecurityScore публикуется только сводка: total — количество оценённых неймспейсов, average — средняя оценка по ним. Для интерфейсов, которым не разрешено читать SecurityScore по всему кластеру, в ClusterSecurityScore также публикуется блок score.topNamespaces с неймспейсами, требующими внимания в первую очередь.

SecurityScore удаляется вместе со своим неймспейсом. Если неймспейс перестал оцениваться, например получил лейбл security.deckhouse.io/skip-compliance=true, модуль сам удаляет его SecurityScore.

Просмотр оценки

Чтобы получить оценки всех неймспейсов, к которым есть доступ, выполните:

d8 k get securityscores.deckhouse.io --all-namespaces

Чтобы получить оценку одного неймспейса со всеми составляющими, выполните:

d8 k -n <NAMESPACE> get securityscores.deckhouse.io security-score -o yaml

Чтобы получить оценку кластера, выполните:

d8 k get clustersecurityscores.deckhouse.io cluster -o yaml

Вместо <NAMESPACE> укажите имя неймспейса.

В выводе первой команды содержатся оценка, состояние сканирования и применённый стандарт безопасности подов по каждому неймспейсу. Полные объекты содержат значение каждой составляющей и находки, по которым она рассчитана.

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

Метрики оценки

Модуль экспортирует оценку кластера в Prometheus, чтобы значение можно было выводить на графики и использовать в алертах без чтения ClusterSecurityScore.

Доступны следующие метрики:

  • deckhouse_trivy_security_score — оценка кластера от 0 до 100;
  • deckhouse_trivy_security_score_component — значение отдельной составляющей от 0 до 1, имя составляющей передаётся в лейбле component;
  • deckhouse_trivy_security_namespace_score_average — средняя оценка по всем пользовательским неймспейсам;
  • deckhouse_trivy_security_namespaces_total — количество пользовательских неймспейсов;
  • deckhouse_trivy_security_namespaces_scanned — количество пользовательских неймспейсов с включённым сканированием.

Составляющая, которая не измерялась, не экспортируется вовсе: её временной ряд пропадает, а не сообщает значение. Учитывайте это в алертах по метрике deckhouse_trivy_security_score_component: дополняйте условие функцией absent() либо опирайтесь на составляющую coverage, которая присутствует всегда. Например, выражение deckhouse_trivy_security_score_component{component="cve"} < 0.5 не сработает на кластере, где ничего не сканируется, то есть там, где алерт нужнее всего.

Оценки отдельных неймспейсов в метрики не выводятся: в большом кластере это добавило бы отдельный временной ряд на каждый неймспейс. Читайте их из объектов SecurityScore.

Версия формулы

Веса, константы и правила расчёта не меняются между релизами. Любое их изменение увеличивает значение поля formulaVersion, которое публикуется вместе с оценкой — как для кластера, так и для неймспейсов. Изменение правила расчёта увеличивает его так же, как изменение веса.

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

Работа с приватными и небезопасными реестрами

По умолчанию модуль ожидает, что все реестры контейнеров используют доверенные TLS-сертификаты. Для окружений с самоподписанными сертификатами, HTTP-реестрами или отключённой проверкой TLS доступны следующие параметры.

Корневые сертификаты для приватных реестров

Параметр additionalRegistryCA задаёт корневые CA-сертификаты для приватных реестров контейнеров.

Каждая запись содержит поле name (произвольное название, только для справки) и ca (сертификат или цепочка в формате PEM). При указании цепочки объедините сертификаты последовательно в формате PEM без лишних пустых строк между ними.

spec:
  settings:
    additionalRegistryCA:
      - name: корпоративный CA
        ca: |
          -----BEGIN CERTIFICATE-----
          ...
          -----END CERTIFICATE-----
      - name: CA с промежуточным сертификатом
        ca: |
          -----BEGIN CERTIFICATE-----
          ...
          -----END CERTIFICATE-----
          -----BEGIN CERTIFICATE-----
          ...
          -----END CERTIFICATE-----

Небезопасные реестры

Параметр insecureRegistries разрешает сканеру подключаться к указанным реестрам по HTTP или по HTTPS без проверки сертификата. Каждая запись — имя хоста реестра (опционально с портом).

spec:
  settings:
    insecureRegistries:
      - my.internal-registry.example.com
      - legacy-registry.example.com:5000

Параметр применяется при сканировании рабочих нагрузок и при admission-проверке (denyVulnerableImages). Для сканирования реестров укажите insecure: true в RegistryScanTarget.

insecureRegistries отключает проверку сертификата только для указанных хостов. Чтобы отключить проверку TLS для загрузки баз данных уязвимостей Trivy (не реестров образов), используйте отдельный параметр insecureDbRegistry.

Источники данных об уязвимостях

Основная база уязвимостей trivy-db — это база проекта Trivy, дополненная источниками DP. Каждые 6 часов DP берёт актуальную базу Trivy, добавляет в неё свои источники и публикует результат в реестр DP.

Источники из базы Trivy

Базу Trivy собирает Aqua Security, в неё входят перечисленные ниже источники. Aqua Security добавляет в базу новые источники, полный список приведён в документации Trivy.

Дистрибутивы ОС:

Поставщики исправленных образов и пакетов:

Зависимости приложений:

Уязвимости Kubernetes берутся из Official Kubernetes CVE Feed.

Сведения об уязвимостях, например описание и оценка CVSS, берутся также из National Vulnerability Database (NVD).

Дополнительные источники

DP добавляет в базу Trivy следующие источники:

Источник Данные Для чего используется
Errata ALT Linux OVAL для веток p9, p10, p11, c9f2 и c10f2 Пакеты ALT Linux
Бюллетени безопасности «РЕД СОФТ» OVAL для РЕД ОС 7.3 и 8.0 Пакеты РЕД ОС
ScanOVAL для Astra Linux OVAL для Astra Linux Special Edition 1.7 Пакеты Astra Linux
Банк данных угроз безопасности информации ФСТЭК России (БДУ ФСТЭК) Перечень уязвимостей Сопоставление идентификаторов CVE с БДУ, база trivy-bdu

Записи ALT Linux также содержат идентификаторы БДУ, которые ALT публикует вместе с errata.

Управление базами данных

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

База данных Содержимое Кто и когда загружает
<deckhouse-repo>/security/trivy-db:2 База уязвимостей: база Trivy с дополнительными источниками Trivy-сервер раз в час
<deckhouse-repo>/security/trivy-java-db:1 База Java-артефактов (JAR, WAR, EAR) с привязкой к хешам файлов, берётся из Trivy без изменений Задания сканирования Java-образов; trivy-provider раз в час, если включён параметр denyVulnerableImages; registry-scanner, если включено сканирование реестров
<deckhouse-repo>/security/trivy-bdu:1 Сопоставление идентификаторов CVE с БДУ, собирается DP из БДУ ФСТЭК report-updater каждые 6 часов, если включён параметр linkCVEtoBDU

Trivy-сервер хранит trivy-db в PersistentVolumeClaim размером 5 ГиБ. Если параметр storageClass равен false или StorageClass не задан ни для модуля, ни глобально, база хранится в emptyDir и загружается заново после каждого перезапуска Trivy-сервера.

Версия trivy-db и trivy-java-db, которую использует Trivy-сервер, отображается в ConfigMap trivy-db-info:

d8 k -n d8-operator-trivy get configmap trivy-db-info -o yaml

Параметр vulnerabilityDatabaseMaxAge (по умолчанию 168h) задаёт, насколько старой может быть база trivy-db, прежде чем сработает алерт TrivyVulnerabilityDatabaseOutdated. Связанный алерт TrivyVulnerabilityDatabaseMissing срабатывает, если ConfigMap trivy-db-info отсутствует или в нём нет временной метки (timestamp) trivy-db.updatedAt в течение 30 минут. Установите параметр в "", чтобы отключить оба алерта актуальности базы.

Политики для проверок конфигурации не загружаются: они встроены в образ оператора и обновляются вместе с модулем. Изменения DP в проверках Trivy описаны в разделе «Доработки DP».

Закрытые окружения

Кластер загружает базы данных только из своего реестра, поэтому их актуальность зависит от того, как часто они туда копируются. Копируйте базы данных с помощью CLI-утилиты d8 каждые 6 часов — так же часто, как публикуются новые версии. Команды приведены в разделе «Механика обновления баз данных сканера уязвимостей».

d8 mirror копирует базы данных под теми же тегами (trivy-db:2, trivy-java-db:1 и trivy-bdu:1), поэтому менять конфигурацию модуля не нужно. Если базы не обновлять, сканирование продолжится по уже загруженной базе: уязвимости, опубликованные после неё, обнаружены не будут, а когда база станет старше vulnerabilityDatabaseMaxAge, сработает алерт TrivyVulnerabilityDatabaseOutdated.