Безопасность
Эта страница предназначена для администратора, который запускает сервер. Она начинается с шагов по защите новой установки, а затем подробно описывает каждую защиту.
В проекте указано, что модель угроз и внешняя проверка безопасности ещё не выполнены. Не публикуйте сервер в открытом интернете. Разрешайте доступ к нему только сетям ваших клиентов.
Защитите новый сервер
- Оставьте адрес прослушивания по умолчанию
127.0.0.1, пока HTTPS не заработает. См. Сеть и HTTPS. - Включите HTTPS и откройте клиентским сетям только порт HTTPS. Никогда не открывайте порт базы данных.
- Создайте личные учётные записи для администраторов. Ключ восстановления берегите для экстренных случаев. См. Ключ восстановления.
- Дайте каждому инструменту или системе CI собственную сервисную учётную запись с ключом, у которого минимум прав. См. Ключи и токены.
- Оставьте самостоятельную регистрацию выключенной. По умолчанию она выключена.
- Если перед Arkvory стоит обратный прокси, задайте
ARKVORY_TRUSTED_PROXIES. См. Ограничения входа. - Сделайте vault зашифрованным (так по умолчанию) и храните набор восстановления вне сервера. Кроме того, держите его на зашифрованном томе, который читают только учётная запись службы и администратор копирования. См. Резервные копии.
- Храните копии секретных файлов вне сервера. См. Копии секретов.
- Подключите метрики и оповещения. См. Мониторинг.
Сеть и HTTPS
По умолчанию сервер слушает 127.0.0.1:8080. Нативная установка может слушать другой адрес после настройки HTTPS:
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 строк и удаляет самые старые строки пакетами. Запросы, которые отклонили ограничения частоты, не записываются, поэтому поток запросов не может раздуть таблицу. Если нужна более длинная история, экспортируйте журнал в собственное хранилище событий.
curl -fsS -H "Authorization: Bearer $ARKVORY_KEY" "https://arkvory.example/api/v1/security/audit?limit=100"Чтобы прочитать более старые строки, используйте параметр after с последним ID.
Консоль и браузер
Сервер добавляет в ответы консоли такие заголовки:
| Заголовок | Значение |
|---|---|
Content-Security-Policy | default-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-Policy | no-referrer |
X-Content-Type-Options | nosniff |
Cache-Control | private, no-store |
X-Request-Id | ID запроса для этого ответа |
Каждый ответ 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 тоже нет секретов.
Как это отключить:
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 в репозитории.