Стандартні CI/CD конвеєри побудовані на припущенні про повсюдну наявність вихідного інтернет-з'єднання. Кожен раннер завантажує базовий образ із публічного реєстру, кожна збірка розв'язує залежності з upstream-репозиторіїв пакетів, кожен інструмент сканування завантажує актуальні підписи вразливостей під час запуску. У засекреченому, ізольованому оборонному середовищі жодне з цих припущень не виконується — і інженерні наслідки охоплюють кожен рівень інструментарію. Цей посібник розглядає архітектурні рішення, вибір інструментарію та операційні процедури, які забезпечують роботу безперервної інтеграції та доставки за відсутності доступу до Інтернету, на інфраструктурі, загартованій за STIG, всередині межі акредитації.
Чому стандартний CI/CD не працює в ізольованих оборонних середовищах
Збій — це не одна відсутня функція, а каскад припущень, вбудованих у кожен сучасний CI/CD-інструмент, який руйнується при контакті з межею акредитації ізольованого середовища. Розуміння цих збоїв заздалегідь запобігає марним циклам закупівель та архітектурним змінам в останній момент під час перевірки ATO.
Мережева ізоляція. Засекречений анклав рівня Secret і вище не має вихідного доступу до Інтернету за своєю суттю. Раннери не можуть завантажувати образи з Docker Hub, Maven Central, npmjs.com або PyPI. Інструменти збірки, що завантажують плагіни або розширення під час першого використання, зазнають тихих збоїв або виводять незрозумілі повідомлення про недоступні хости. Механізми оновлення в Jenkins, GitLab та більшості комерційних CI-інструментів надсилають запити додому під час запуску — цей трафік блокується та часто генерує шум у консолі мережевого моніторингу, який ISSM має пояснювати AO.
Затвердження та акредитація програмного забезпечення. Кожен програмний компонент, розгорнутий всередині межі акредитації DoD, має бути затверджений Уповноваженою посадовою особою (AO) як частина Пакету авторизації системи. Це стосується не лише CI-сервера, а й кожного плагіна, кожного образу агента збірки, кожної бібліотеки, від якої залежить сам конвеєр. «Ми використаємо останню версію з публічного реєстру» — неприйнятна відповідь у контексті ATO. Список затвердженого програмного забезпечення є контрольованим документом; додавання нових пакетів вимагає офіційного запиту, сканування на вразливості, перевірки ліцензії та — для пакетів без наявного покриття STIG — додаткового навантаження на документацію для інженерної команди. Цей процес зазвичай займає від кількох днів до тижнів на пакет, що робить ситуативне додавання залежностей несумісним із темпом розробки, якого вимагає сучасний CI-конвеєр. Рішення полягає у виконанні процесу затвердження наперед, шляхом визначення кожної залежності до розгортання конвеєра, а не після.
Закупівля інструментів та ліцензування. Деякий CI-інструментарій безпосередньо доступний державним підрядникам. Деякий вимагає конкретних ліцензійних угод для державного використання, деякий вимагає перевірки на предмет експортного контролю (класифікація ITAR/EAR). Jenkins OSS та GitLab CE уникають більшості цих проблем, що частково пояснює їхнє домінування у засекречених середовищах. Комерційні CI-платформи, що постачаються разом із власними раннерами, керованими службами секретів або хмарною аналітикою, зазвичай не підходять для ізольованого анклаву без значних архітектурних змін.
Кінцевий результат: air-gapped CI/CD необхідно проектувати з нуля, а не адаптувати з комерційного SaaS-патерну. Будівельні блоки доступні та перевірені — вони просто вимагають явного офлайн-забезпечення для кожного компонента, який стандартний конвеєр розв'язує динамічно. Щодо ширшого контексту DevSecOps, який регулює ці рішення, дивіться наш посібник із DevSecOps для оборонних конвеєрів.
Архітектура офлайн-реєстру артефактів
Реєстр артефактів є якорем ланцюга постачання для ізольованого середовища збірки. Кожна залежність — JAR-файли, npm-пакети, Python wheels, Go-модулі, RPM-пакети — повинна обслуговуватися зсередини анклаву. Два продукти домінують у цьому просторі у засекречених середовищах: Sonatype Nexus Repository (OSS та Pro) і JFrog Artifactory (OSS та Pro). Обидва розгортаються на RHEL без необхідності вихідного з'єднання для роботи; обидва підтримують формати репозиторіїв, які потрібні типовому проекту оборонного програмного забезпечення.
Топологія має дві половини. На незахищеному боці (з підключенням до Інтернету, але не засекреченому) робоча станція куратора запускає ту саму версію Nexus або Artifactory, що й екземпляр на захищеному боці. Куратор використовує вбудований інструментарій експорту/імпорту менеджера репозиторіїв або скриптовий робочий процес для завантаження затверджених артефактів, розв'язання їхніх транзитивних залежностей, перевірки контрольних сум за опублікованими хешами upstream-реєстру та складання підписаного пакету для передачі. Крок підписання є критичним: пакет передачі має бути підписаний ключем передачі програми, щоб система на захищеному боці могла перевірити цілісність перед імпортом чого-небудь.
# Low-side curator: assemble and sign the transfer bundle
nexus-curator export \
--format maven \
--repos approved-central-proxy \
--output /transfer/bundle-2026-06-24.tar.gz
# Generate SHA-256 manifest
sha256sum /transfer/bundle-2026-06-24.tar.gz \
> /transfer/bundle-2026-06-24.manifest
# GPG-sign the manifest with the program transfer key
gpg --detach-sign --armor \
--local-user transfer@program.mil \
/transfer/bundle-2026-06-24.manifest
# Physical transfer via encrypted removable media or data diode
# ...
# High-side import: verify before extracting
gpg --verify bundle-2026-06-24.manifest.asc \
bundle-2026-06-24.manifest
sha256sum -c bundle-2026-06-24.manifest
nexus-curator import --file bundle-2026-06-24.tar.gz
На захищеному боці екземпляр Nexus або Artifactory обслуговує лише розміщені репозиторії — проксі-репозиторії, що вказують на зовнішні URL, відсутні, оскільки ці URL недоступні. Конфігураційні файли інструментів агента збірки посилаються лише на внутрішнє ім'я хосту. Таблиця конфігураційних файлів, що потребують модифікації:
| Екосистема | Конфігураційний файл | Ключове налаштування |
|---|---|---|
| Maven | ~/.m2/settings.xml |
<mirror> що вказує на внутрішній Nexus |
| npm / Node.js | .npmrc |
registry=https://nexus.enclave.mil/repository/npm-hosted/ |
| Python / pip | pip.conf |
index-url = https://nexus.enclave.mil/repository/pypi-hosted/simple/ |
| Go | GONOSUMCHECK / GOFLAGS |
GOPROXY=https://nexus.enclave.mil/repository/go-proxy/ |
| Образи контейнерів | /etc/containers/registries.conf |
unqualified-search-registries = ["harbor.enclave.mil"] |
Частота кураторства є питанням політики: як правило, щомісячно для виправлень безпеки, щоквартально для нових версій залежностей, та негайно для будь-якого CVE з оцінкою CVSS вище 8,0. Рада конфігураційного управління програми приймає рішення щодо кожного імпорту.
CI-сервер, загартований за STIG: Jenkins або GitLab на засекреченій інфраструктурі
Два найпоширеніші варіанти для виконання CI на засекреченій інфраструктурі — це Jenkins (тривалий домінуючий варіант, широко розгорнутий у програмах DoD з середини 2010-х років) та GitLab (який все більше віддається перевагу для нових програм завдяки опублікованому DISA STIG та інтегрованим функціям DevSecOps). Обидва можна привести у відповідність; зусилля та профіль залишкового ризику відрізняються.
Для Jenkins базова лінія загартування — це DISA Application Server SRG у поєднанні з RHEL 9 STIG для базової ОС. Контрольний список загартування, специфічний для Jenkins, охоплює такі сфери:
- Вимкніть Jenkins CLI через remoting (клас вразливостей CVE-2024-23897); використовуйте CLI лише через SSH за потреби.
- Увімкніть заголовки Content Security Policy (CSP) для запобігання XSS у виводі консолі збірки.
- Вимкніть доступ до Script Console для не-адміністраторів; обмежте виходи з Groovy sandbox.
- Налаштуйте матричну безпеку з принципом найменших привілеїв: розробники можуть запускати збірки, але не можуть адмініструвати агентів або облікові дані.
- Увімкніть плагін audit-log; пересилайте журнали до SIEM анклаву.
- Розмістіть
JENKINS_HOMEу файловій системі з контролем доступу; обмежте права читання для всіх наcredentials.xml. - Вимкніть підключення до сайту оновлень (
hudson.model.UpdateCenter.never=trueуjenkins.properties). - Запускайте Jenkins від виділеного облікового запису служби без прав root; застосуйте контексти SELinux.
GitLab CE/EE на RHEL отримує переваги від DISA GitLab Enterprise Edition STIG (V1R1, опублікований 2022), який безпосередньо пов'язує елементи керування з налаштуваннями конфігурації GitLab. Ключові елементи керування включають застосування мінімуму TLS 1.2, вимкнення реєстрації та OAuth-провайдерів, увімкнення подій аудиту в syslog, обмеження протоколу Git SSH через відомий порт та вимкнення функцій auto-DevOps, що здійснюють вихідні виклики. Інтегрований реєстр GitLab, робочий процес merge request та синтаксис YAML конвеєра зменшують кількість окремо акредитованих компонентів порівняно з Jenkins-орієнтованим стеком, що часто є вирішальним фактором у програмах із жорсткими термінами ATO.
В будь-якому випадку агенти збірки мають працювати всередині тієї самої межі класифікації, що й контролер. Образи агентів будуються з затверджених базових образів, що зберігаються у реєстрі контейнерів анклаву, та перебудовуються за визначеним графіком (як правило, щомісячно) для включення оновлень ОС, переданих через робочий процес кураторства.
Відключений реєстр контейнерів
Образи контейнерів у ізольованому конвеєрі мають зберігатися, скануватися та підписуватися всередині анклаву. Два продукти найбільш поширені: Harbor (з CNCF-статусом, широко використовується у середовищах DoD Platform One) та Red Hat Quay (підтримується за корпоративною угодою DoD з Red Hat, тісно інтегрується з OpenShift). Обидва підтримують підписання образів OCI, рольовий контроль доступу та сканування на вразливості з офлайн-базами даних.
Початкове заповнення реєстру відбувається за тим самим робочим процесом передачі, що й реєстр артефактів: затверджені базові образи (RHEL UBI, загартовані образи Iron Bank, затверджені базові рівні додатків) експортуються з незахищеного боку як OCI-архіви, передаються та імпортуються в Harbor або Quay за допомогою skopeo copy:
# Low side: export approved images as OCI tarballs
skopeo copy \
docker://registry.access.redhat.com/ubi9/ubi:9.4 \
oci-archive:/transfer/ubi9-9.4.tar \
--override-os linux
# Generate and sign manifest
sha256sum /transfer/ubi9-9.4.tar >> /transfer/images.manifest
gpg --detach-sign --armor --local-user transfer@program.mil \
/transfer/images.manifest
# High side: verify and import
gpg --verify images.manifest.asc images.manifest
sha256sum -c images.manifest
skopeo copy \
oci-archive:/transfer/ubi9-9.4.tar \
docker://harbor.enclave.mil/base/ubi9:9.4 \
--dest-creds admin:${HARBOR_TOKEN}
Підписання образів за допомогою Cosign в офлайн-режимі використовує довгостроковий ключ підписання, збережений у рушії Transit анклавного Vault, оминаючи журнал прозорості Sigstore (який розміщений в Інтернеті). Ключ підписання генерується всередині Vault і ніколи не експортується; CI-конвеєр викликає API Transit Vault для підписання хешу образу та прикріплює отриманий підпис як OCI-артефакт поруч із маніфестом образу в Harbor. Перевірка під час допуску здійснюється політикою Kyverno, яка викликає верифікатор Cosign для Harbor з використанням внутрішнього пакету довіри PKI анклаву.
# Sign image using Vault Transit key (no transparency log)
cosign sign \
--key hashivault://transit/keys/image-signing-key \
--no-tlog-upload \
harbor.enclave.mil/myapp/service:v1.4.2@sha256:abc123...
# Kyverno policy: require valid Cosign signature on every pod
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: check-image-signature
match:
resources:
kinds: [Pod]
verifyImages:
- imageReferences: ["harbor.enclave.mil/*"]
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
... (enclave signing public key) ...
-----END PUBLIC KEY-----
rekor:
ignoreTlog: true
Сканування на вразливості всередині реєстру використовує Trivy або Grype, налаштований із офлайн-пакетом бази даних. База даних вразливостей (NVD, OSV, поради RedHat) завантажується на незахищеному боці, передається на захищений бік та завантажується у локальний шлях бази даних сканера. Щоденний конвеєрний завдання оновлює пакет бази даних через робочий процес кураторства, підтримуючи актуальність знань сканера в межах циклу передачі.
Робочий процес транспортування програмного забезпечення: від sneakernet до захищеного сервера оновлень
Термін «sneakernet» передує CI/CD, але концепція саме і забезпечує роботу ізольованої доставки програмного забезпечення: фізичне транспортування даних між мережами різних рівнів класифікації. У сучасних засекречених об'єктах це транспортування систематизовано у задокументований робочий процес із обов'язковими воротами, журналами аудиту та вимогами щодо ланцюжка зберігання, що відображають те, що автоматизовані засоби контролю ланцюга постачання забезпечують у підключеному середовищі. Виклик для CI/CD конвеєрів полягає в тому, що час циклу передачі — який зазвичай вимірюється днями, а не мілісекундами — має бути закладений у модель планування випусків.
Робочий процес має чітку структуру:
Low-side workstation (UNCLASSIFIED)
│
├─ [1] Assemble candidate package set
│ - download, resolve transitive deps
│ - verify upstream signatures/checksums
│ - run malware scan (ClamAV / commercial AV)
│ - run vulnerability scan (Grype offline db)
│ - license review
│
├─ [2] Generate signed manifest
│ sha256sum * > manifest.txt
│ gpg --detach-sign manifest.txt
│
├─ [3] Submit transfer request (CMT/JIRA ticket)
│ - package name, version, purpose, license
│ - vulnerability scan results attached
│
├─ [4] ISSO/AO review and approval (Gate)
│
├─ [5] Physical transfer
│ - encrypted USB (FIPS 140-2 validated)
│ - OR hardware data diode (one-way)
│ - transfer log entry created
│
High-side secure update server (CLASSIFIED)
│
├─ [6] Verify manifest signature
│ gpg --verify manifest.txt.asc manifest.txt
│ sha256sum -c manifest.txt
│
├─ [7] Import into Nexus / Harbor
│
└─ [8] Log in configuration management tool
Підписання пакетів використовує GPG з ключами, специфічними для програми, або — у програмах, що прийняли інструментарій на основі PKI — sigstore/cosign проти внутрішнього екземпляра Rekor програми. Ключовий момент: ключ підписання, що використовується для маніфестів передачі, відрізняється від ключа, що використовується для підписання артефактів збірки. Ключ передачі утримується роллю куратора, а не автоматизованими агентами збірки, оскільки затвердження передачі є людськими воротами, які не повинні бути автоматизованими.
Для програм із високим темпом виправлень, односпрямовані апаратні діоди даних (такі як від Owl Cyber Defense або Waterfall Security) автоматизують фізичний рівень передачі, зберігаючи однонаправлену гарантію. Дані течуть лише від незахищеного до захищеного боку; система на захищеному боці не може надсилати жодного трафіку назад. Це не усуває ворота затвердження, але усуває крок з фізичним знімним носієм і може використовуватися для передачі нічних пакетів виправлень за визначеним графіком. Дивіться наше детальніше висвітлення безпеки ланцюга постачання для оборонного програмного забезпечення щодо політичної основи, яка регулює те, що потрапляє у робочий процес передачі.
Автоматизація відповідності STIG у конвеєрі
Ручні контрольні списки STIG несумісні з темпом безперервної доставки. Збірка, що розгортається щодня, не може бути вручну перевірена за 300+ елементами керування STIG перед кожним випуском. Рішення — це відповідність як код: кодування елементів керування STIG як машинно-перевірюваної політики, виконання політики у конвеєрі як автоматизованих воріт та генерація структурованих доказів, що задовольняють вимоги безперервного моніторингу AO.
Основний інструментарій — це OpenSCAP із SCAP Security Guide (SSG). SSG постачає XCCDF/OVAL-вміст для RHEL 8, RHEL 9 та споріднених дистрибутивів, який безпосередньо відповідає DISA STIG. У ізольованому середовищі вміст SSG вбудовується в образ агента збірки, а не завантажується під час виконання:
# Pipeline stage: STIG scan of a deliverable container image
stages:
- build
- stig-scan
- sign
- promote
stig-scan:
stage: stig-scan
image: harbor.enclave.mil/tools/openscap-runner:latest
script:
- |
# Mount the container image filesystem for scanning
skopeo copy \
docker://harbor.enclave.mil/${CI_PROJECT_PATH}:${CI_COMMIT_SHA} \
oci:./image-under-test
# Run STIG profile evaluation
oscap-chroot ./rootfs xccdf eval \
--profile xccdf_org.ssgproject.content_profile_stig \
--results stig-results.xml \
--report stig-report.html \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Block on any CAT I (high severity) failures
python3 /tools/parse-stig-results.py \
--results stig-results.xml \
--fail-on-severity high \
--output stig-summary.json
artifacts:
paths:
- stig-results.xml
- stig-report.html
- stig-summary.json
expire_in: 90 days
Застосунок DISA STIG Viewer може завантажувати вивід results.xml з OpenSCAP та відображати його у знайомому форматі контрольного списку, який AO та ISSO використовують під час перевірок. Для програм, що ведуть інформаційну панель безперервного моніторингу (як правило, з передачею даних до SIEM або GRC-інструменту), структурований вивід JSON зі скрипта розбору надсилається до репозиторію доказів як артефакт конвеєра разом зі збіркою.
Поширеним патерном є розділення STIG-сканування рівня хосту (яке виконується командою інфраструктури для базових образів агентів збірки щомісяця) від STIG-сканування рівня образу (яке виконується конвеєром застосунку при кожній збірці для образу контейнера, що постачається). Знахідки рівня хосту впливають на ATO самої CI-інфраструктури та відстежуються у POA&M системи. Знахідки рівня образу відстежуються на рівні застосунку та є відповідальністю команди розробки. Журнал аудиту чітко розмежовує, яка команда є відповідальною за яку знахідку, що важливо, коли акредитор переглядає пакет доказів безперервного моніторингу.
Для застосування SBOM в оборонних конвеєрах, вивід сканування STIG доповнює SBOM, надаючи докази того, що середовище виконання, в якому буде виконуватися артефакт, також відповідає вимогам — а не лише програмні компоненти артефакту.
Управління секретами без інтернету: HashiCorp Vault у режимі ізоляції
Управління секретами — це компонент, який найімовірніше буде погано імпровізований у ізольованих середовищах. Поширена імпровізація — зберігання облікових даних у вбудованому сховищі облікових даних CI-сервера, у спільному менеджері паролів або у змінних середовища, вбудованих в образи агентів — не проходить ті самі елементи керування аудитом, які провалюються у підключеному середовищі. Затверджене рішення — це виділена система управління секретами, розгорнута всередині межі акредитації.
HashiCorp Vault OSS (відкрите джерело, а не Enterprise) не вимагає інтернет-з'єднання для роботи. Він може бути розгорнутий на RHEL-хості, загартованому за STIG, всередині анклаву, ініціалізованого з поділом ключів Shamir, розподіленим між авторизованими хранителями ключів:
# Initialize Vault with 5 key shares, threshold of 3
vault operator init \
-key-shares=5 \
-key-threshold=3
# Example output (each share goes to a separate custodian):
# Unseal Key 1: AbCdEf...
# Unseal Key 2: GhIjKl...
# Unseal Key 3: MnOpQr...
# Unseal Key 4: StUvWx...
# Unseal Key 5: YzAbCd...
# Initial Root Token: hvs.XXXXXX (use once, then revoke)
# Unseal using 3 of 5 shares (separate operator ceremony)
vault operator unseal # enter share 1
vault operator unseal # enter share 2
vault operator unseal # enter share 3
Початкове налаштування PKI у ізольованому середовищі використовує вбудований рушій секретів PKI Vault для управління сертифікатною інфраструктурою програми. Процес: генерація кореневого ключа CA та сертифіката в офлайн-режимі (на ізольованій робочій станції, а не всередині Vault), зберігання кореневого ключа CA в апаратному HSM або зашифрованій офлайн-резервній копії відповідно до плану управління ключами програми. Імпорт кореневого сертифіката CA у Vault. Всередині рушія PKI Vault генерація пари ключів проміжного CA та CSR, підписання CSR кореневим CA (офлайн-крок), імпорт підписаного проміжного сертифіката у Vault. Відтепер Vault видає всі короткострокові TLS-сертифікати для служб анклаву — CI-сервера, реєстру артефактів, реєстру контейнерів, самого менеджера секретів — без будь-якої зовнішньої залежності від CA.
Автентифікація CI-агентів використовує метод аутентифікації AppRole Vault. Кожен агент збірки забезпечується role_id (не секретним, може бути у конфігурації агента) та secret_id (короткостроковим, що вводиться постачальником інфраструктури під час запуску агента). Агент обмінює їх на токен Vault, обмежений лише секретами, необхідними для його збірок. Токени є короткостроковими (1 годину за замовчуванням, можна поновити під час збірки) і автоматично закінчуються після завершення збірки. Цей патерн означає, що скомпрометований агент збірки не має постійного доступу до секретів — він утримує лише токен, який закінчується, а не облікові дані, що зберігаються безстроково.
Ротація секретів без доступу до Інтернету відбувається за запланованим ритуалом: квартальна ротація статичних секретів (ключі API, паролі службових облікових записів), річна ротація ключів підписання. Вбудовані політики ротації Vault відстежують час; результат кожної ротації записується в журнал аудиту Vault, який пересилається до SIEM анклаву. Для динамічних секретів — облікових даних бази даних, PKI-сертифікатів — рушії динамічних секретів Vault генерують облікові дані для кожної збірки з короткими TTL, роблячи ротацію несуттєвою подією, оскільки кожен обліковий запис вже є ефемерним.
Підсумок архітектури: Готовий до виробництва air-gapped CI/CD стек має шість рівнів — (1) офлайн-реєстр артефактів (Nexus/Artifactory), (2) CI-сервер, загартований за STIG (Jenkins/GitLab), (3) відключений реєстр контейнерів (Harbor/Quay) з підписанням Cosign, (4) робочий процес транспортування програмного забезпечення з підписаними маніфестами та воротами затвердження, (5) автоматизоване STIG-сканування (OpenSCAP + SSG) у кожному запуску конвеєра та (6) HashiCorp Vault для секретів та PKI. Кожен рівень може бути зібраний поетапно, але всі шість мають бути присутніми до подання конвеєра на перевірку ATO. Стек, у якому відсутній будь-який із цих рівнів, генеруватиме елементи POA&M, що блокують акредитацію.
Операційна дисципліна, необхідна для роботи цього стеку, є нетривіальною. Ролі кураторів, процедури затвердження передачі, ритуали зберігачів ключів та щомісячний графік сканування — це організаційні зобов'язання, а не одноразові інженерні рішення. Програми, що інвестують у документування цих процедур як частини Плану безпеки системи (SSP), а не як неформальні племінні знання, значно більш стійкі до плинності кадрів — що, враховуючи вимоги до допуску та ринок оборонної праці, є реалістичним операційним ризиком для кожної довгострокової програми.
Щодо рівня політики ланцюга постачання, який регулює те, що потрапляє в конвеєр, дивіться нашу статтю про застосування SBOM в оборонних конвеєрах. Описаний тут air-gapped CI-стек є рівнем виконання; застосування SBOM та ширша основа DevSecOps для оборонних конвеєрів є рівнем політики, який визначає, що конвеєр збирає, сканує та атестує.