103 lines
13 KiB
Markdown
103 lines
13 KiB
Markdown
# 2FAuth на Rust — 0.3.0
|
||
|
||
Целевая версия: **2FAuth 8.0.3**, коммит `3516c776a1fcbd83d234efc007e3a49807d6ed91`.
|
||
|
||
Это развиваемая реализация совместимости, **пока не подтверждённая как полная замена PHP**. Рабочий сервер пользователя не изменялся. Все сравнения выполняются на отдельных синтетических базах, включая копию БД, созданной настоящими Laravel-миграциями.
|
||
|
||
## Что реализовано
|
||
|
||
- HOTP, TOTP и Steam; SHA-1/256/512 и MD5; атомарный HOTP-счётчик; URI и экспорт.
|
||
- Шифрование Laravel AES-CBC, `APP_KEY`, предыдущие ключи; транзакционное включение/выключение шифрования данных и иконок.
|
||
- Аккаунты, группы, порядок и назначения отдельно для каждого пользователя; общие аккаунты, всеобщие ссылки доступа, передача владельца с подтверждением пароля; запрет выдачи секретов получателям.
|
||
- Регистрация, вход, CSRF, профиль, смена/восстановление пароля, ограничения регистрации, последний администратор, управление пользователями.
|
||
- Passport 13: настоящие RSA JWT, создание/отзыв PAT, существующие PHP bearer-токены и зашифрованные браузерные `laravel_token`. Действующая PHP-cookie может быть преобразована в Rust-сессию при загрузке интерфейса.
|
||
- OAuth: authorization code с PKCE, client credentials, Device Code Flow, ротация refresh-токенов и запрет повторного обмена; формат шифрования Defuse PHP совместим с эталоном.
|
||
- Перенос Laravel-сессий из файлов и SQLite: JSON/PHP-сериализация, SESSION_ENCRYPT, проверка cookie/CSRF, remember-me и отзыв при выходе.
|
||
- WebAuthn: регистрация, вход, список/переименование/удаление устройств, восстановление; импорт существующих зашифрованных PEM-ключей Laragear P-256/RSA/Ed25519. Проверки используют подписанные данные аутентификатора.
|
||
- GitHub/OpenID SSO, PKCE, одноразовый state, проверка OIDC JWT при настройке issuer; reverse-proxy-вход только от доверенного сетевого адреса.
|
||
- Импорт 2FAuth, Aegis, 2FAS, Bitwarden, текстовых URI и Google Authenticator; вложенные иконки; QR; официальные и локальные наборы иконок.
|
||
- Настройки, предпочтения, журналы входа/OTP, уведомления, SMTP/STARTTLS/TLS/sendmail/log; исходный собранный Vue-интерфейс и размещение в подкаталоге.
|
||
|
||
Подробные доказательства и ограничения: [compatibility/CURRENT.md](compatibility/CURRENT.md), [compatibility/VERIFICATION.md](compatibility/VERIFICATION.md). Старые разделы аудита в `compatibility/README.md` относятся к исходной версии 0.1.0.
|
||
|
||
## Готовый бинарный файл
|
||
|
||
В архиве есть `bin/twofauth-rs` для Linux x86_64 GNU. Он проверен в этой среде; для запуска нужны glibc 2.39 или новее и libgcc_s. Контрольная сумма приведена в `bin/BUILD.txt`. Если система старее или имеет другую архитектуру, соберите проект из исходников либо через Docker.
|
||
|
||
Запускайте бинарный файл из каталога `rust-server`; соседний каталог `public` определяется автоматически. Для новой установки сначала задайте и сохраните `APP_KEY`, затем используйте команды ниже, заменив `./target/release/twofauth-rs` на `./bin/twofauth-rs`. Для имеющейся установки ключи должны остаться прежними.
|
||
|
||
## Сборка и отдельная тестовая установка
|
||
|
||
Нужны современный stable Rust, C-компилятор, make и Perl: OpenSSL собирается из исходников для WebAuthn. Сборка Docker в этой среде не запускалась.
|
||
|
||
```sh
|
||
cargo build --locked --release
|
||
mkdir -p data
|
||
./target/release/twofauth-rs init
|
||
RUST_COOKIE_SECURE=false ./target/release/twofauth-rs serve
|
||
```
|
||
|
||
Откройте `http://127.0.0.1:8080`. На пустой БД доступна регистрация; первый пользователь становится администратором. Отключать Secure-cookie следует только для локального HTTP. Для HTTPS оставьте значение по умолчанию.
|
||
|
||
Можно создать отдельного тестового пользователя через файл пароля:
|
||
|
||
```sh
|
||
./target/release/twofauth-rs create-user --name Test --email test@example.invalid --password-file /path/password.txt
|
||
```
|
||
|
||
`init` отказывается создавать схему поверх существующих пользователей. `create-user` создаёт обычного пользователя. Файл пароля должен быть доступен только владельцу; для этой CLI-команды требуется 12–72 байта.
|
||
|
||
## Проверка копии существующей SQLite
|
||
|
||
Сначала сделайте согласованную копию БД и каталога `storage` средствами SQLite/вашего резервного копирования. Не копируйте только основной файл SQLite при незавершённом WAL.
|
||
|
||
Настройте окружение на **копию**:
|
||
|
||
```sh
|
||
export DB_CONNECTION=sqlite
|
||
export DB_DATABASE=/absolute/path/to/copied/database.sqlite
|
||
export APP_URL=https://test.example.invalid
|
||
export STORAGE_PATH=/absolute/path/to/copied/storage
|
||
export PASSPORT_KEY_PATH=/absolute/path/to/copied/storage
|
||
# APP_KEY и APP_PREVIOUS_KEYS должны сохранять исходные значения.
|
||
./target/release/twofauth-rs prepare-sqlite
|
||
./target/release/twofauth-rs serve
|
||
```
|
||
|
||
`prepare-sqlite` проверяет используемые поля таблиц и добавляет только служебные таблицы Rust. Он не выполняет Laravel-миграции и не меняет историю миграций. Если эти служебные таблицы отсутствуют при запуске, `serve` также проверит схему и создаст их. Исходная БД должна уже быть обновлена до целевого PHP-коммита. Поддержка PostgreSQL/MySQL/SQL Server в этой реализации **ещё отсутствует**.
|
||
|
||
Сохраняйте исходные ключи Passport `oauth-private.key`/`oauth-public.key`, `APP_KEY`, предыдущие ключи и содержимое хранилища. Не генерируйте новые ключи вместо существующих. Для encrypted WebAuthn-ключей `APP_KEY` нужен даже при выключенном шифровании OTP.
|
||
|
||
## Конфигурация
|
||
|
||
`DATABASE_URL=sqlite:///absolute/file.sqlite` имеет приоритет над `DB_DATABASE`. По умолчанию используется `sqlite://data/2fauth.sqlite`. Адрес прослушивания: `LISTEN_ADDR`, по умолчанию `127.0.0.1:8080`.
|
||
|
||
Применяются исходные `APP_URL`, `APP_NAME`, `APP_KEY`, `APP_PREVIOUS_KEYS`, настройки SMTP `MAIL_*`, параметры `GITHUB_*`, `OPENID_*`, `WEBAUTHN_*`, `AUTH_GUARD`/`AUTHENTICATION_GUARD`, `AUTH_PROXY_HEADER_FOR_*`, `TRUSTED_PROXIES`, предпочтения `USERPREF_DEFAULT__*`/`USERPREF_LOCKED__*`.
|
||
|
||
Дополнительно:
|
||
|
||
| Параметр | Назначение |
|
||
|---|---|
|
||
| `STORAGE_PATH` | Каталог Laravel storage; по умолчанию `storage` |
|
||
| `PASSPORT_KEY_PATH` | Каталог ключей Passport; по умолчанию `storage` |
|
||
| `RUST_PUBLIC_DIR` | Каталог собранного интерфейса; по умолчанию `public` рядом с исходниками |
|
||
| `RUST_COOKIE_SECURE` | `false` только для локального HTTP; по умолчанию Secure |
|
||
| `APP_SUBDIRECTORY` | Например `/tools/2fa`; `APP_URL` должен содержать тот же путь |
|
||
| `SESSION_DRIVER`, `SESSION_TABLE`, `SESSION_COOKIE`, `SESSION_ENCRYPT` | Чтение исходных Laravel-сессий: `file` или `database`; сохраняйте исходные параметры и `STORAGE_PATH` |
|
||
| `PASSPORT_JSON_API_ROUTES` | `true` включает исправленные маршруты управления OAuth-клиентами и токенами; по умолчанию выключено, как в закреплённом PHP-эталоне |
|
||
| `RUST_OAUTH_CONSENT_ENABLED` | `true` включает исправленный экран согласия OAuth; это явное расширение относительно дефектного маршрута эталона |
|
||
| `OPENID_ISSUER` | Включает discovery и проверку подписанного ID token; без него сохранён upstream-flow с явными URL |
|
||
| `OPENID_DISCOVERY_URL`, `OPENID_JWKS_URL` | Необязательные переопределения OIDC endpoints |
|
||
|
||
В Docker каталог `/data` должен быть доступен UID 10001. В образе `STORAGE_PATH` и `PASSPORT_KEY_PATH` указывают на `/data/storage`. Команды и проверки для разработчиков приведены в английском README.
|
||
|
||
## Что ещё препятствует полной замене
|
||
|
||
Другие СУБД; остальные Laravel session-хранилища (Redis, cookie и другие); все варианты конфигурации и переводы ошибок; полное сравнение всех маршрутов и middleware; браузерная проверка всех экранов и реальных SSO/WebAuthn-провайдеров. Некоторые диагностические ответы сознательно описывают Rust, а не PHP. QR-код может иметь другое SVG-представление при том же URI. Отдельные ограничения удалённых иконок и почтовых драйверов описаны в `compatibility/CURRENT.md`.
|
||
|
||
Прохождение ограниченного набора тестов не означает полной совместимости. Боевой PHP-сервер пока не следует выключать на основании этого архива.
|
||
|
||
## Особенности закреплённого OAuth-эталона
|
||
|
||
В исходном PHP-файле AppServiceProvider флаг регистрации JSON-маршрутов Passport устанавливается после загрузки пакета. Поэтому `/oauth/clients` и `/oauth/tokens` по умолчанию возвращают SPA для GET и 405 для изменений. Стандартный GET `/oauth/authorize` также неработоспособен: отсутствует реализация AuthorizationViewResponse. По умолчанию сохранено наблюдаемое поведение. Два явных параметра выше включают рабочее управление и согласие для authorization code; экран подтверждения Device Flow в этой версии сохраняет исходную ошибку привязки представления. Эти расширения не считаются точным воспроизведением дефектов эталона.
|