Образи контейнерів — це атомарна одиниця сучасної доставки оборонного програмного забезпечення. Кожне навантаження, що виконується на оборонних кластерах Kubernetes — місіонерські застосунки, конвеєри даних, сервіси AI-інференсу — надходить у вигляді незмінного образу, який десь і з чогось зібрано. Безпека всього нижчого рівня залежить від цілісності цього ланцюга складання. У корпоративних середовищах скомпрометований образ контейнера — це серйозний інцидент. У засекреченому оборонному середовищі — це потенційний вектор збору розвідувальних даних, механізм закріплення для держав-акторів або точка входу для деструктивних можливостей, що загрожують інфраструктурі, пов'язаній зі зброєю.
Ця стаття охоплює повний життєвий цикл безпеки образів контейнерів для оборони: вибір і перевірку базових образів, сумісних зі STIG, зміцнення складань за допомогою багатоетапних Dockerfile, виконання сканування вразливостей уізольованих CI/CD-конвеєрах, підпис образів за допомогою Cosign/Sigstore у відключених середовищах, генерацію SBOM для пакетів ATO та забезпечення контролів цілісності реєстру в Harbor. Аудиторія — інженери платформ і архітектори безпеки, які працюють над засекреченими або чутливими оборонними системами.
Чому безпека образів контейнерів важливіша в обороні, ніж у корпоративному секторі
У комерційному підприємстві вразливий або скомпрометований образ контейнера являє собою ризик витоку даних, операційного збою та регуляторної відповідальності. У засекреченому оборонному середовищі наслідки поширюються на розкриття джерел і методів, компрометацію місії та кінетичний вплив на системи, які програмна вразливість може дозволити противнику контролювати або вивести з ладу. Модель загроз якісно відрізняється: противник — це не фінансово мотивована злочинна група, а держава зі стійкими операціями доступу та терпінням чекати роками на потрібний момент для активації підсадженої можливості.
Атаки на ланцюг постачання контейнерів використовують багаторівневу природу образів контейнерів. Типовий образ місіонерського застосунку може бути зібраний на основі базового образу ОС, який встановлює пакети середовища виконання з репозиторію пакетів, а ті своєю чергою включають транзитивні залежності, підтягнуті під час складання з мовних реєстрів пакетів верхнього рівня. Противнику не потрібно зламувати внутрішні системи оборонного підрядника — компрометація залежності на три рівні глибше в цьому ланцюзі досягає того самого ефекту. Інциденти SolarWinds і XZ Utils продемонстрували, що ця модель загроз не є теоретичною; обидва були вставками в ланцюг постачання, які були б технічно невиявленими без глибоких контролів ланцюга постачання.
Оборонні середовища додають три вимоги, що роблять безпеку образів контейнерів значно операційно складнішою, ніж у корпоративних умовах:
- Вимоги до ізольованого середовища. Засекречені мережі не можуть отримувати образи з інтернет-реєстрів під час виконання. Кожна залежність образу повинна бути попередньо схвалена, проскановано та перенесена до внутрішнього реєстру перед використанням — тобто межа ланцюга постачання є жорстким периметром, який інженерні команди повністю контролюють і відповідають за його забезпечення.
- Вимоги формальної авторизації. Програмне забезпечення, що працює на засекречених системах, повинно пройти процес авторизації для роботи (ATO), який вимагає задокументованого походження для кожного компонента програмного забезпечення. Генерація SBOM та підпис образів переходять від необов'язкових практик гігієни до обов'язкових доказових матеріалів ATO.
- Примусове застосування незмінної інфраструктури. Оборонні платформи дедалі частіше вимагають, щоб жодна модифікація образів контейнерів під час виконання не була дозволена: контейнери знищуються і замінюються, а не патчуються на місці. Це означає, що стан безпеки розгорнутого навантаження постійно встановлюється під час складання образу, що робить зміцнення та шлюзи сканування під час складання обов'язковими, а не кращими практиками.
Базові образи, сумісні зі STIG
DISA (Агентство інформаційних систем оборони) публікує Посібники з технічної реалізації безпеки (STIG) для операційних систем і платформ, що використовуються в оборонних середовищах. Для контейнерних навантажень найбільш операційно значущими є STIG RHEL 8 і STIG RHEL 9, які застосовуються до похідних Red Hat Universal Base Image (UBI) — найбільш широко використовуваних базових образів на оборонних контейнерних платформах, включаючи репозиторій зміцнених образів Iron Bank платформи DoD Platform One.
STIG RHEL застосовує контролі в кількох категоріях, які суттєво відрізняються від стандартної інсталяції ОС:
- Параметри ядра (sysctl). Пересилання IP вимкнено за замовчуванням (
net.ipv4.ip_forward=0), перенаправлення ICMP відхиляються, SYN-cookies TCP увімкнено, а рандомізація адресного простору (ASLR) застосовується примусово. Ці контролі зменшують вразливість ОС як мережевого ретранслятора та ускладнюють використання вразливостей пам'яті. - Конфігурація PAM. Правила складності паролів (мінімальна довжина, класи символів), блокування облікового запису після невдалих спроб автентифікації та вимоги до запису сеансів. Для сервісних облікових записів контейнерів, що використовують автентифікацію на основі ключів або токенів, деякі з цих контролів можуть потребувати задокументованих винятків.
- Правила auditd. STIG визначає вичерпний набір правил auditd, що охоплюють доступ до файлової системи за чутливими шляхами, використання команд підвищення привілеїв (sudo, su), зміну баз даних користувачів і груп, зміни конфігурації мережі та завантаження модулів ядра. У контексті контейнерів auditd зазвичай виконується на ядрі хоста і застосовується до всіх контейнерів — правила STIG слід застосовувати на рівні вузла, а не для кожного контейнера окремо.
- Криптографічна політика FIPS 140. STIG вимагає, щоб загальносистемна крипто-політика була встановлена на FIPS або FIPS:OSCP, що вимикає TLS 1.0/1.1, MD5, SHA-1 для підписів, RC4 та DES/3DES. Компоненти застосунків, що залежать від застарілих алгоритмів, не працюватимуть під крипто-політикою FIPS — це поширена проблема інтеграції, яку виявляють пізно в проектах зміцнення, коли базовий образ STIG перевіряється проти наборів тестів застосунків.
Iron Bank (зміцнений реєстр контейнерів платформи Platform One) публікує попередньо зміцнені образи, які були перевірені на відповідність DISA STIG, проскановані на вразливості та підписані. Для програм, що вже використовують Platform One, складання на основі базового образу Iron Bank є найбільш практичним підходом: він забезпечує задокументовану, попередньо авторизовану базову лінію, яка задовольняє вимоги до базового образу більшості ATO. Для програм, що не використовують Platform One, складання та незалежна перевірка відповідності STIG за допомогою OpenSCAP (oscap-docker або oscap для експортованої файлової системи контейнера) є еквівалентним процесом.
# Перевірка файлової системи образу контейнера за STIG RHEL 9
# Експорт файлової системи образу до тимчасової директорії
docker export $(docker create registry.example.mil/myapp:v1.2.3) | tar -C /tmp/image-fs -xf -
# Запуск OpenSCAP проти експортованої файлової системи
oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_stig \
--results /tmp/stig-results.xml \
--report /tmp/stig-report.html \
--chroot /tmp/image-fs \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
Зміцнення за допомогою багатоетапного складання
Багатоетапні збірки Docker — це найефективніша окрема техніка для зменшення поверхні атаки образу контейнера. Принцип простий: використовувати один або кілька проміжних етапів збірки, що містять усі інструменти, необхідні для компіляції та пакування застосунку, і копіювати лише скомпільовані артефакти до фінального етапу виконання, який не містить нічого, що не потрібне застосунку для роботи. Застосунок на C++, зібраний на етапі, що містить gcc, make, cmake та заголовки розробки, продукує фінальний образ, що містить лише двійковий файл та його спільні бібліотеки часу виконання.
# Етап 1: збірка — повний інструментарій, відсутній у фінальному образі
FROM registry.mil/ironbank/redhat/ubi/ubi9:latest AS builder
RUN dnf install -y gcc make cmake openssl-devel && dnf clean all
WORKDIR /build
COPY src/ .
RUN cmake -DCMAKE_BUILD_TYPE=Release . && make -j$(nproc)
# Етап 2: виконання — мінімальна база, без інструментів збірки
FROM registry.mil/ironbank/redhat/ubi/ubi9-micro:latest
COPY --from=builder /build/bin/myapp /usr/local/bin/myapp
# Непривілейований користувач — вимога зміцнення STIG і NSA
RUN useradd -r -u 10001 -s /sbin/nologin appuser
USER 10001
EXPOSE 8443
ENTRYPOINT ["/usr/local/bin/myapp"]
Для статично скомпільованих застосунків Go або Rust фінальним етапом може бути scratch — повністю порожній образ, що містить лише двійковий файл. Це повністю усуває шар ОС, видаляючи всі вразливості на рівні ОС з поверхні знахідок сканера. Можливості перехресної компіляції та статичного компонування стандартної бібліотеки Go роблять образи scratch практичними для широкого класу оборонних мікросервісів без додаткової складності збірки.
Коли застосунок вимагає оболонки або утиліт ОС під час виконання (налагодження в розробці, скрипти перевірки стану, логіка ініціалізації), образи gcr.io/distroless забезпечують золоту середину: мінімальна база Debian або Alpine, що містить лише середовище виконання мови та бібліотеку C, без оболонки, без менеджера пакетів і без системних утиліт. Образи distroless підтримуються Google та публікуються з результатами сканування вразливостей; оборонні програми, що використовують distroless, повинні зеркалювати ці образи у свій внутрішній реєстр та вести власні записи оцінки вразливостей.
Примусове застосування непривілейованого користувача є вимогою зміцнення як в Посібнику з зміцнення Kubernetes NSA, так і в STIG. Інструкція USER у Dockerfile встановлює стандартного користувача для всіх наступних команд і для точки входу контейнера. Використовуйте числовий UID (не іменованого користувача), щоб уникнути залежності від файлу /etc/passwd, і вибирайте UID вище 10000, щоб уникнути конфліктів із діапазонами системних користувачів. Контролери допуску, що застосовують профіль restricted Pod Security, відхилятимуть поди, де runAsNonRoot не є true або де контейнер оголошує runAsUser: 0.
Сканування вразливостей у засекречених CI/CD-конвеєрах
Сканування вразливостей — це якісний шлюз, що запобігає потраплянню образів із відомими використовуваними CVE у засекречені розгортання. Два сканери з відкритим вихідним кодом домінують у реалізаціях оборонних контейнерних платформ: Trivy (Aqua Security) та Grype (Anchore). Обидва підтримують автономну роботу — обов'язкова вимога для CI/CD для ізольованих оборонних середовищ.
Автономний режим Trivy вимагає попереднього завантаження бази даних вразливостей та передачі її до ізольованого середовища. База даних охоплює пакети ОС (RPM, DEB, APK), пакети мовних екосистем (pip, npm, Maven, модулі Go, Cargo) та сигнатури двійкових файлів застосунків. Робочий процес передачі з використанням знімних носіїв або рішення для міждоменної передачі повинен бути інтегрований у регулярні операції команди як заплановане завдання — застаріла база даних (старша 14 днів) є поширеною знахідкою під час оцінки безпеки засекреченого середовища.
# На підключеній (з виходом в інтернет) системі — завантаження БД Trivy
trivy image --download-db-only --cache-dir /transfer/trivy-cache
# Передача /transfer/trivy-cache на ізольовану систему через схвалені носії
# На ізольованому CI/CD-виконавці — сканування образу з локальною БД
trivy image \
--skip-update \
--cache-dir /opt/trivy-cache \
--severity CRITICAL,HIGH \
--exit-code 1 \
--ignore-unfixed \
--format json \
--output /artifacts/scan-results.json \
registry.classified.mil/myapp@sha256:abc123...
# Еквівалент Grype — вимкнути автооновлення, вказати на локальну БД
GRYPE_DB_AUTO_UPDATE=false \
GRYPE_DB_CACHE_DIR=/opt/grype-db \
grype registry.classified.mil/myapp@sha256:abc123... \
--fail-on critical \
--output json > /artifacts/grype-results.json
Шлюзи політики сканування визначають, які знахідки блокують збірку конвеєра, а які генерують попередження. Обґрунтована політика шлюзу для засекречених середовищ:
- Блокування (конвеєр не вдається, образ не надсилається): будь-яка CVE критичної серйозності, будь-яка CVE високої серйозності у прямій залежності з підбалом використовуваності CVSS вище 7,0 або балом EPSS вище 0,05.
- Попередження та вимога відмови: CVE високої серйозності в транзитивних залежностях, CVE високої серйозності, для яких немає патча постачальника, CVE середньої серйозності.
- Лише інформаційний: знахідки низького рівня та незначні, CVE, що впливають на компоненти, які явно недосяжні в шляху виконання застосунку.
Кожна відмова повинна бути підписаним, обмеженим у часі документом, що пов'язує ідентифікатор CVE, обґрунтування (патч недоступний, компонент недосяжний, компенсуючий контроль), відповідального офіцера безпеки та дату закінчення дії, що ініціює повторну оцінку. Відмови, збережені як файли YAML, які перевіряються в коді репозиторію CI/CD, забезпечують аудиторський запис, що задовольняє вимоги до доказів ATO.
Підпис образів за допомогою Cosign/Sigstore у відключених середовищах
Підпис образів забезпечує криптографічний доказ того, що конкретний образ контейнера — ідентифікований за допомогою SHA-256 дайджесту вмісту — був створений авторизованим конвеєром і не був змінений після підписання. Cosign (частина проекту Sigstore Linux Foundation) став стандартним інструментом підпису образів для контейнерних середовищ, що продукує OCI-сумісні підписи, збережені як артефакти в тому самому реєстрі, що й образ.
Безключовий потік підпису Sigstore використовує OIDC-токени ідентичності та публічну інфраструктуру (Fulcio CA та журнал прозорості Rekor) для підпису образів без керування довгостроковими приватними ключами. Ця модель добре підходить для публічних CI/CD відкритого вихідного коду, але вимагає доступу до Інтернету — несумісно з ізольованими засекреченими середовищами. У відключених середовищах є два практичні варіанти:
- Підпис із ключем (рекомендується для засекречених). Генерація пари ключів Cosign; зберігання приватного ключа в HSM або схваленому менеджері секретів (HashiCorp Vault із сертифікованим FIPS бекендом, AWS CloudHSM або Azure Dedicated HSM). Крок підпису в конвеєрі CI/CD отримує посилання на ключ і підписує дайджест образу. Публічний ключ розподіляється контролерам допуску для перевірки. Зовнішня інфраструктура не потрібна.
- Приватний екземпляр Sigstore. Розгортання Fulcio та Rekor всередині засекреченої мережі. Це забезпечує UX безключового підходу та переваги журналу прозорості, але вимагає обслуговування додаткової інфраструктури, включаючи внутрішнього провайдера ідентичності OIDC. Підходить для великих програм із виділеними інженерними командами платформ.
# Генерація пари ключів Cosign (виконати один раз, зберегти приватний ключ в HSM/Vault)
cosign generate-key-pair --kms awskms:///arn:aws:kms:us-gov-east-1:123456789:key/abc-def
# Підписання образу після проходження шлюзів сканування — посилання на образ за дайджестом, а не тегом
IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' myapp:v1.2.3)
cosign sign \
--key awskms:///arn:aws:kms:us-gov-east-1:123456789:key/abc-def \
--tlog-upload=false \
registry.classified.mil/myapp@${IMAGE_DIGEST}
# Перевірка підпису (використовується контролерами допуску та під час ручних аудитів)
cosign verify \
--key /etc/cosign/cosign.pub \
--insecure-ignore-tlog=true \
registry.classified.mil/myapp@sha256:abc123...
Примусове застосування контролером допуску перевірки підписів образів заповнює розрив між підписанням конвеєра та розгортанням під час виконання. Правило verifyImages у ClusterPolicy Kyverno відхиляє будь-який под, що посилається на образ без дійсного підпису від схваленого публічного ключа Cosign. Політика також повинна вмикати mutateDigest: true, що переписує змінні посилання на теги до незмінних посилань на дайджест у специфікації пода під час допуску — забезпечуючи, що середовище виконання контейнера завантажує саме той образ, який був перевірений, а не наступний push до того самого тега.
Генерація SBOM для пакетів ATO
Перелік програмних компонентів (SBOM) — це машиночитаний інвентар кожного програмного компонента в розгорнутому артефакті — пакети ОС, бібліотеки середовища виконання мови, залежності застосунку та їх відносини. Для пакетів ATO SBOM надає авторизуючій посадовій особі видимість ланцюга постачання в розгорнуту систему та дедалі частіше є обов'язковим результатом відповідно до політики придбання програмного забезпечення DoD та вказівок CISA, що реалізують Виконавчий наказ 14028.
Syft (Anchore) — це стандартний генератор SBOM з відкритим вихідним кодом для образів контейнерів. Він сканує файлову систему образу шар за шаром, ідентифікує пакети як за записами бази даних пакетів ОС, так і за файлами блокування мовних екосистем, і виводить структуровані документи SBOM. Запуск Syft проти фінального дайджесту образу (а не Dockerfile або вихідного репозиторію) захоплює фактичний розгорнутий набір компонентів, включаючи пакети, встановлені транзитивно або додані під час процесу складання, яких немає явно в файлах залежностей застосунку.
# Генерація SBOM у форматах SPDX і CycloneDX з фінального образу
syft registry.classified.mil/myapp@sha256:abc123... \
-o spdx-json=/artifacts/sbom.spdx.json \
-o cyclonedx-json=/artifacts/sbom.cdx.json
# Прикріплення SBOM до образу в реєстрі (зберігається як OCI-артефакт)
cosign attach sbom \
--sbom /artifacts/sbom.spdx.json \
--type spdx \
registry.classified.mil/myapp@sha256:abc123...
# Перевірка прикріплення SBOM
cosign verify-attestation \
--key /etc/cosign/cosign.pub \
--insecure-ignore-tlog=true \
--type spdx \
registry.classified.mil/myapp@sha256:abc123...
Щодо питання SPDX проти CycloneDX: обидва формати прийняті вказівками CISA та здатні представляти ту саму інформацію про компоненти. SPDX (ISO/IEC 5962:2021) є старішим стандартом із сильнішим мандатом у урядових контекстах; CycloneDX має кращу підтримку інструментів для збагачення вразливостей через документи VEX (Vulnerability Exploitability eXchange). Для примусового застосування SBOM у оборонних конвеєрах генерація обох форматів з одного виклику Syft не коштує нічого і забезпечує сумісність із будь-яким інструментарієм ATO або вимогами авторизуючої посадової особи.
SBOM, поданий до AO, повинен супроводжуватися документом розкриття вразливостей, що відображає ідентифікатори компонентів SBOM на знахідки сканування та їх розпорядження (виправлено, відхилено з обґрунтуванням, не торкається). Цей комбінований пакет — дайджест образу, SBOM, результати сканування, відмови та підпис Cosign — формує набір доказів ланцюга постачання, який аудитори використовують для оцінки надійності розгорнутої системи.
Безпека реєстру образів контейнерів
Harbor — це сертифікований CNCF реєстр контейнерів, що найбільш широко розгортається в оборонних і засекречених середовищах. Його набір функцій відповідає конкретним операційним вимогам оборонних реєстрів: незмінність тегів, інтеграція довіри до вмісту з Cosign, контроль доступу на основі ролей, інтеграція сканування вразливостей (Trivy) та політики реплікації для багатоанклавних мереж реєстрів. Запуск Harbor у засекреченому середовищі вимагає уваги до кількох областей конфігурації, які налаштування за замовчуванням не застосовують.
Незмінність тегів запобігає будь-якій операції push від перезапису існуючого тега образу. Без цього контролю скомпрометований сервісний обліковий запис CI/CD або неправильно налаштований конвеєр міг би непомітно замінити схвалений, підписаний образ шкідливим або непідписаним під тим самим тегом. Правила незмінності тегів Harbor налаштовуються для кожного проекту і можуть бути обмежені конкретними шаблонами тегів — наприклад, блокування всіх тегів, що відповідають v[0-9]* (версії випусків), дозволяючи мінливі теги dev-* у проектах розробки.
Політика довіри до вмісту в Harbor інтегрується з Cosign для застосування перевірки підписів під час витягування. Коли довіра до вмісту увімкнена для проекту, проксі-шар Harbor викликає Cosign verify для кожного запиту на витягування образу та повертає помилку авторизації, якщо образ не має дійсного підпису від налаштованого публічного ключа. Це забезпечує застосування на рівні реєстру незалежно від контролера допуску Kubernetes — образи не можуть бути витягнуті навіть інструментами, що обходять вебхук допуску.
# Конфігурація проекту Harbor через CLI (harbor-cli або curl проти API Harbor)
# Увімкнення незмінності тегів для виробничого проекту
curl -X POST https://registry.classified.mil/api/v2.0/projects/mission-apps/immutabletagrules \
-H "Content-Type: application/json" \
-u "admin:${HARBOR_ADMIN_PASSWORD}" \
-d '{
"action": "immutableTagRule",
"scope_selectors": {"repository": [{"decoration": "repoMatches","pattern": "**"}]},
"tag_selectors": [{"decoration": "matches","pattern": "v[0-9]*"}]
}'
# Увімкнення сканування вразливостей при push для всіх проектів
curl -X PUT https://registry.classified.mil/api/v2.0/projects/mission-apps \
-H "Content-Type: application/json" \
-u "admin:${HARBOR_ADMIN_PASSWORD}" \
-d '{"metadata": {"auto_scan": "true", "severity": "critical"}}'
Кеш прокрутки Harbor виконує критичну функцію в багатоанклавних архітектурах. Підключений (нижчого рівня таємності) екземпляр Harbor налаштовується з проектами кешу проксі верхнього рівня, що вказують на схвалені зовнішні реєстри (Red Hat Registry, Iron Bank). На засекреченій стороні окремий екземпляр Harbor не має налаштованого реєстру верхнього рівня — він обслуговує лише образи, які були витягнуті через кеш на підключеній стороні, проскановані, підписані та фізично передані до засекреченого реєстру через схвалений механізм міждоменної передачі. Це створює контрольований робочий процес просування образів, де кожен образ повинен пройти контролі безпеки перед входом у засекречене середовище, а не покладаючись на застосування лише під час виконання.
Політика збирання сміття в Harbor видаляє позначені маніфести та невикористані шари за визначеним розкладом. У засекречених середовищах з обмеженою ємністю сховища збирання сміття запобігає необмеженому зростанню сховища реєстру по мірі заміни образів новими версіями. Рекомендована конфігурація виконує збирання сміття щотижня під час вікна технічного обслуговування, зберігає налаштовувану кількість історично тегованих образів на репозиторій для можливості відкату та генерує журнал видалень для аудиту. Видалення образів у засекреченому реєстрі повинно бути узгоджено з вимогами щодо збереження доказів ATO — артефакти SBOM та сканування для розгорнутих версій образів можуть потребувати збереження поза життєвим циклом образу.
Ключовий висновок: Безпека образів контейнерів — це не єдиний контроль, а ланцюг глибокого захисту: базові образи STIG зменшують успадковану поверхню вразливостей; багатоетапні збірки усувають невикористану поверхню атаки з образу часу виконання; сканування вразливостей під час збірки виявляє відомі CVE перед розгортанням; підпис образів забезпечує перевірку цілісності від збірки до виконання; генерація SBOM забезпечує прозорість ланцюга постачання для авторизації; контролі реєстру (незмінність, довіра до вмісту, кеш прокрутки) застосовують ланцюг на рівні розповсюдження. Прогалина в будь-якій ланці цього ланцюга — непідписаний образ, застаріла база даних вразливостей, змінний тег — є поверхнею атаки, яку противник із доступом до ланцюга постачання використає.