diff --git a/.tasks/ARCHIVE.md b/.tasks/ARCHIVE.md index 6819aee..1f16b58 100644 --- a/.tasks/ARCHIVE.md +++ b/.tasks/ARCHIVE.md @@ -814,3 +814,34 @@ Copy-Item C:\sites\snolla\Web.config.bak-pre-vds-cutover-20260522 C:\sites\snoll **Closes "Backup strategy для windows-host warm-standby"** — re-scoped из `cms-stopgap-backup-daily` (2026-05-21 spec) 2026-05-24 после migration MSSQL/sites + user-decision держать windows-host как DR fallback. **Branch:** master + +--- + +## 🟢 [books-ssh-audit-shared-vds] — Closed 2026-05-24 — audit clean, 0 keys revoked + cosmetic dead-key cleanup + +**Closed:** 2026-05-24 — SSH audit на shared VDS (vds-kzntsv = 89.253.255.94 — где books Slovo+Bookva живут в shared compose-стеке) clean: 1 retained key (vitya core dev), 0 keys revoked, sshd hardening verified. + +**Audit findings:** +- `/home/vitya/.ssh/authorized_keys` — 1 key (`ssh-ed25519 …ER/Z vitya@DESKTOP-NSEF0UK`) +- `/root/.ssh/authorized_keys` — 1 dead duplicate key (root SSH disabled via `permitrootlogin no`), removed cosmetically (backup overwrite gotcha but trivially restorable from vitya's key) +- 2 system users with shell — root + vitya (минимум) +- `sshd -T` effective: `permitrootlogin no` + `passwordauthentication no` + `kbdinteractiveauthentication no` ✅ +- **Gotcha noted:** raw `/etc/ssh/sshd_config` grep показывал `PermitRootLogin yes` + `PasswordAuthentication yes` — defaults from package. Override'ы в `/etc/ssh/sshd_config.d/*.conf` make effective config. Future audits должны use `sshd -T`, not raw grep. +- fail2ban active: 2670 failed / 37 banned historically, currently 0 +- journalctl `Accepted publickey` last 7 days — только `vitya from 94.19.247.14` (мой home public IP), no surprises + +**Acceptance check (per spec §Acceptance):** +- ✅ `~/.ssh/authorized_keys` на shared VDS reviewed +- ✅ Non-core keys revoked — N/A (only my key existed) +- ✅ Analyst keys revoked — N/A (никогда не выдавались) +- ✅ Documented in `OpeItcLoc03/admin/.wiki/concepts/books-ssh-access.md` (retained keys table + sshd state + fail2ban + login history + add/revoke processes + cross-refs) + +**Implications для tenant-split Phase 3 §SSH-аудит:** ✅ verified clean — на промежуточной стадии (1 VDS, 2 стека, 2 БД), хотя infra-level изоляция теоретически compromised (vitya с SSH мог бы прочитать обе БД через localhost), de-facto risk = nil. Single-developer setup, analyst access всегда был app-level only. Pre-cutover sigh of relief. + +**Atomic revert (если понадобится restore dead root key):** `ssh vitya@89.253.255.94 'echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwYw1sS0Dj5FQmNxqJUV9IxU+9hZcg8qYQRgLN5ER/Z vitya@DESKTOP-NSEF0UK" | sudo tee /root/.ssh/authorized_keys'`. Key dead anyway (root SSH disabled), restoration cosmetic-only. + +**Detail:** `.tasks/books-ssh-audit-shared-vds.md` (per-task file with Decisions log + Completed steps). + +**Closes** Фаза 3, шаг 2 в `victor/books/.wiki/concepts/tenant-split.md`. + +**Branch:** master diff --git a/.tasks/STATUS.md b/.tasks/STATUS.md index 4940ef7..39f9507 100644 --- a/.tasks/STATUS.md +++ b/.tasks/STATUS.md @@ -1,5 +1,5 @@ # Admin Task Board -_Updated: 2026-05-24 (`windows-host-fallback-backup-daily` 🟢 closed — daily 03:00 MSK rclone SFTP windows-host → kreknin live, smoke #1 ✓ 4868 sec / 23 GB total / 5 MSSQL DBs backed up. Все 3 host'а (windows + RUVDS + VDS) backup'ятся на kreknin sequentially за одну ночь. **Merged 4 new books-* tasks из workshop** (`books-vds-bookva-bootstrap` 🔵, `books-dns-cutover-bookva` 🔵, `books-ssh-audit-shared-vds` ⚪, `books-bookva-user-whitelist-gathering` ⚪) — tenant-split phase для victor/books, реализация после design в `victor/books/.wiki/concepts/tenant-split.md`. Current scope: IIS migration в soak (kupimknigi + emspb flipped, tandemmebel excluded), infra-inventory ready, books-* awaits tenant-split design Phase 3-4.)_ +_Updated: 2026-05-24 (`books-ssh-audit-shared-vds` 🟢 closed — audit clean: 1 retained vitya key, 0 revoked, removed cosmetic dead root key, sshd hardening verified via `sshd -T`. Doc в `.wiki/concepts/books-ssh-access.md`. Pre-cutover acceptance для tenant-split Phase 3 ✅. Earlier today: `windows-host-fallback-backup-daily` 🟢 closed (daily 03:00 MSK rclone SFTP windows-host → kreknin live, 23 GB / 4868 sec smoke #1). Все 3 host'а (windows + RUVDS + VDS) backup'ятся на kreknin sequentially за одну ночь. Current scope: IIS migration в soak (kupimknigi + emspb flipped, tandemmebel excluded), infra-inventory ready, остальные books-* awaits tenant-split Phase 3-4 design Direction.)_ - ---- - ## ⚪ [books-bookva-user-whitelist-gathering] — **Процессная** ops-таска для Фазы 3, шаг 1 дизайна `tenant-split` из victor/books. Получить от учредителя Bookva письменный список пользователей, которые допущены к Bookva-инсталляции. Без этого списка cutover не возможен — иначе утечка доступа: либо лишние юзеры получат доступ к Bookva (через копирование «всех users»), либо легитимные юзеры заблокированы (через пустой whitelist). **Direction:** Bookva — новая инсталляция, начинается с whitelist'а (закрытый список). Slovo — остаётся на текущем стеке, получает копию всех текущих users (статус-кво). diff --git a/.tasks/books-ssh-audit-shared-vds.md b/.tasks/books-ssh-audit-shared-vds.md new file mode 100644 index 0000000..ec204dd --- /dev/null +++ b/.tasks/books-ssh-audit-shared-vds.md @@ -0,0 +1,56 @@ +# books-ssh-audit-shared-vds + +## Goal + +SSH-аудит на shared VDS (`vds.kzntsv.site` / 89.253.255.94 — на нём сейчас живёт books-инсталляция Slovo+Bookva в shared compose-стеке) перед Phase 3 cutover'ом `tenant-split`. Минимизировать infra-level риск утечки между tenant'ами: пользователь с SSH к VDS может прочитать БД соседнего tenant'а через localhost независимо от app-level RBAC. + +См. `victor/books/.wiki/concepts/tenant-split.md` §«Двухуровневая изоляция пользователей → Infra-level». + +## Key files + +- `[[../entities/vds-kzntsv]]` — host entity (89.253.255.94 / vds.kzntsv.site) +- `[[../sources/vds-kzntsv-bootstrap-2026-05-20]]` — bootstrap chronology, initial hardening +- `[[../.wiki/concepts/books-ssh-access.md]]` — **created by this task** — audit results + retained keys table + add/revoke processes +- `victor/books/.wiki/concepts/tenant-split.md` — design context (dev-source) + +## Decisions log + +- **2026-05-24 (initial audit run):** dumped `/home/vitya/.ssh/authorized_keys` + `/root/.ssh/authorized_keys` + sshd effective config via `sshd -T` + fail2ban status + journalctl ssh log last 7 days. Result: 1 key (vitya@DESKTOP-NSEF0UK) на vitya, 1 dead duplicate ключ на root, никаких analyst/bывших keys, никаких неопознанных source IPs за 7 дней. +- **2026-05-24 (cleanup):** удалил dead key из `/root/.ssh/authorized_keys` (truncate). Был dead из-за `permitrootlogin no` — не functional, только cosmetic-confusing. Backup сделан, но второй cp клобнул backup нулевым content'ом (моё упущение в команде). Восстановление trivial если понадобится — key identical to vitya's в `vitya/.ssh/authorized_keys`. +- **2026-05-24 (finding sshd config inconsistency):** raw grep `/etc/ssh/sshd_config` показывает `PermitRootLogin yes` + `PasswordAuthentication yes`, но `sshd -T` (effective config) показывает correct hardening: `permitrootlogin no` + `passwordauthentication no`. Override'ы в `/etc/ssh/sshd_config.d/*.conf` или cloud-init drop-in делают finальный config. **Future audits должны проверять через `sshd -T`, не плоский grep.** Это зафиксировано в `concepts/books-ssh-access.md` §«sshd hardening state». + +## Open questions + +(none — все решены в audit) + +## Completed steps + +- [x] **2026-05-24 ~15:53:** SSH audit run на vds-kzntsv: + - `cat /home/vitya/.ssh/authorized_keys` → 1 key (`vitya@DESKTOP-NSEF0UK`) + - `getent passwd` → 2 users with shell: root + vitya (минимум, ожидаемо) + - `sudo cat /root/.ssh/authorized_keys` → 1 dead duplicate key (root SSH disabled) + - `sudo systemctl is-active fail2ban` → active; 2670 failed / 37 banned (currently 0) — adequate + - `sudo journalctl -u ssh ... | grep Accepted` → только vitya@94.19.247.14 last 7 days + - `sudo sshd -T | grep ...` → correct hardening (permitrootlogin/passwordauth/kbd = no) +- [x] **2026-05-24 ~15:55:** removed dead key из `/root/.ssh/authorized_keys` via `sudo bash -c ': > /root/.ssh/authorized_keys'`. File now empty (0 bytes). +- [x] **2026-05-24:** documentation written → `.wiki/concepts/books-ssh-access.md` (retained keys table + sshd state + fail2ban + login history + add/revoke processes + cross-refs). + +## Closed + +**2026-05-24** — audit clean, нечего revoke'ать кроме cosmetic dead root key. Тенант-split Phase 3 §SSH-аудит acceptance ✅: + +- ✅ `~/.ssh/authorized_keys` reviewed — 1 key (vitya, core dev) +- ✅ Non-core keys revoked — N/A (none existed) +- ✅ Analyst keys revoked — N/A (none existed) +- ✅ Documented in `.wiki/concepts/books-ssh-access.md` + +**Closes** Фаза 3, шаг 2 `tenant-split` design. + +## Notes + +- **Single-developer / single-key environment** — на этой машине я единственный человек, у которого SSH. Это упрощает audit dramatically. После Phase 4 (когда Bookva уедет на отдельный VDS) — каждая box будет под SSH своей "команды" (которая для нашего setup = me, но formal-administrator-of-bookva от учредителя Bookva может быть добавлен — process в `books-ssh-access.md` §«How to add a new key»). +- **Bootstrap claim audit:** `[vds-kzntsv-bootstrap]` 🟢 close-note сказал «hardened sshd (key-only)». Verified through `sshd -T` — claim true, но raw `/etc/ssh/sshd_config` misleading (default pkg config). Если ещё кто-то будет верифицировать → `sshd -T` always. +- **Atomic revert:** ничего материального не сделано revoke (только cosmetic empty root-keys). Если понадобится — `ssh vitya@89.253.255.94 'echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKwYw1sS0Dj5FQmNxqJUV9IxU+9hZcg8qYQRgLN5ER/Z vitya@DESKTOP-NSEF0UK" | sudo tee /root/.ssh/authorized_keys'`. + + + diff --git a/.wiki/concepts/books-ssh-access.md b/.wiki/concepts/books-ssh-access.md new file mode 100644 index 0000000..a381473 --- /dev/null +++ b/.wiki/concepts/books-ssh-access.md @@ -0,0 +1,89 @@ +--- +title: books shared VDS — SSH access audit + retained keys +status: live +tags: [vds, ssh, audit, books, tenant-split, ops] +related: [[vds-kzntsv]], [[../sources/vds-kzntsv-bootstrap-2026-05-20]] +--- + +# books shared VDS — SSH access (post-audit 2026-05-24) + +Snapshot SSH-доступа к `vds-kzntsv` (89.253.255.94 / vds.kzntsv.site), на котором сейчас живёт shared `books`-инсталляция (Slovo + Bookva в одном compose-стеке, до physical split Фазы 4 в [`tenant-split`](https://git.kzntsv.site/victor/books/src/branch/master/.wiki/concepts/tenant-split.md)). + +Создан 2026-05-24 в результате таски `[books-ssh-audit-shared-vds]` 🟢 (см. spec в Фазе 3 §SSH-аудит). + +## Retained keys + +| User | Key (truncated) | Owner | Date added | Reason | Source machine | +|---|---|---|---|---|---| +| `vitya` | `ssh-ed25519 AAAA…ER/Z vitya@DESKTOP-NSEF0UK` | Виктор Кузнецов (core dev) | 2026-05-20 (bootstrap) | Core developer, sole administrator. Single key for both dev + ops. | `DESKTOP-NSEF0UK` (home workstation) | + +**Только 1 ключ.** Никаких аналитических, бывших-сотрудников, неопознанных ключей не найдено в audit'е 2026-05-24. + +## Removed keys (audit cleanup) + +| Path | Key | Status | Removed | Note | +|---|---|---|---|---| +| `/root/.ssh/authorized_keys` | `ssh-ed25519 AAAA…ER/Z vitya@DESKTOP-NSEF0UK` (duplicate vitya key) | Cosmetic dead | 2026-05-24 | Был dead с момента bootstrap'а — `sshd -T` показывает `permitrootlogin no`, root SSH disabled независимо от authorized_keys. Удалён для чистоты (backup в `/root/.ssh/authorized_keys.bak-pre-ssh-audit-2026-05-24`, но overwrite затёр содержимое — restoration trivial since key identical to vitya's main). | + +## sshd hardening state + +Effective config от `sshd -T 2>&1 | grep -E "^(permitrootlogin|passwordauthentication|pubkeyauthentication|challengeresponseauthentication|kbdinteractiveauthentication)"`: + +``` +permitrootlogin no +pubkeyauthentication yes +passwordauthentication no +kbdinteractiveauthentication no +``` + +**Note:** raw grep `/etc/ssh/sshd_config` может показать `PermitRootLogin yes` / `PasswordAuthentication yes` — это default-config от пакета. Override'ы в `/etc/ssh/sshd_config.d/*.conf` (или drop-in от cloud-init) делают finальный config. Всегда проверять через `sshd -T`, не плоский config. + +## fail2ban state (2026-05-24) + +- `systemctl is-active fail2ban` → `active` +- Total failed attempts (since deploy): **2670** +- Total IPs ever banned: **37** +- Currently banned: **0** (бан выходит по TTL) +- Configured jail: `sshd` (default debian jail) + +Brute-force protection adequate; нет required action. + +## SSH login history (last 7 days) + +`sudo journalctl -u ssh -u sshd --since="7 days ago" | grep Accepted` показал **только** `vitya from 94.19.247.14` (мой home public IP). Никаких других source-IP — clean. + +## Tenant-split implications (Phase 3 acceptance) + +Spec `tenant-split.md` §«Двухуровневая изоляция пользователей → Infra-level»: +> на промежуточной стадии не давать аналитикам Bookva SSH к VDS, только app-level. SSH-аудит до cutover'а. + +**Verified clean** as of 2026-05-24 — никаких аналитических SSH-ключей не было выдано. Single-developer setup; analyst access всегда был app-level only. Pre-cutover sigh of relief. + +После Phase 4 (physical split на 2 VDS): +- vds-kzntsv (Slovo) — продолжит хостить остальную нашу инфру (gitea, registry, ntfy, mssql, minio, owncloud, board-viewer) + books-slovo стек. SSH = vitya only. +- vds-bookva-new (Bookva) — отдельная box, отдельный SSH. Заводить core-dev key (vitya) + опционально formally-named Bookva admin. + +## How to add a new key (process) + +1. Получить от пользователя ` ` (full one-line pubkey). +2. Verify identity: comment должен match human-readable identifier (`alice@laptop`, не just `id_ed25519`). +3. Document **before** adding: append row to "Retained keys" table выше с rationale. +4. Commit doc change (PR / direct push depending on grant). +5. После doc-commit: `ssh vitya@vds.kzntsv.site 'echo "" >> ~/.ssh/authorized_keys'`. +6. Verify new user can login via new key. +7. **NEVER** add key without doc update — иначе через 3 месяца забудем кто/зачем. + +## How to revoke a key + +1. Backup: `sudo cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak-$(date +%F)`. +2. Edit `~/.ssh/authorized_keys` — delete the line. +3. Update doc — переместить row из "Retained" в новый "Revoked" section с datestamp + reason. +4. Verify revoked key fails: `ssh -i vitya@vds.kzntsv.site` returns publickey rejection. +5. Commit doc change. + +## Cross-refs + +- [[vds-kzntsv]] — entity page (host details). +- [[../sources/vds-kzntsv-bootstrap-2026-05-20]] — bootstrap chronology, contains initial sshd hardening setup. +- `victor/books` `.wiki/concepts/tenant-split.md` §«Двухуровневая изоляция пользователей» — design context для этого аудита. +- `.tasks/books-ssh-audit-shared-vds.md` — close-note + decisions. diff --git a/.wiki/index.md b/.wiki/index.md index 68d8842..1c4fc91 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -18,6 +18,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever ## Concepts - [admin-infra-project](concepts/admin-infra-project.md) — design + migration plan для OpeItcLoc03/admin (canonical) +- [books-ssh-access](concepts/books-ssh-access.md) — SSH access audit на shared VDS (books Slovo+Bookva), retained keys + add/revoke processes - [compose-bcrypt-escape-trap](concepts/compose-bcrypt-escape-trap.md) — Docker Compose ест `$` в bcrypt hashes - [db-tls-self-signed-via-traefik-raw-tcp](concepts/db-tls-self-signed-via-traefik-raw-tcp.md) — DB TLS через traefik raw TCP с self-signed certs - [docker-host-loopback-detect](concepts/docker-host-loopback-detect.md) — Docker host-loopback detection — как доказать что host.docker.internal не петля diff --git a/.wiki/log.md b/.wiki/log.md index 4161e7e..b7e239b 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -19,3 +19,5 @@ Append-only log of wiki operations (ingests, promotions, lints, migrations). ## [2026-05-22] update | concepts/ocis-on-vds-deploy-recipe — Gotcha 5: 60s HTTP timeout caps slow-uplink uploads at ~200MB on 3 MiB/s link; traefik buffering NOT the fix (500 from oxy buffer); workaround = VDS-side curl PUT loopback via throwaway sftp key. Source: .tasks/owncloud-vds-deploy.md close-note. ## [2026-05-23] ingest | concepts/windows-server-2025-core-bootstrap — default-blockers (SMB closed, IIS/URL-Rewrite/.NET unverified) + transfer-методов матрица (RDP-redirect / SMB / WinRM / SFTP); recommendation = SMB inbound с source-IP whitelist на время migration. Source: failed-robocopy инцидент 2026-05-23 18:08 (.tasks/iis-migration-to-ruvds.md Decisions log). + +## [2026-05-24] ingest | concepts/books-ssh-access — SSH access audit на shared VDS pre-cutover Фазы 3 tenant-split. Retained keys table (1 key, vitya core dev), removed cosmetic dead root key, sshd hardening verified via `sshd -T` (not raw config), fail2ban active 2670 failed/37 banned, only vitya@94.19.247.14 в access log last 7 days. Source: .tasks/books-ssh-audit-shared-vds.md.