10 KiB
DevOps Security Handoff
Актуализировано: 2026-05-12.
Документ фиксирует границу передачи NODE.DC platform DevOps-инженеру. Локальная разработка закрывает код, конфиги, preflight и smoke-сценарии, которые можно честно проверить без реального staging host. DevOps закрывает серверные домены, TLS, secrets, firewall и финальную staging acceptance.
Что уже подготовлено локально
Platform / Authentik / reverse proxy
Репозиторий:
/Users/dcconstructions/Downloads/mnt/NODEDC/platform
Готовые артефакты:
docs/STAGING_SECURITY_PLAN.md
docs/SECURITY_CHECKLIST.md
infra/docker-compose.staging.example.yml
infra/reverse-proxy/Caddyfile.staging
infra/.env.staging.example
infra/scripts/check-staging-env.sh
Локально проверено:
cd platform/infra
NODEDC_STAGING_ENV_FILE=.env.staging.example docker compose --env-file .env.staging.example -f docker-compose.staging.example.yml config
docker run --rm --env-file .env.staging.example -v "$PWD/reverse-proxy/Caddyfile.staging:/etc/caddy/Caddyfile:ro" caddy:2-alpine caddy validate --config /etc/caddy/Caddyfile
./scripts/check-staging-env.sh .env.staging.example
Ожидаемый результат: compose и Caddyfile валидны; preflight на .env.staging.example падает, потому что example содержит placeholder secrets.
Launcher / control plane
Репозиторий:
/Users/dcconstructions/Downloads/mnt/data/nodedc_launcher
Подготовлено:
- control-plane snapshot перенесён из public static в server-only storage;
/storage/launcher-data.jsonзакрыт;/api/storage/dataи/api/storage/uploadтребуют session;/api/appsотдаёт каталог сервисов с флагами доступа; карточки сервисов видны всем authenticated users, но launch разрешён только при app access;- hard delete вызывает Tasker cleanup: sessions, identity links, workspace/project memberships, issue assignees;
- internal API token отделён от OIDC client secret;
- повторный accept уже принятого invite отклоняется.
Локально проверено:
cd nodedc_launcher
node --check server/dev-server.mjs
npm run build
npm test
curl -i http://launcher.local.nodedc/api/me
curl -i http://launcher.local.nodedc/api/apps
curl -i http://launcher.local.nodedc/api/services/task-manager/launch
Ожидаемый результат без session: 401.
Task Manager / Operational Core
Репозиторий:
/Users/dcconstructions/Downloads/mnt/data/dc_taskmanager/NODEDC_TASKMANAGER
Готовые артефакты:
plane-app/plane.env.staging.example
scripts/check-tasker-staging-env.sh
Подготовлено:
PLANE_NODEDC_ACCESS_TOKENбольше не fallback-ится наPLANE_OIDC_CLIENT_SECRET;- unlinked old sessions могут отзываться через
PLANE_NODEDC_ACCESS_ENFORCE_UNLINKED=1; - internal logout умеет чистить ExternalIdentityLink, WorkspaceMember, ProjectMember, IssueAssignee;
- self-host workspace invite снова создаёт pending request в Launcher;
- launcher-managed workspace отклоняет self-service invite request;
- Tasker proxy получает
TRUSTED_PROXIESиз env.
Локально проверено:
cd NODEDC_TASKMANAGER
docker compose --env-file plane-app/plane.env.staging.example -f plane-app/docker-compose.yaml config
./scripts/check-tasker-staging-env.sh plane-app/plane.env.staging.example
Ожидаемый результат: compose валиден; preflight на example падает из-за placeholder secrets.
Что DevOps должен сделать на сервере
Последний локальный smoke перед передачей
Выполнено 2026-05-12 после rebuild nodedc/plane-backend:local и nodedc/plane-frontend:ru, затем ./setup.sh stop && ./setup.sh start.
Контейнеры Tasker:
admin, api, beat-worker, live, plane-db, plane-minio, plane-mq, plane-redis, proxy, space, web, worker — Up
web/admin/space — healthy
HTTP smoke:
http://auth.local.nodedc/ -> 302
http://launcher.local.nodedc/healthz -> 200
http://task.local.nodedc/ -> 200
http://localhost:8090/ -> 200
Unauth negative paths:
GET http://launcher.local.nodedc/api/me -> 401
GET http://launcher.local.nodedc/api/apps -> 401
GET http://launcher.local.nodedc/api/services/task-manager/launch -> 401
POST http://launcher.local.nodedc/api/internal/access/check without token -> 401
POST http://task.local.nodedc/api/internal/nodedc/logout/ without token -> 401
Этот smoke закрывает локальную runtime-ready часть. Он не заменяет DevOps staging smoke на реальных HTTPS-доменах.
1. Подготовить DNS и host
Выбрать реальные домены:
auth.<staging-domain>
launcher.<staging-domain>
task.<staging-domain>
Все DNS-записи должны указывать на staging host или ingress. Порты 80/tcp и 443/tcp должны быть доступны снаружи для TLS/ACME.
2. Создать реальные env-файлы
Platform:
cd platform/infra
cp .env.staging.example .env.staging
Tasker:
cd NODEDC_TASKMANAGER
cp plane-app/plane.env.staging.example plane-app/plane.env.staging
Заменить все replace-with-* на реальные значения. Нельзя использовать local/dev secrets, change-me, local-dev, .local.nodedc, localhost.
Обязательное правило:
NODEDC_INTERNAL_ACCESS_TOKENдолжен совпадать сPLANE_NODEDC_ACCESS_TOKEN;NODEDC_INTERNAL_ACCESS_TOKENне должен совпадать ни с одним OIDC client secret;LAUNCHER_OIDC_CLIENT_SECRETиPLANE_OIDC_CLIENT_SECRETдолжны быть разными;COOKIE_SECURE=true;- все public/OIDC/internal URLs должны быть
https://.
3. Ограничить proxy trust
В staging нельзя оставлять broad ranges:
0.0.0.0/0
::/0
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
127.0.0.0/8
Нужно указать только фактический subnet reverse proxy / ingress:
AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS=<edge-or-ingress-cidr>
TRUSTED_PROXIES=<edge-or-ingress-cidr>
4. Прогнать preflight
Platform:
cd platform/infra
./scripts/check-staging-env.sh .env.staging
docker compose --env-file .env.staging -f docker-compose.staging.example.yml config
Tasker:
cd NODEDC_TASKMANAGER
./scripts/check-tasker-staging-env.sh plane-app/plane.env.staging
docker compose --env-file plane-app/plane.env.staging -f plane-app/docker-compose.yaml config
Preflight обязан пройти на реальных env-файлах. Если падает — staging не запускать.
5. Поднять runtime
Platform:
cd platform/infra
docker compose --env-file .env.staging -f docker-compose.staging.example.yml up -d
Tasker команда зависит от выбранной topology. Если используется текущий Plane runtime:
cd NODEDC_TASKMANAGER
docker compose --env-file plane-app/plane.env.staging -f plane-app/docker-compose.yaml up -d
Если Tasker стоит за platform reverse proxy, наружу публикуется только platform edge. Postgres, Redis/Valkey, MinIO, RabbitMQ, Authentik server/worker, Launcher BFF и Tasker API не публикуются напрямую наружу.
6. Bootstrap Authentik
Создать/обновить:
- отдельное Application/Provider для Launcher;
- отдельное Application/Provider для Tasker;
- отдельные OIDC client secrets;
- группы
nodedc:superadmin,nodedc:launcher:admin,nodedc:launcher:user,nodedc:taskmanager:admin,nodedc:taskmanager:user; - access policies для каждого приложения;
- redirect/logout URI только на staging HTTPS domains.
7. Проверить финальный staging smoke
Минимальный smoke:
https://auth...,https://launcher...,https://task...открываются по HTTPS.- HTTP делает redirect на HTTPS.
- Ответы содержат HSTS.
- Cookies выставляются как
SecureиHttpOnly. - Без login Launcher ведёт в Authentik.
- Active user видит все карточки сервисов, но открыть может только разрешённые сервисы.
- User без Task Manager app access видит карточку Task Manager в Launcher, не может открыть сервис и получает deny по прямому
https://task.... - Blocked/annulled user теряет Launcher и Tasker session после hard refresh.
- Self-host workspace invite создаёт pending request в Launcher.
- Launcher-managed workspace не принимает self-service invite request из Tasker.
- Hard delete удаляет active Tasker WorkspaceMember/ProjectMember/IssueAssignee.
- Повторный accept уже принятого invite отклоняется.
- Internal endpoints без token дают
401. - Audit содержит admin actions: approve/reject/access change/hard delete.
- Снаружи не доступны Postgres, Redis/Valkey, MinIO, RabbitMQ, Authentik server/worker, Launcher BFF и Tasker API-порты.
Что не входит в текущую передачу
- billing;
- тарифы;
- email automation;
- production HA/backup automation;
- production monitoring/SIEM;
- public self-service без ручного approve.
Эти темы не являются блокерами текущего закрытого demo release.