NODEDC_PLATFORM/docs/DEVOPS_SECURITY_HANDOFF.md

10 KiB
Raw Permalink Blame History

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:

  1. https://auth..., https://launcher..., https://task... открываются по HTTPS.
  2. HTTP делает redirect на HTTPS.
  3. Ответы содержат HSTS.
  4. Cookies выставляются как Secure и HttpOnly.
  5. Без login Launcher ведёт в Authentik.
  6. Active user видит все карточки сервисов, но открыть может только разрешённые сервисы.
  7. User без Task Manager app access видит карточку Task Manager в Launcher, не может открыть сервис и получает deny по прямому https://task....
  8. Blocked/annulled user теряет Launcher и Tasker session после hard refresh.
  9. Self-host workspace invite создаёт pending request в Launcher.
  10. Launcher-managed workspace не принимает self-service invite request из Tasker.
  11. Hard delete удаляет active Tasker WorkspaceMember/ProjectMember/IssueAssignee.
  12. Повторный accept уже принятого invite отклоняется.
  13. Internal endpoints без token дают 401.
  14. Audit содержит admin actions: approve/reject/access change/hard delete.
  15. Снаружи не доступны 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.