
Доказательства SOC 2, которые собираются сами в GitLab CI: каждый merge создаёт подписанный пакет, шлюз OPA блокирует релизы при отсутствии подтверждений, а аудиторы получают одну ссылку вместо скриншотов.
Доказательства SOC 2, которые собираются сами в GitLab CI: каждый merge создаёт подписанный пакет, шлюз Open Policy Agent блокирует релизы при отсутствии доказательств, а аудитор получает одну ссылку на пакет вместо скриншотов.
Живая панель аудитора · Проект GitLab · Демонстрационные доказательства · Дорожная карта
Я создал ShipProof, потому что корпоративные продажи раз за разом застревают на этапе проверки информационной безопасности. Когда аудитор запрашивает доказательства управления изменениями по SOC 2 Type II, инженеры часто тратят две недели на поиск скриншотов в Jira, Slack и Drive.
Я хотел, чтобы доказательства жили непосредственно в конвейере развёртывания. Каждый merge-коммит в ShipProof автоматически создаёт канонический подписанный пакет доказательств, охватывающий прогоны тестов, SAST-сканирование Semgrep, обнаружение секретов Gitleaks, спецификации состава ПО Syft и одобрения CODEOWNERS.
Моё главное правило проектирования строгое: LLM может суммировать доказательства или составлять черновики описаний задач, но никогда не может одобрить релиз. Шлюз релиза — это оценка Open Policy Agent, написанная на Rego. Если артефакт отсутствует или одобрение выглядит как формальность, шлюз срабатывает по принципу fail-closed, останавливает релиз и создаёт задачу с путём исправления. Когда шлюз разрешает, аудитор получает единственную ссылку на статический сайт или аутентифицированный API.
Я сопоставил ShipProof с жизненным циклом GitLab DevOps. Он автоматизирует все девять этапов нативно:
| Этап | Что я автоматизировал в конвейере |
|---|---|
| plan | Замкнутое управление задачами о пробелах. Отказы шлюза автоматически открывают структурированные задачи отслеживания со счётчиками повторений; последующие успешные конвейеры автоматически разрешают и закрывают задачи со ссылками на коммиты исправлений. |
| create | Ревью кода и управление исходниками. CODEOWNERS защищает файлы политик; шлюз отклоняет формальные одобрения менее чем за пять минут; автоматические заметки в MR направляют ревью; потоки Duo описывают комментарии в MR. |
| verify | pytest, Semgrep SAST и Gitleaks выполняются на этапе verify, записывая хеши артефактов. |
| package | Syft генерирует SBOM CycloneDX на этапе package и хеширует артефакт в пакет. |
| secure | Детерминированный шлюз OPA проверяет подписи, хеши цепочки и правила формальных одобрений перед релизом. |
| release | Задача шлюза соответствия блокирует развёртывание в production; задачи развёртывания требуют вердикта разрешения. |
| configure | Манифесты развёртывания Cloud Run формируются из переменных окружения без коммита секретов. |
| monitor | Проверки после развёртывания подтверждают, что дайджесты работающих образов контейнеров совпадают с одобренным в пакете коммитом. |
| govern | Неизменяемый хеш-цепочный журнал питает пакеты для аудитора, задачи о пробелах и панель GitLab Pages. |
Я разрабатывал ShipProof с Python 3.11 и Node.js 20.
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Запустите мой набор тестов и проверки типов:
OPA_BIN=/tmp/opa pytest -q && ruff check src tests demo-app scripts && mypy --strict src scripts
Соберите локальный bundle для любого коммита:
PYTHONPATH=src python -m comply.collect --sha aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --out /tmp/bundle.json
Коллектор выводит одну строку JSON в stdout и записывает полный пакет на диск рядом с policy/inputs.json. Если доказательства отсутствуют, в пакете фиксируется статус отказа.
PYTHONPATH=src python -m comply.collect --sha <40-hex-sha> --out evidence/bundle.json \
--mr-iid 42 --pipeline-id 1001 --project group/project \
--pipeline-file pipeline.json --approvals-file approvals.json
В CI scripts/gate_bridge.py подготавливает pipeline.json, а scripts/fetch_approvals.py извлекает данные проверок из GitLab API. Отсутствующие файлы фиксируются со статусом «отсутствует», а не считаются автоматически пройденными. Каждый лог stderr содержит корреляционный ID пакета, а секреты маскируются как ***.
PYTHONPATH=src python -m comply.gate --bundle evidence/bundle.json --ledger logs/ledger.jsonl
Код выхода 0 означает вердикт «разрешено». Код выхода 1 означает отказ со структурированной ошибкой, указывающей на не пройденный контроль. Код выхода 2 означает недопустимые аргументы. Когда шлюз блокирует в CI, конвейер запускает python -m comply.gap, чтобы открыть отслеживающую задачу.
PYTHONPATH=src python -m comply.packet --ledger logs/ledger.jsonl --release all \
--out packet.json --csv packet.csv --pdf packet.pdf
CSV-экспорт содержит одиннадцать столбцов: bundle_id,commit_sha,mr_iid,pipeline_id,control,proof_type,status,artifact_sha,approver_ids,policy_sha,created_at. PDF формируется из того же источника JSON с помощью print CSS.
AUDITOR_TOKEN=local-only PYTHONPATH=src uvicorn comply.api:app --port 8000
Запросы к бандлам с использованием bearer-аутентификации:
curl -H "Authorization: Bearer local-only" "localhost:8000/api/v1/bundles?mr_iid=42"
API предоставляет конечные точки для запросов пакетов, релизных пакетов и фонового экспорта PDF, защищённые bearer-токенами и ограничением в 60 запросов в минуту.
cd auditor && npm install && npm run build
Интерфейс построен на React 19, TypeScript и Tailwind CSS. Он экспортируется как статический сайт с хеш-маршрутизацией, что позволяет запускать его напрямую на GitLab Pages без серверных перезаписей. При отсутствии backend API используются примеры данных из public/fallback/demo-packets.json.
flowchart LR
A["CI jobs (pytest, Semgrep, Gitleaks, Syft)"] --> B["gate_bridge.py (artifact summary)"]
B --> C["comply.collect (bundle.json + inputs.json)"]
C --> D["comply.sign (Cosign, HMAC fallback)"]
D --> E["ledger.jsonl (hash chain)"]
E --> F["comply.gate (OPA policy + signature + chain)"]
F -->|"deny"| G["comply.gap (gap issue + MR comment)"]
F -->|"allow"| H["deploy jobs (gated)"]
E --> I["comply.packet (JSON, CSV, PDF)"]
I --> J["GitLab Pages dashboard + read API"]