SECURITY - PLATFORM: internal token and staging plan
This commit is contained in:
parent
9d7f8167d3
commit
95072586b9
|
|
@ -1,5 +1,7 @@
|
|||
# Security Checklist
|
||||
|
||||
Staging path and runbook: `docs/STAGING_SECURITY_PLAN.md`.
|
||||
|
||||
## Network
|
||||
|
||||
- [x] Local dev compose публикует только reverse proxy port.
|
||||
|
|
@ -26,6 +28,8 @@
|
|||
- [ ] Admin endpoints требуют `nodedc:superadmin` или `nodedc:launcher:admin`.
|
||||
- [ ] Все admin actions пишутся в audit log.
|
||||
- [ ] Удаление пользователя реализовано как deactivate/disable, не hard delete.
|
||||
- [x] Local runtime не отдает `storage/launcher-data.json` напрямую через public static route.
|
||||
- [x] Local runtime требует user session для `/api/storage/data`.
|
||||
|
||||
## Plane
|
||||
|
||||
|
|
@ -43,13 +47,20 @@
|
|||
- [ ] Access/refresh tokens не логируются.
|
||||
- [ ] Session cookies имеют `secure=true` в staging/production.
|
||||
- [ ] В production включены HTTPS и HSTS.
|
||||
- [x] Local internal API token отделен от `PLANE_OIDC_CLIENT_SECRET`.
|
||||
- [x] Launcher internal access API отклоняет запросы без token, с неверным token и со старым OIDC client secret.
|
||||
- [x] Tasker internal logout API отклоняет запросы без token и со старым OIDC client secret.
|
||||
|
||||
## Acceptance scenarios
|
||||
|
||||
- [ ] Без логина Launcher отправляет в Authentik.
|
||||
- [ ] Пользователь без `nodedc:taskmanager:access` не видит Task Manager в Launcher.
|
||||
- [ ] Пользователь без `nodedc:taskmanager:access` получает deny на прямой `task.local.nodedc`.
|
||||
- [x] Без логина Launcher отправляет в Authentik.
|
||||
- [x] Пользователь без Task Manager app access не видит Task Manager в Launcher.
|
||||
- [x] Пользователь без Task Manager app access получает deny в Tasker access middleware при прямом доступе.
|
||||
- [ ] Пользователь с доступом открывает Task Manager.
|
||||
- [ ] Старый Plane admin после OIDC видит старые workspace/tasks/comments.
|
||||
- [ ] Деактивированный пользователь теряет доступ.
|
||||
- [ ] Admin action появляется в audit log.
|
||||
- [x] Hard-deleted/annulled user теряет stale Tasker identity link и старая unlinked-сессия отзывается middleware.
|
||||
- [x] Hard-deleted/annulled user удаляется из active Tasker workspace/project members и issue assignees.
|
||||
- [x] Self-host Tasker workspace invite создает pending request в Launcher, а launcher-managed workspace не принимает self-service invite request.
|
||||
- [x] Admin action появляется в audit log.
|
||||
- [x] Повторный accept уже принятого invite отклоняется.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
# Staging Security Plan
|
||||
|
||||
Актуализировано: 2026-05-12.
|
||||
|
||||
Этот документ фиксирует минимальный staging path для закрытого demo release NODE.DC platform. Billing, тарифы и email automation не входят в текущий scope: доступы, approve и передача ссылок остаются ручными через Launcher/root-admin.
|
||||
|
||||
## Целевые домены
|
||||
|
||||
Для staging нужны отдельные домены от локального `.local.nodedc`:
|
||||
|
||||
```text
|
||||
auth.staging.nodedc.example -> Authentik
|
||||
launcher.staging.nodedc.example -> Launcher BFF/web
|
||||
task.staging.nodedc.example -> Task Manager / Operational Core
|
||||
```
|
||||
|
||||
Финальные DNS-имена заменяются перед deploy. Все redirect URI в Authentik должны совпадать с этими доменами и использовать `https://`.
|
||||
|
||||
## Публичная поверхность
|
||||
|
||||
Снаружи публикуется только edge reverse proxy:
|
||||
|
||||
- `80/tcp` — только redirect на HTTPS;
|
||||
- `443/tcp` — HTTPS termination, HSTS, proxy headers;
|
||||
- Postgres, Redis/Valkey, MinIO, Authentik server/worker, Launcher BFF и Tasker backend не публикуются напрямую наружу.
|
||||
|
||||
Reverse proxy обязан прокидывать:
|
||||
|
||||
- `Host`;
|
||||
- `X-Forwarded-Proto`;
|
||||
- `X-Forwarded-For`;
|
||||
- WebSocket/HTTP upgrade для Tasker realtime/live.
|
||||
|
||||
## Runtime topology
|
||||
|
||||
Staging можно собрать compose-файлом или эквивалентным deployment unit, но правила одинаковые:
|
||||
|
||||
- Authentik `server` и `worker` используют отдельный Postgres volume/network;
|
||||
- Authentik worker не монтирует `/var/run/docker.sock`;
|
||||
- Launcher хранит control-plane snapshot только в server-side storage;
|
||||
- Tasker остаётся отдельным приложением со своей БД, storage и доменной моделью;
|
||||
- Launcher не читает и не пишет Plane DB напрямую;
|
||||
- интеграция Launcher -> Tasker идёт через internal API с отдельным `NODEDC_INTERNAL_ACCESS_TOKEN`.
|
||||
|
||||
## Обязательные env
|
||||
|
||||
Значения с `change-me`, local token и dev secrets запрещены в staging.
|
||||
|
||||
```text
|
||||
COOKIE_SECURE=true
|
||||
COOKIE_DOMAIN=.staging.nodedc.example
|
||||
|
||||
NODEDC_INTERNAL_ACCESS_TOKEN=<random-32-bytes-min>
|
||||
SESSION_SECRET=<random-32-bytes-min>
|
||||
AUTHENTIK_SECRET_KEY=<random-32-bytes-min>
|
||||
PG_PASS=<random-32-bytes-min>
|
||||
|
||||
LAUNCHER_OIDC_ISSUER=https://auth.staging.nodedc.example/application/o/launcher/
|
||||
LAUNCHER_OIDC_REDIRECT_URI=https://launcher.staging.nodedc.example/auth/callback
|
||||
LAUNCHER_OIDC_LOGGED_OUT_REDIRECT_URI=https://launcher.staging.nodedc.example/auth/logged-out
|
||||
|
||||
PLANE_OIDC_ISSUER=https://auth.staging.nodedc.example/application/o/task-manager/
|
||||
PLANE_OIDC_REDIRECT_URI=https://task.staging.nodedc.example/auth/oidc/callback
|
||||
PLANE_NODEDC_ACCESS_ENFORCEMENT=1
|
||||
PLANE_NODEDC_ACCESS_ENFORCE_UNLINKED=1
|
||||
PLANE_NODEDC_ACCESS_TOKEN=<same-as-NODEDC_INTERNAL_ACCESS_TOKEN>
|
||||
```
|
||||
|
||||
OIDC client secrets для Launcher и Tasker должны быть разными. Internal API token не должен совпадать ни с одним OIDC client secret.
|
||||
|
||||
## Trusted proxies
|
||||
|
||||
Локальный default `127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,::1/128` допустим только для dev.
|
||||
|
||||
В staging `AUTHENTIK_LISTEN__TRUSTED_PROXY_CIDRS` и аналогичные параметры Tasker должны указывать только на фактический reverse-proxy subnet или ingress CIDR. Широкие private ranges без необходимости запрещены.
|
||||
|
||||
## Cookies и HTTPS
|
||||
|
||||
Для staging:
|
||||
|
||||
- TLS обязателен на всех публичных доменах;
|
||||
- HTTP должен делать permanent redirect на HTTPS;
|
||||
- `COOKIE_SECURE=true`;
|
||||
- session cookies остаются `HttpOnly`;
|
||||
- `SameSite=Lax` допустим для текущего top-level OIDC flow;
|
||||
- включить HSTS после проверки сертификатов и redirect URI.
|
||||
|
||||
## Backup перед staging
|
||||
|
||||
Перед первым staging deploy и перед destructive security smoke:
|
||||
|
||||
- dump Authentik Postgres;
|
||||
- dump Tasker/Plane Postgres;
|
||||
- архив Launcher `server/storage`;
|
||||
- архив Tasker uploads/MinIO data;
|
||||
- архив `.env`/secret references без публикации в git;
|
||||
- зафиксировать image tags Launcher/Tasker/Authentik.
|
||||
|
||||
Минимальный restore check: поднять копию DB/storage на isolated host или namespace и проверить login + открытие Tasker.
|
||||
|
||||
## Secrets rotation
|
||||
|
||||
Rotation policy до допуска внешних пользователей:
|
||||
|
||||
- `NODEDC_INTERNAL_ACCESS_TOKEN` — rotate при любом подозрении на утечку и перед production;
|
||||
- OIDC client secrets — rotate отдельно для Launcher и Tasker;
|
||||
- `SESSION_SECRET` — rotate с принудительным logout всех пользователей;
|
||||
- DB passwords — rotate через maintenance window;
|
||||
- старые secrets удаляются из `.env`, shell history и runtime logs.
|
||||
|
||||
## Acceptance перед людьми
|
||||
|
||||
Минимальный staging smoke:
|
||||
|
||||
1. Super sudo входит в Launcher через `https://launcher...`.
|
||||
2. Обычный active user видит только разрешённые сервисы.
|
||||
3. User без Task Manager app access не видит Task Manager в витрине и получает deny по прямому `https://task...`.
|
||||
4. Blocked/annulled user теряет Launcher и Tasker session после hard refresh.
|
||||
5. Self-host workspace invite создаёт pending request в Launcher.
|
||||
6. Launcher-managed workspace не принимает self-service invite request из Tasker.
|
||||
7. Hard delete удаляет active WorkspaceMember/ProjectMember/IssueAssignee в Tasker.
|
||||
8. Audit сохраняет admin actions, approve/reject и hard delete.
|
||||
9. Повторный accept уже принятого invite отклоняется.
|
||||
10. Прямые backend/internal endpoints без token возвращают `401`.
|
||||
|
||||
|
|
@ -42,5 +42,6 @@ PLANE_OIDC_REDIRECT_URI=http://task.local.nodedc/auth/oidc/callback
|
|||
|
||||
# security
|
||||
SESSION_SECRET=change-me-generate-with-infra-scripts-init-dev-env
|
||||
NODEDC_INTERNAL_ACCESS_TOKEN=change-me-generate-with-infra-scripts-init-dev-env
|
||||
COOKIE_DOMAIN=.local.nodedc
|
||||
COOKIE_SECURE=false
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ ensure_env_value LAUNCHER_OIDC_CLIENT_ID nodedc-launcher
|
|||
ensure_env_value PLANE_OIDC_CLIENT_ID nodedc-task-manager
|
||||
ensure_env_value LAUNCHER_OIDC_CLIENT_SECRET "$(rand_hex 48)"
|
||||
ensure_env_value PLANE_OIDC_CLIENT_SECRET "$(rand_hex 48)"
|
||||
ensure_env_value NODEDC_INTERNAL_ACCESS_TOKEN "$(rand_hex 48)"
|
||||
ensure_env_value LAUNCHER_OIDC_REDIRECT_URI http://launcher.local.nodedc/auth/callback
|
||||
ensure_env_value PLANE_OIDC_REDIRECT_URI http://task.local.nodedc/auth/oidc/callback
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ PLANE_OIDC_REDIRECT_URI=http://task.local.nodedc/auth/oidc/callback
|
|||
|
||||
# security
|
||||
SESSION_SECRET=$(rand 48)
|
||||
NODEDC_INTERNAL_ACCESS_TOKEN=$(openssl rand -hex 48 | tr -d '\n')
|
||||
COOKIE_DOMAIN=.local.nodedc
|
||||
COOKIE_SECURE=false
|
||||
EOF
|
||||
|
|
|
|||
Loading…
Reference in New Issue