Перейти к содержимому

Безопасность ​

Эта страница предназначена для администратора, который запускает сервер. Она начинается с шагов по защите новой установки, а затем подробно описывает каждую защиту.

В проекте указано, что модель угроз и внешняя проверка безопасности ещё не выполнены. Не публикуйте сервер в открытом интернете. Разрешайте доступ к нему только сетям ваших клиентов.

Защитите новый сервер ​

  1. Оставьте адрес прослушивания по умолчанию 127.0.0.1, пока HTTPS не заработает. См. Сеть и HTTPS.
  2. Включите HTTPS и откройте клиентским сетям только порт HTTPS. Никогда не открывайте порт базы данных.
  3. Создайте личные учётные записи для администраторов. Ключ восстановления берегите для экстренных случаев. См. Ключ восстановления.
  4. Дайте каждому инструменту или системе CI собственную сервисную учётную запись с ключом, у которого минимум прав. См. Ключи и токены.
  5. Оставьте самостоятельную регистрацию выключенной. По умолчанию она выключена.
  6. Если перед Arkvory стоит обратный прокси, задайте ARKVORY_TRUSTED_PROXIES. См. Ограничения входа.
  7. Сделайте vault зашифрованным (так по умолчанию) и храните набор восстановления вне сервера. Кроме того, держите его на зашифрованном томе, который читают только учётная запись службы и администратор копирования. См. Резервные копии.
  8. Храните копии секретных файлов вне сервера. См. Копии секретов.
  9. Подключите метрики и оповещения. См. Мониторинг.

Сеть и HTTPS ​

По умолчанию сервер слушает 127.0.0.1:8080. Нативная установка может слушать другой адрес после настройки HTTPS:

bash
sudo arkvory configure --root /opt/proanima-arkvory --tls-cert /etc/arkvory/fullchain.pem --tls-key /etc/arkvory/privkey.pem --listen-host 0.0.0.0

Команда проверяет файлы, перезапускает службы и возвращает прежние настройки, если службы не запустились. Полную процедуру, а также Docker Compose, которому нужен обратный прокси, см. в разделе HTTPS и обратный прокси.

  • Сертификат и ключ должны читаться, соответствовать друг другу и не быть просроченными. Иначе API не запускается и никогда не переключается на обычный HTTP.
  • Минимальная версия TLS — 1.2. Чтобы потребовать 1.3, задайте ARKVORY_TLS_MIN_VERSION=TLSv1.3. Клиентские сертификаты не поддерживаются.
  • Когда сервер сам обслуживает HTTPS, он отвечает с заголовком Strict-Transport-Security: max-age=31536000. Если TLS завершает прокси, этот заголовок принадлежит ему.
  • Обновлённые файлы сертификата читаются заново каждые 300 секунд (ARKVORY_TLS_RELOAD_SECONDS) без перезапуска. Новые соединения получают новый сертификат. Если файл не читается, остаётся рабочий сертификат и записывается tls.reload_failed. Запись tls.expiring делается ежедневно в последние 14 дней.
  • Адрес, отличный от loopback, без TLS и без доверенного прокси записывает при запуске предупреждение http.plaintext_exposed. Исправьте это, прежде чем пускать клиентов.
  • Arkvory никогда не отключает проверку получаемого сертификата: ни для зеркал, ни для хаба, ни в клиенте командной строки. Свой центр сертификации для зеркал добавляйте через --mirror-ca-file.

За обратным прокси API остаётся на loopback. Прокси должен передавать тела потоком, не буферизуя файлы целиком. Не записывайте строку запроса в журнал прокси, потому что ссылка на скачивание несёт в ней свой секрет.

Секреты на сервере ​

Установщики создают в корне установки такие файлы. Сохраняйте права доступа, которые задал установщик.

ФайлСодержимоеДоступ
config/bootstrap-token.txtКлюч восстановления. Имеет права администратораLinux: только root (режим 0600). Windows: SYSTEM и Администраторы
config/keys.jsonХеши SHA-256 ключа восстановления и ключа состояния, но не сами ключиLinux: пишет root, читает группа службы (0640). Windows: наследуется от корня
config/health-token.txtКлюч состояния deployment-health. Прав на репозитории не имеетLinux: только root. Compose: читается в контейнере
config/runtime.jsonВсе настройки сервера, включая URL базы данных с паролемLinux: пишет root, читает группа службы (0640). Windows: наследуется от корня
config/postgres.envПароль базы данных установки ComposeТолько root либо SYSTEM и Администраторы
github-token.txtНеобязательный токен GitHub для обновленийТолько root либо SYSTEM и Администраторы
config/mirrors/*.tokenКлючи чтения для серверов-источников зеркалУчётная запись службы
Ключ TLSЗакрытый ключ сертификатаРасположение выбираете вы. Разрешите доступ только учётной записи службы

В Windows корень даёт полный доступ SYSTEM и Администраторам. Учётная запись службы LocalService читает корень и пишет только в data\, logs\ и папку входящих обновлений. База данных работает под другой учётной записью, поэтому API не может читать файлы базы данных.

Правила для всех секретов:

  • Передавайте их в файлах или переменных окружения, а не в аргументах команд. Аргументы видны в списке процессов.
  • Не копируйте ключ восстановления клиентам, системам CI и скриптам. Для ежедневной работы создавайте учётные записи и ключи сервисов.
  • Сервер никогда не записывает в журнал ключи, пароли, токены, заголовки Authorization и строки запроса. См. Мониторинг.
  • Вывод команд установщика скрывает URL баз данных, ключи и длинные секреты.

Чтобы заменить ключ восстановления, измените файл bootstrap-token.txt и его хеш в config/keys.json вместе, сохраните запись deployment-health и перезапустите API и обработчик. См. Настройка.

Пароли и ограничения входа ​

Пароль состоит из 12–128 символов и хранится только в виде хеша с солью (scrypt). Вход действует 12 часов. У одной учётной записи не более 32 активных сессий; новый вход завершает самую старую. Смена или сброс пароля завершает все сессии и отзывает все персональные токены учётной записи.

В Arkvory нет жёсткой блокировки, из-за которой любой, кто знает имя, мог бы заблокировать владельца. Атаки замедляются по уровням:

УровеньОграничение
На адрес, вход10 попыток сразу, затем ещё по одной каждые 15 секунд. Верный пароль возвращает попытку. IPv6 учитывается по сети /64
На адрес, самостоятельная регистрация3 попытки, затем по одной раз в 20 минут; 20 на процесс, затем по одной раз в 3 минуты
На учётную записьКаждый неверный пароль добавляет одну штрафную единицу. Штраф уменьшается на 1 каждые 6 секунд. Выше 20 единиц каждый неверный пароль добавляет ожидание, которое удваивается от 1 секунды до 2 минут. Во время ожидания даже верный пароль получает 429
Одновременные запросы входаНе более 16, а тело запроса должно прийти в течение 10 секунд
Проверки паролейАнонимные проверки и проверки администраторов идут в разных очередях, поэтому поток входов не блокирует администратора

Ответ — 429 rate_limited с причиной login_attempts и заголовком Retry-After. Счётчики адресов живут в процессе и сбрасываются при перезапуске. Штраф учётной записи хранится в базе данных. Сброс пароля администратором его обнуляет.

За обратным прокси задайте в ARKVORY_TRUSTED_PROXIES адреса прокси (до 32, IP или CIDR). Только эти адреса могут указывать адрес клиента через X-Forwarded-For. Без этой настройки все клиенты делят адрес прокси, и несколько неудачных входов на какое-то время блокируют всех.

Ключи, токены и срок действия ​

Учётные данныеСрок жизниРотация
Сессия входа12 часовВойдите снова
Персональный токен доступаПо умолчанию 90 дней, не более 365. Область read или read-write. Никогда не даёт прав администратораСоздайте новый токен в Персональные токены доступа и отзовите старый
Ключ сервисаПо умолчанию 90 дней, не более 365. Выпущенный, но не активированный ключ истекает через 15 минутРотировать выпускает новый ключ. Старый ключ работает ещё не более 24 часов. Отозвать останавливает ключ сразу
Ссылка на скачиваниеОдин час в консолиСоздайте новую ссылку
Ключ восстановления и ключ состоянияНе истекаютЗаменяйте вручную. См. Секреты на сервере

Создавайте персональные токены и меняйте пароли только в сессии после входа. Токен не может создавать токены. У персонального токена нет прав администратора, кому бы он ни принадлежал.

Минимум прав для инструментов:

  • Создайте по одной сервисной учётной записи для каждого потребителя в Сервисный доступ и задайте в Права на репозитории только те репозитории и действия, которые ему нужны. Набор для чтения и Набор для публикации заполняют типовые наборы.
  • Для создания учётных записей и выдачи прав нужно отдельное право ключа восстановления или делегирования. Делегирование управления позволяет владельцу передать оператору ограниченные права. Делегированный ключ никогда не живёт дольше ключа того, кто его выдал.
  • Дайте сборщику метрик отдельный ключ с минимальными правами.
  • Отзыв выданного права блокирует ключ, ожидающий активации, но не отзывает уже активные ключи. Отзовите или отключите их сами. Начавшееся скачивание продолжается после отзыва.
  • Изменение прав действует со следующего запроса. Сервер проверяет доступ заново при каждом запросе — к спискам, метаданным и байтам файлов.

Журналы аудита ​

ЖурналЧто содержитГде читать
Журнал безопасностиВходы и неудачи, регистрации, изменения учётных записей, групп, прав, паролей и персональных токенов с исполнителем, видом учётных данных, целью, результатом и адресом клиентаGET /api/v1/security/audit, для сессии администратора или ключа восстановления
Аудит каталогаИзменения артефактов, путей, аннотаций и стадий в репозиторииGET /api/v1/repositories/{repository}/audit, с правом читать аудит
Действия сервисной учётной записиСоздание, изменения, выпущенные и отозванные ключи сервисной учётной записиЖурнал действий в консоли
Журнал процессаОдна строка http.access на запрос, с principal и clientIpСм. Мониторинг

Журнал безопасности только добавляет записи: база данных отказывается менять или удалять строку. Сервер хранит 365 дней и не более 1 000 000 строк и удаляет самые старые строки пакетами. Запросы, которые отклонили ограничения частоты, не записываются, поэтому поток запросов не может раздуть таблицу. Если нужна более длинная история, экспортируйте журнал в собственное хранилище событий.

bash
curl -fsS -H "Authorization: Bearer $ARKVORY_KEY" "https://arkvory.example/api/v1/security/audit?limit=100"

Чтобы прочитать более старые строки, используйте параметр after с последним ID.

Консоль и браузер ​

Сервер добавляет в ответы консоли такие заголовки:

ЗаголовокЗначение
Content-Security-Policydefault-src 'none'; img-src 'self' blob:; script-src 'self'; style-src 'self'; connect-src 'self'; worker-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'
Referrer-Policyno-referrer
X-Content-Type-Optionsnosniff
Cache-Controlprivate, no-store
X-Request-IdID запроса для этого ответа

Каждый ответ API тоже содержит X-Content-Type-Options, Cache-Control и X-Request-Id. CSP не разрешает ни встроенных скриптов, ни внешних скриптов, ни вложения в фреймы, ни соединений с другими узлами. Изображения из blob: — это снимки экрана, которые вы добавляете в сообщение обратной связи.

Сервер не устанавливает cookie. Консоль держит ключ или токен сессии только в памяти вкладки браузера. Браузер сохраняет только выбор темы и языка и закрытые файлы очереди скачивания. Страница браузера с другого адреса не может обращаться к API: ARKVORY_CORS_ORIGINS по умолчанию пуст. В нём можно указать до 16 точных источников (origin) для внешней консоли, с HTTPS или с HTTP на loopback. Разрешённый источник не получает дополнительных прав, потому что каждому запросу нужен ключ.

Подпись обновлений ​

У каждого выпуска есть манифест arkvory-release.json с SHA-256 его архива и установщика и подпись arkvory-release.json.sig. Это подпись Ed25519 в формате minisign. Открытые ключи программа обновления хранит в своём коде.

  • Выпуск из хаба или с GitHub устанавливается, только если его подпись соответствует встроенному ключу, а значения SHA-256 совпадают с манифестом. Неверная подпись — это ошибка, и программа обновления не ищет другой источник.
  • Закрытый ключ подписи остаётся у сопровождающего и никогда не попадает на ваш сервер. Чтобы ротировать ключи, выпуск может нести старый и новый открытые ключи.
  • Локальная папка, которую вы передаёте через --artifact, — ваш собственный выбор. Файл подписи в ней проверяется, если он есть.
  • Графический установщик и пакеты .deb и .rpm пока не подписаны сертификатом издателя. Windows показывает издателя как неизвестного. Скачивайте их только из GitHub Releases и сравнивайте значения SHA-256 с release-checksums.json.
  • Выпуск, который меняет схему базы данных, устанавливается, только когда сервер сделал и проверил свежую резервную копию. См. Обновления.

Что отправляется в хаб ProAnimaStudio ​

Обновления одобряются в хабе ProAnimaStudio (https://hub.proanima.net). Сервер обращается к нему в таких случаях:

ДанныеКогдаСодержимое
Проверка обновленийКаждые 6 часовТекущая версия, операционная система и архитектура входят в адрес. При включённой статистике — случайный ID установки в заголовке X-Install-Id
Событие updatedПосле установленного обновления, при включённой статистикеВерсия и ID установки
Обратная связьТолько когда пользователь отправляет форму в консолиТекст, необязательный адрес электронной почты для ответа, до 6 снимков экрана и журнал страницы браузера. Администратор может добавить последние 1,5 МиБ журнала API и сводку о системе. Форма показывает всё это перед отправкой (Показать, что будет приложено)

ID установки — случайный UUID в config/install-id. В нём нет ни имени, ни адреса, ни содержимого. В проекте указано, что хаб не хранит IP-адреса, имена и содержимое файлов. Без статистики ID не отправляется, а хаб предлагает версию, только когда она выпущена для всех установок. Сводка о системе содержит версии, номер схемы и состояние обновлений и зеркал, без адресов и секретов. В журнале API тоже нет секретов.

Как это отключить:

bash
sudo arkvory configure --root /opt/proanima-arkvory --statistics off
sudo arkvory configure --root /opt/proanima-arkvory --hub-off
  • --statistics off прекращает отправку ID установки и событие updated. В консоли есть такой же переключатель: Отправлять анонимную статистику в ProAnimaStudio в разделе Обновления.
  • --hub-off прекращает любое обращение к хабу. Тогда обновления приходят только с GitHub, а обратная связь в консоли выключается после следующего перезапуска служб. Вместо неё пользователям показывается контактный адрес.
  • --hub-url https://hub.example направляет сервер на другой хаб. Принимается только HTTPS или HTTP на loopback.

Проверки каждые 6 часов выполняются и при выключенной автоматической установке. Сервер без доступа в интернет устанавливает обновления из локальной копии выпуска. См. Обновления.

Копии секретов ​

Vault хранит каталог, хеши паролей и все опубликованные файлы. Arkvory шифрует его при создании, а набор восстановления нужно хранить вне сервера (см. Резервные копии). Файлов вашей конфигурации в vault нет. Храните вторую копию этих файлов в зашифрованном месте вне сервера:

  • набор восстановления vault копий: это единственный способ прочитать копии, если потеряны сервер и его файл ключа; храните две копии в двух местах.
  • config/keys.json и config/bootstrap-token.txt (ключ восстановления),
  • config/runtime.json,
  • сертификат TLS и ключ,
  • config/mirrors/ с ключами зеркал,
  • config/hub.json и github-token.txt, если вы ими пользуетесь.

Восстановление создаёт новый экземпляр с собственными настройками и собственным файлом ключей. После восстановления сессий нет, персональные токены и ключи сервисов отозваны, а политики очистки и хранения выключены. Выпустите новые ключи и включите политики снова осознанно. Пароли возвращаются такими, какими были на момент снимка. Относитесь к каждой копии этих файлов как к секрету. См. Резервные копии.

Сообщите об уязвимости ​

Не описывайте уязвимость и не публикуйте ключи в открытой задаче. Владелец проекта — Ian Panaev (учётная запись GitHub ProAnima). Отдельного закрытого канала для сообщений о безопасности проект пока не опубликовал. Отправьте короткое сообщение без подробностей эксплойта через учётную запись проекта на GitHub или на адрес студии, который показывает консоль, info@proanima.net, и попросите закрытый способ продолжить. См. SECURITY.md в репозитории.

Arkvory · ProAnimaStudio