Стадия жизненного цикла модуля: Общедоступная версия
У модуля есть требования для установки
В кластере DKP сканирование на уязвимости выполняется с помощью оператора Trivy Operator. Он автоматически генерирует Software Bill Of Materials (SBOM) для всех рабочих нагрузок и запускает сканирование для заданных объектов без ручного вмешательства.
Поддерживаемые типы объектов для сканирования
Сканирование поддерживается для следующих типов объектов:
- образы контейнеров, размещённые в хранилище (registry);
- файловые системы узлов кластера.
Архитектура анализа
Независимо от типа объекта сканирование выполняется в три этапа:
| Этап | Описание |
|---|---|
| 1. Сканирование | Сканер обходит целевой объект и применяет анализаторы для извлечения использованных пакетов, манифестов зависимостей и конфигурационных файлов, формируя SBOM. |
| 2. Фильтрация | Собранные данные сопоставляются с базами данных уязвимостей и политиками. Применяются фильтры по серьёзности, статусу исправления и типу пакетных зависимостей. |
| 3. Отчёт | Результаты сохраняются в виде ресурса VulnerabilityReport и публикуются в кластере в неймспейсе целевого объекта. При сканировании файловых систем узлов отчет сохраняется в виде кластерного ресурса NodeVulnerabilityReport |
Механизм сканирования уязвимостей
Сканер уязвимостей является центральным компонентом Trivy: он выявляет известные уязвимости на основе специализированных баз данных. Модуль operator-trivy сканирует пакеты и компоненты операционной системы (исполняемые файлы, библиотеки) и зависимости приложений (библиотеки, модули и прочие зависимости).
Оператор автоматически запускает сканирование при обнаружении новых или изменённых рабочих нагрузок в неймспейсах, для которых включено сканирование.
Отчёты пересоздаются, когда их возраст превышает scanPeriods.workloadRescanPeriod (по умолчанию 24h).
Установите параметр в "", чтобы отключить периодическое повторное сканирование.
Пакеты операционной системы
Сканер автоматически определяет дистрибутив ОС и применяет соответствующие данные из баз уязвимостей, предоставляемых DKP.
Используются следующие источники данных:
- Банк данных угроз безопасности информации ФСТЭК России (БДУ ФСТЭК);
- AlmaLinux Errata;
- Alpine SecDB;
- ALTRepo Errata OVAL;
- Amazon Linux Security Advisories;
- Arch Linux Security Tracker;
- Debian Security Tracker;
- GitHub Security Advisory Database;
- National Vulnerability Database (NVD);
- Oracle OVAL;
- Photon Security Advisory;
- Red Hat OVAL;
- RED SOFT OVAL;
- Rocky Linux UpdateInfo;
- SUSE Security CVRF;
- Ubuntu CVE Tracker;
- Wolfi SecDB.
Зависимости приложений
Сканер обнаруживает и анализирует файлы манифестов пакетных менеджеров и lock-файлы более чем двадцати экосистем. Для каждого языка используются специализированные базы уязвимостей, преимущественно основанные на GitLab Advisory Database и GitHub Advisory Database.
| Язык / экосистема | Анализируемые файлы |
|---|---|
| Node.js (npm, Yarn) | package.json, package-lock.json, yarn.lock |
| Python (pip, Poetry, Pipenv) | requirements.txt, Pipfile.lock, poetry.lock |
| Java (Maven, Gradle) | pom.xml, build.gradle, *.jar, *.war |
| Go | go.mod, go.sum, бинарные файлы Go |
| .NET (NuGet) | *.csproj, packages.lock.json |
| Ruby (Bundler) | Gemfile.lock |
| PHP (Composer) | composer.lock |
| Rust (Cargo) | Cargo.lock |
| Swift (SwiftPM) | Package.resolved |
| Dart (pub) | pubspec.lock |
Результаты сканирования и ресурс VulnerabilityReport
Результаты сканирования уязвимостей сохраняются в кластере в виде кастомного ресурса VulnerabilityReport группы trivy.deckhouse.io. Каждый отчёт создаётся в неймспейсе рабочей нагрузки, именуется по схеме <kind>-<workload-name>-<container-name> и содержит перечень обнаруженных уязвимостей с указанием серьёзности, статуса исправления, затронутого пакета и ссылок на источники.
Отчёт привязывается к родительскому ресурсу через поле ownerReferences. При обновлении образа или удалении рабочей нагрузки устаревший VulnerabilityReport удаляется механизмом сборки мусора Kubernetes и при необходимости пересоздаётся.
По умолчанию в отчёт попадают все уровни критичности. Параметр severities оставляет в VulnerabilityReport только выбранные уровни.
Дополнительные поля из базы уязвимостей добавляются параметром additionalVulnerabilityReportFields.
Чтобы скопировать лейблы сканируемой нагрузки на отчёт, используйте reportResourceLabels.
Генерация и обработка SBOM
Сгенерированный SBOM сохраняется в кластере в виде CRD SbomReport группы trivy.deckhouse.io. Каждый отчёт создаётся в неймспейсе рабочей нагрузки и содержит:
- метаданные контейнерного образа (репозиторий, тег, дайджест);
- компонентный состав в формате CycloneDX (пакеты ОС и зависимости приложений с идентификаторами PURL, лицензиями и информацией о поставщике);
- граф зависимостей между компонентами;
- сводку по количеству компонентов и зависимостей.
Оператор отслеживает изменения ресурсов кластера. При создании или изменении рабочей нагрузки автоматически запускается задание сканирования, по результатам которого одновременно формируются SbomReport и VulnerabilityReport. Оба отчёта именуются по схеме <kind>-<workload-name>-<container-name> и привязываются к родительскому ресурсу через поле ownerReferences. При удалении рабочей нагрузки отчёты удаляются автоматически через механизм сборки мусора Kubernetes.
SbomReport и VulnerabilityReport дополняют друг друга: VulnerabilityReport содержит выявленные уязвимости, а SbomReport фиксирует полный состав компонентов образа.
Чтобы отключить генерацию SBOM, установите disableSBOMGeneration в true. При включении этого параметра существующие ресурсы SbomReport однократно удаляются из кластера.
Сканирование узлов
Модуль может сканировать хостовую файловую систему каждого узла Kubernetes на уязвимости в пакетах ОС и, при необходимости, на секреты в файлах узла. Результаты сохраняются в cluster-wide-ресурсах NodeVulnerabilityReport.
Функция по умолчанию отключена. Включите её в 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 |
Значение по умолчанию для заданий сканирования | Тайм-аут заданий сканирования узлов |
concurrentLimit |
1 |
Максимальное число одновременных заданий сканирования узлов |
nodeSelector |
Все узлы | Сканировать только узлы с указанными лейблами |
severities |
["CRITICAL", "HIGH"] |
Уровни критичности, которые попадают в отчёт |
hideUnfixedCVEs |
false |
Включать в отчёт только уязвимости, для которых есть исправление |
Пример конфигурации:
spec:
settings:
nodeScanning:
enabled: true
scanners:
- Vuln
pkgTypes:
- OS
severities:
- CRITICAL
- HIGH
concurrentLimit: 1Уровни LOW и MEDIUM могут на порядок увеличить объём отчётов.
Сканирование реестров
Помимо сканирования образов, запущенных в кластере, модуль поддерживает периодическое сканирование репозиториев образов, хранящихся во внешних реестрах контейнеров.
Включите функцию в ModuleConfig/operator-trivy:
spec:
settings:
registryScanning:
enabled: true
concurrentScans: 5Параметр registryScanning.concurrentScans ограничивает число одновременных сканирований образов по всем целям. Значение по умолчанию — 5.
Настройка сканирования репозиториев в реестрах
Целевой реестр контейнеров для сканирования описывается cluster-scoped ресурсом RegistryScanTarget:
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]+" # Опционально: сканировать только теги, соответствующие регулярному выражению.
maxTags: 50 # Опционально: не более 50 тегов на репозиторий (по умолчанию 100).
registrySecretRef: # Опционально: учётные данные для приватного реестра.
name: image-pull-credentialssecret
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.
Результаты сканирования
Результаты сохраняются в cluster-scoped ресурсах RegistryImageVulnerabilityReport, по одному на каждый сканируемый тег образа.
Каждый отчёт принадлежит своему RegistryScanTarget. При удалении объекта RegistryScanTarget связанные с ним отчёты автоматически удаляются механизмом сборки мусора Kubernetes.
# Список всех отчётов.
d8 k get registryimagevulnerabilityreport
# Просмотр конкретного отчёта.
d8 k describe registryimagevulnerabilityreport <name>Отчёт хранится в etcd, поэтому его размер ограничен. Если отчёт образа превышает 1 МиБ, сканер удаляет из него данные в следующем порядке, пока отчёт не поместится:
- Удаляются списки
links, полеprimaryLinkсохраняется. - Удаляются описания уязвимостей.
- Удаляются векторы CVSS, поле
scoreсохраняется. - Удаляются уязвимости самых низких уровней критичности.
Счётчики 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 показывает время последнего цикла и его результат:
d8 k get registryscantarget
d8 k describe registryscantarget my-registryУсловие Ready появляется после первого цикла цели. Оно принимает значение True после успешного завершения цикла и False
во всех остальных состояниях. Различить состояния позволяет поле reason:
| Причина | Значение | Следующий цикл |
|---|---|---|
ScanCompleted |
Все выбранные образы просканированы. | Через период, заданный параметром rescanPeriod. |
ScanInProgress |
Цикл выполняется или был прерван перезапуском. | Через период, заданный параметром rescanPeriod, от последнего завершённого цикла. |
ScanFailed |
Часть репозиториев не прочитана или часть образов не просканирована. Они перечислены в сообщении. | Через час, далее с увеличением интервала, пока ошибка сохраняется, но не реже периода, заданного параметром rescanPeriod. Повтор пересканирует цель целиком. |
DiscoveryFailed |
Цикл прекращён до начала сканирования: некорректный tagFilter, нечитаемый секрет с учётными данными или каталог, который реестр не отдал. |
Через пять минут. |
WaitingForJavaDB |
Индексная база Java ещё загружается. Цель с прошлым результатом сохраняет его, пока загрузка коротка, и сообщает об ожидании, когда оно превысит 15 минут. | В течение 30 секунд после готовности базы. |
Пока загружается индексная база Java, не сканируется ни одна цель. До завершения загрузки компонент сообщает о неготовности, поэтому при остановке циклов проверяйте готовность его пода.
Если задан параметр tagFilter, в поле status.targets перечисляются совпавшие теги не более чем 50 репозиториев.
Отчёт, удалённый вручную, создаётся заново следующим циклом цели, а не сразу. Чтобы вернуть его немедленно, удалите у ресурса
RegistryScanTarget аннотацию registry-scanner.deckhouse.io/last-scan-time.
Отчёты, созданные до текущего выпуска, удаляет первый цикл, прочитавший все репозитории своей цели. Цель, у которой каталог
постоянно длиннее 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-проверке. Секрет с учётными данными реестра, из которого установлен DKP, добавляется автоматически. Укажите здесь секреты для рабочих нагрузок, использующих образы из других приватных реестров, доступ к которым не обеспечивается этим секретом. |
Пример конфигурации
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).
VEX-аттестации создаются и публикуются вендором образа — как правило, командой которая его поддерживает. Для подавления уязвимостей к образу в реестре должна быть прикреплена VEX-аттестация. Если аттестация отсутствует, сканирование выполняется в штатном режиме и ничего не фильтруется.
Требования
- Реестр должен поддерживать OCI Referrers API (OCI Distribution Spec v1.1+). Большинство современных реестров (Harbor, Quay, GHCR, ECR) поддерживают его.
- VEX-аттестации должны храниться как OCI referrers образа.
Включение
Добавьте следующий параметр в ModuleConfig/operator-trivy:
spec:
settings:
useVEXFromOCI: trueСопоставление идентификаторов CVE с БДУ
При включённом параметре linkCVEtoBDU модуль заменяет записи CVE в отчётах об уязвимостях идентификаторами из Банка данных угроз безопасности информации ФСТЭК России (БДУ).
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-ФЗ). |
Пример конфигурации
complianceReports:
enabled:
- CIS
- NSA
- FSTEC-21
- FZ-187В приведённом примере развёртываются только четыре отчёта. Для просмотра отчёта используйте:
d8 k get clustercompliancereports
d8 k describe clustercompliancereport fstec-21Что попадает в отчёты соответствия
По умолчанию параметр complianceReports.skipSystemResources включён, поэтому отчёты соответствия сфокусированы на нагрузках, которые владелец кластера может исправить. Модуль автоматически исключает из compliance:
- ресурсы, управляемые Deckhouse и его модулями;
- системные компоненты Kubernetes (встроенные RBAC, дефолтные cluster-scoped объекты и т. п.).
Сам control plane при этом продолжает проверяться по соответствующим инфраструктурным мерам контроля (например, раздел 1.x CIS Kubernetes Benchmark для параметров kube-apiserver, etcd, kube-scheduler) — отсекаются только общие workload-проверки для платформенных подов.
Сканирование уязвимостей работает независимо от этих фильтров и продолжает сообщать о CVE и секретах для всех сканируемых образов, включая платформенные.
Чтобы исключить отдельный неймспейс из compliance — например, экспериментальный или временный — повесьте на него метку:
d8 k label namespace my-namespace security.deckhouse.io/skip-compliance=trueОценка безопасности
Модуль сводит состояние безопасности кластера к единой оценке от 0 до 100 и рассчитывает такую же оценку для каждого пользовательского неймспейса. Обе величины публикуются в ресурсах и отображаются в веб-интерфейсе Deckhouse.
Оценка кластера лежит в ресурсе ClusterSecurityScore с именем cluster, оценка неймспейса — в ресурсе SecurityScore с именем security-score в самом неймспейсе. Полезная нагрузка в обоих ресурсах лежит в блоке score.
Разделение сделано ради прав доступа: оценка неймспейса выдаётся вместе с самим неймспейсом, ролью d8:use:capability:module:operator-trivy:view, а оценка кластера — ролью d8:manage:permission:module:operator-trivy:view. Пользователь проекта видит оценку своих неймспейсов и не получает вместе с ней картину слабых мест всего кластера.
Оценка пересчитывается при изменении ресурсов Namespace, NetworkPolicy и ModuleConfig, а также по расписанию раз в 10 минут. Ресурсы отчётов читаются при каждом пересчёте, поэтому все составляющие отражают текущее состояние кластера.
Изменения неймспейсов с метками heritage=deckhouse и heritage=upmeter пересчёт не запускают.
Эти неймспейсы и так не входят в оценку, а upmeter создаёт и удаляет probe-неймспейс раз в минуту — иначе оценка пересчитывалась бы дважды в минуту и каждый раз перечитывала все отчёты кластера ради неизменного результата.
Остальные исключённые неймспейсы — попадающие под шаблоны 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:
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, если отчётов соответствующего типа нет. Поле называется не unknown, потому что рядом в счётчиках находок unknown означает количество находок с неизвестной степенью критичности. Правило одинаково для кластера и для неймспейса: без отчётов составляющая исключается из расчёта, а не считается безупречным результатом. Кластер, в котором ничего не сканируется, из-за этого не получает полный вес составляющих cve и secrets за отсутствие находок.
Составляющая compliance — осознанное исключение из этого правила: если в кластере нет ни одного отчёта соответствия, она равна 1 и сохраняет свой вес. Отчёты соответствия включаются по требованию параметром complianceReports.enabled, поэтому их отсутствие — выбор конфигурации, а не неохваченная область. Это ещё одна причина не сравнивать оценку кластера со средней оценкой неймспейсов.
Неймспейс, по которому нет ни одного отчёта, ограничен значением 60: покрытие не даёт ничего, и в расчёте остаются только веса psa и network.
Это ограничение не относится ко всем несканируемым неймспейсам. Ресурсы ConfigAuditReport создаются независимо от метки security-scanning.deckhouse.io/enabled, поэтому у несканируемого неймспейса обычно есть известная составляющая misconfig и более широкий набор применимых весов. Такой неймспейс всегда теряет весь вес составляющей coverage, и уже поэтому не может получить 100.
То же правило даёт и обратный случай. Неймспейс, помеченный для сканирования, с сетевой политикой и стандартом Restricted, но пока без единого отчёта, получает 100: три составляющие по отчётам исключаются из расчёта, а оставшиеся находятся на максимуме. Сразу после включения сканирования и до появления первых отчётов такой неймспейс выглядит безупречным.
Читайте оценку вместе с полем notMeasured у составляющих: значение 100 при cve, misconfig или secrets в состоянии «не измерено» означает, что неймспейс хорошо настроен и ещё не проверен, а не что в нём нет находок.
Оценки неймспейсов лежат в отдельных ресурсах, поэтому их количество ничем не ограничено. В блоке score.namespaceScores ресурса ClusterSecurityScore публикуется только сводка: total — количество оценённых неймспейсов, average — средняя оценка по ним. Для интерфейсов, которым не разрешено читать SecurityScore по всему кластеру, там же остаётся блок score.topNamespaces с неймспейсами, требующими внимания в первую очередь.
Ресурс SecurityScore удаляется вместе со своим неймспейсом. Если неймспейс перестал оцениваться — например, получил метку security.deckhouse.io/skip-compliance — модуль удаляет ресурс сам.
Просмотр оценки
Чтобы получить текущие данные, выполните команду:
# Оценки всех неймспейсов, к которым есть доступ.
d8 k get securityscore --all-namespaces
# Оценка одного неймспейса со всеми составляющими.
d8 k -n <NAMESPACE> get securityscore security-score -o yaml
# Оценка кластера.
d8 k get clustersecurityscore cluster -o yamlВ выводе первой команды содержатся оценка, состояние сканирования и применённый стандарт безопасности подов по каждому неймспейсу. Полные ресурсы содержат значение каждой составляющей и находки, по которым она рассчитана.
Ресурсы имеют сокращённые имена secscore и clustersecscore. Указывайте либо их, либо полное имя с группой (securityscores.deckhouse.io): короткое имя без группы может совпасть с ресурсом другого модуля.
Метрики оценки
Модуль экспортирует оценку кластера в Prometheus, чтобы значение можно было выводить на графики и использовать в алертах без чтения ресурсов.
Доступны следующие метрики:
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, которое публикуется вместе с оценкой — как для кластера, так и для неймспейсов.
Изменение правила учитывается наравне с изменением веса: например, версия 3 отличается от версии 2 только тем, что составляющая без отчётов исключается из среднего, а не засчитывается как чистый результат.
Оценки, рассчитанные по разным версиям формулы, сравнивать между собой нельзя.
Работа с приватными и небезопасными реестрами
По умолчанию модуль ожидает, что все реестры контейнеров используют доверенные TLS-сертификаты. Для окружений с самоподписанными сертификатами, HTTP-реестрами или отключённой проверкой TLS доступны следующие параметры.
Корневые сертификаты для приватных реестров (additionalRegistryCA)
Параметр 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)
Параметр insecureRegistries разрешает сканеру подключаться к указанным реестрам по HTTP или по HTTPS без проверки сертификата. Каждая запись — имя хоста реестра (опционально с портом).
spec:
settings:
insecureRegistries:
- my.internal-registry.example.com
- legacy-registry.example.com:5000Параметр применяется при сканировании рабочих нагрузок (scan jobs), при admission-проверке (denyVulnerableImages) и при сканировании сторонних реестров (RegistryScanTarget).
insecureRegistries отключает проверку сертификата только для указанных хостов. Чтобы отключить проверку TLS для загрузки баз данных уязвимостей Trivy (не реестров образов), используйте отдельный параметр insecureDbRegistry.
Управление базами данных
Модуль автоматически загружает, поддерживает и кеширует необходимые базы данных при выполнении сканирования. Актуальность данных обеспечивается регулярными автообновлениями.
| Образ контейнера базы данных | Назначение |
|---|---|
<deckhouse-repo>/security/trivy-db:2 |
Основная база данных уязвимостей — агрегирует данные из NVD, Red Hat, Alpine, Ubuntu, Debian, GitLab Advisory DB, GitHub Advisory DB и других источников. |
<deckhouse-repo>/security/trivy-java-db:1 |
Специализированная база для Java-артефактов (JAR, WAR, EAR) с привязкой к хешам файлов. |
<deckhouse-repo>/security/trivy-checks:0 |
Набор политик (Rego) для проверки ошибок конфигурации в IaC. |
<deckhouse-repo>/security/trivy-bdu:1 |
Связка идентификаторов уязвимостей сторонних провайдеров баз уязвимостей с идентификаторами БДУ ФСТЭК. |
В изолированных окружениях поддерживается загрузка баз данных и их локальное использование без доступа к интернету с помощью CLI-утилиты d8 (через команду d8 mirror).
Параметр vulnerabilityDatabaseMaxAge (по умолчанию 168h) задаёт, насколько старой может быть база trivy-db, прежде чем сработает алерт TrivyVulnerabilityDatabaseOutdated. Связанный алерт TrivyVulnerabilityDatabaseMissing срабатывает, если ConfigMap trivy-db-info отсутствует или в нём нет метки trivy-db.updatedAt в течение 30 минут. Установите параметр в "", чтобы отключить оба алерта актуальности базы.