Перейти к содержанию

Настройка SSH-доступа

Пошагово: что нажать в админке и что положить на ваш сервер. Что это за функция и зачем нужны два механизма — в обзоре раздела.

Настройка делается один раз. После неё сотрудник входит обычной командой ssh, а вы управляете доступом из интерфейса.

Шаг 1. Разрешите выдачу в админке

Ключ не появляется у сотрудника сам: сначала выдачу разрешает администратор.

  1. Откройте Настройки → Политика выдачи и включите строку «SSH» в колонке «Выдаём». У каждой цели здесь свой переключатель: включать «mTLS пользователя» или любую другую цель ради SSH не требуется. Если выдача включается не для всего парка машин, а точечно — откройте Устройства, раскройте строку нужной машины и в блоке «Цели на этой машине» переключите ssh с «как в системе» на «разрешить сверх системного» (или наоборот — «запретить вопреки системному», если у вас включена выдача по всему парку, а этой машине SSH не положен).
  2. Откройте Устройства, раскройте строку машины и назначьте ей цель ssh. Цель — это то, что Alatyr выдаёт на устройство; цель ssh означает SSH-ключ.

Результат. Через несколько минут агент на машине сотрудника создаст ключ и пришлёт его на одобрение.

Если ключ не появляется

Откройте Настройки → SSH-ключи и посмотрите на настройку «Требовать подтверждение identity у SSH-ключей». Если выбрано «Обязательно», сервер отклоняет регистрацию ключа до тех пор, пока на этом же устройстве нет одобренного сертификата user_mtls, ad_logon или k8s. Окно агента в этом случае покажет «Сервер отказал в регистрации ключа» и причину. Для начала работы выберите «Наблюдение»: вердикт продолжит записываться, но вход будет работать.

Шаг 2. Одобрите ключ

Откройте раздел SSH-ключи в левом меню. Новый ключ появится в списке со статусом pending. Проверьте, что владелец и устройство те самые, и нажмите «Одобрить».

Результат. Статус сменится на active — с этого момента Alatyr считает ключ действующим. Осталось научить ваш сервер спрашивать об этом.

Шаг 3. Возьмите два значения из админки

Откройте Настройки → SSH-ключи и найдите блок «Доверие на ваших серверах». В нём два значения:

  • Публичный ключ SSH CA — им подписаны сертификаты. Скопируйте его и сохраните на сервере как /etc/ssh/alatyr_user_ca.pub.
  • Список отзыва (KRL) — перечень отозванных сертификатов. Скачайте его и положите на сервер как /etc/ssh/alatyr.krl.

Оба значения открытые: их можно копировать, хранить в системе управления конфигурацией и раздавать на серверы обычным способом.

Результат. На вашем сервере лежат два файла: alatyr_user_ca.pub и alatyr.krl.

Шаг 4. Разрешите вашему серверу спрашивать Alatyr

Ваш сервер обращается к Alatyr через Keyholder — служебный интерфейс, предназначенный для серверов, а не для людей. По умолчанию он закрыт для всех, и его нужно открыть для ваших адресов.

В том же разделе Настройки → SSH-ключи:

  1. В поле «Разрешённые сети (CIDR)» перечислите подсети, из которых будут приходить запросы, — например 10.0.5.0/24. Пустое поле означает «закрыто для всех». Это не оплошность, а умолчание: пока вы не назовёте хотя бы одну подсеть, ваши серверы будут получать отказ.

    Подсеть должна быть узкой: не шире /24 для IPv4 и не шире /64 для IPv6. Это граница между «наши хосты» и «наша сеть»: Keyholder — служебный интерфейс для считанных серверов, и сеть вроде 10.0.0.0/8 впустила бы к нему всех, кто в неё попадает. Список из нескольких /24 — норма; одна широкая запись сервер отклонит с ошибкой, и это не сбой, а тот же предел. 2. Если ограничения по сети вам недостаточно, включите «Серверный токен держателя ключа» и создайте токен кнопкой ниже. Значение токена показывается один раз — сохраните его сразу, восстановить нельзя.

Результат. Запросы с ваших серверов больше не отклоняются по адресу.

Что даёт разрешённая сеть, а что нет

Список подсетей ограничивает, откуда можно спрашивать, но не о ком. Любой хост из разрешённой сети может запросить ключи любого сотрудника. Если это неприемлемо, включайте токен.

Шаг 5. Настройте ваш сервер

Положите на сервер файл настроек:

# /etc/ssh/sshd_config.d/alatyr.conf

# Сертификаты: сервер проверяет подпись сам, в сеть не ходит.
TrustedUserCAKeys /etc/ssh/alatyr_user_ca.pub
RevokedKeys       /etc/ssh/alatyr.krl

# Ключи из реестра: сервер спрашивает Alatyr на каждый вход.
AuthorizedKeysCommand     /etc/ssh/alatyr-keys.sh
AuthorizedKeysCommandUser root

И сам скрипт, который ходит за ключами:

#!/bin/sh
# /etc/ssh/alatyr-keys.sh — sshd передаёт имя учётной записи первым аргументом
set -eu
. /etc/ssh/alatyr.env

curl -fsS -m 5 \
  -H "Authorization: Bearer $KEYHOLDER_TOKEN" \
  "$ALATYR_URL/api/v1/keyholder/keys?principal=$1" \
  | python3 -c 'import json,sys; [print(k) for k in json.load(sys.stdin)["keys"]]'

Рядом — файл с адресом сервера и токеном:

# /etc/ssh/alatyr.env
ALATYR_URL=https://alatyr.example.com
KEYHOLDER_TOKEN=<значение из шага 4>
sudo chown root:root /etc/ssh/alatyr.env
sudo chmod 0600 /etc/ssh/alatyr.env

Отдельный файл нужен не для порядка: sshd запускает AuthorizedKeysCommand с пустым окружением, поэтому переменные, заданные в профиле или в systemd, до скрипта не доходят.

ALATYR_URL — адрес вашего сервера Alatyr, тот же, что в адресной строке админки. Если токен вы не включали (шаг 4), строку с Authorization из скрипта уберите, а KEYHOLDER_TOKEN из файла удалите.

Разбирайте ответ целиком, а не поиском по строке

Ключи Alatyr начинаются с ecdsa-sha2-nistp256, а не с ssh-. Пример выше разбирает JSON, поэтому работает с любым типом ключа; самодельный фильтр вида grep ssh- не найдёт ничего и даст отказ входа без объяснения.

Скрипт должен принадлежать root — иначе sshd откажется его запускать:

sudo chown root:root /etc/ssh/alatyr-keys.sh
sudo chmod 0755 /etc/ssh/alatyr-keys.sh

# Debian и Ubuntu:
sudo systemctl reload ssh
# RHEL, CentOS, Alma, Rocky, SUSE:
sudo systemctl reload sshd

Права 0755 и владелец root — это требование sshd: он отказывается запускать команду, в которую может писать кто-то кроме владельца.

Результат. sshd прочитал настройку — проверьте это командой:

sudo sshd -T | grep -i authorizedkeyscommand

В ответе должен быть путь /etc/ssh/alatyr-keys.sh.

Обновление списка отзыва

Список отзыва не обновляется сам — поставьте задание по расписанию:

#!/bin/sh
# /etc/ssh/alatyr-krl-update.sh — запускается от root, раз в час
set -eu
. /etc/ssh/alatyr.env

KRL=/etc/ssh/alatyr.krl
TMP=$(mktemp /etc/ssh/.alatyr.krl.XXXXXX)
trap 'rm -f "$TMP"' EXIT
curl -fsS -m 15 -H "Authorization: Bearer $KEYHOLDER_TOKEN" \
     "$ALATYR_URL/api/v1/keyholder/krl" -o "$TMP"
[ -s "$TMP" ] || { echo "пустой список отзыва — не подменяю" >&2; exit 1; }
ssh-keygen -Q -l -f "$TMP" >/dev/null || { echo "файл не разбирается" >&2; exit 1; }
chmod 644 "$TMP"; mv "$TMP" "$KRL"; trap - EXIT

Три проверки в скрипте — не перестраховка:

  1. Скачиваем во временный файл. sshd читает этот файл на каждый вход; оборванная загрузка прямо в боевой файл закроет вход всем, включая вас.
  2. Не подменяем пустым. Пустой файл означает «никто не отозван». Положив его, вы вернёте доступ тем, у кого его забрали.
  3. Проверяем, что файл читается. Битый файл sshd не примет.

Скрипт пишет в /etc/ssh, поэтому запускается от root. Раз в час — достаточно: сертификат живёт сутки, и час задержки отзыва укладывается в его срок жизни.

sudo chown root:root /etc/ssh/alatyr-krl-update.sh
sudo chmod 0755 /etc/ssh/alatyr-krl-update.sh
echo '0 * * * * root /etc/ssh/alatyr-krl-update.sh' | sudo tee /etc/cron.d/alatyr-krl

Результат. Файл /etc/ssh/alatyr.krl существует и обновляется — проверьте дату командой ls -l /etc/ssh/alatyr.krl через час после установки задания.

Шаг 6. Направьте ssh сотрудника на ключ в чипе

Ключ живёт в чипе, и подаёт его агент Alatyr через свой сокет — а не обычный ssh-agent и не файл в ~/.ssh. В большинстве случаев клиент ssh находит этот сокет сам:

  • Windows — агент дописывает в ~/.ssh/config строку IdentityAgent, указывающую на его канал;
  • Linux — пакет кладёт /etc/profile.d/alatyr-agent-ssh-agent.sh, и обычная оболочка входа (bash, zsh, ksh) получает SSH_AUTH_SOCK автоматически;
  • macOS — сокет поднимается в пользовательской сессии.

Проверьте, что клиент видит именно ключ Alatyr:

ssh-add -l
# в списке должен быть ключ с пометкой (alatyr-agent)

Если ключа в списке нет — клиент смотрит на чужой ssh-agent. Так бывает, когда переменную SSH_AUTH_SOCK уже занял системный ключ-агент рабочего стола (GNOME Keyring и подобные) или оболочка не читает /etc/profile.d (например fish). Направьте клиент на сокет Alatyr явно.

Сокет агента:

Linux:  ~/.local/state/alatyr-agent/ssh-agent.sock
macOS:  ~/Library/Application Support/AlatyrAgent/ssh-agent.sock

Способ 1 — строка в ~/.ssh/config (действует всегда и переживает системный ключ-агент, и для ssh, и для scp, rsync, git):

Host *
    IdentityAgent ~/.local/state/alatyr-agent/ssh-agent.sock

Способ 2 — переменная окружения (в текущей оболочке или в профиле входа):

export SSH_AUTH_SOCK=~/.local/state/alatyr-agent/ssh-agent.sock

Теперь пробуйте вход с машины сотрудника:

ssh ivan@server.example.com

На Linux и macOS в момент входа агент попросит подтвердить присутствие — в окне на рабочем столе сотрудника. Пока оно не подтверждено, вход ждёт; без ответа примерно через минуту он завершится ошибкой. Это ожидаемое поведение, а не сбой.

Окно разблокировки: чтобы не подтверждать присутствие на каждый вход

Подтверждение присутствия из предыдущего абзаца можно один раз выдать на несколько входов вперёд, а не проходить заново на каждую команду ssh. Срок такой выдачи называется окном разблокировки, и на трёх платформах он устроен по-разному:

  • Windows. Сотрудник сам задаёт себе окно командой агента:
alatyr-agent ssh-grant-window [минуты]

Без аргумента команда показывает текущее значение; с аргументом — задаёт новое, от 0 до 1440 минут (сутки). Пока окно не истекло, повторные входы подписываются без нового запроса Windows Hello. Значение 0 означает «спрашивать на каждый вход» — так и работает по умолчанию, пока сотрудник не задал своё. - macOS. Персонального значения нет: длительность выбирается прямо на уведомлении, которое появляется в момент подтверждения — кнопками на 1 минуту и на действующий максимум минут (число подставляется в подпись кнопки), плюс кнопка «Не сохранять». Дольше 5 минут окно не бывает ни при каком потолке, заданном администратором, — это жёсткий предел Touch ID (LATouchIDAuthenticationMaximumAllowableReuseDuration), а не решение продукта: macOS сам перестаёт держать повторное использование биометрии после этого срока. - Linux. Окна разблокировки нет вовсе: подпись SSH-ключа на Linux не поднимает системного запроса, который окно могло бы подавлять.

Потолок для всех платформ задаёт администратор: Настройки → Безопасность по умолчанию → «Окно разблокировки SSH — потолок для всех платформ (минуты, макс. 1440)». Своё значение, заданное сотрудником на Windows командой ssh-grant-window, не может превысить этот потолок — меньшее из двух побеждает всегда. На macOS потолок всё равно не даст больше 5 минут: платформенный предел применяется поверх административного. Значение 0 (по умолчанию) отключает повторное использование для всех: подтверждение присутствия спрашивается на каждый вход независимо от того, что сотрудник выставил себе сам.

Если вход прошёл — готово. Посмотрите в журнале сервера, чем именно вошли:

sudo journalctl -u ssh | grep "Accepted publickey"   # RHEL и SUSE: -u sshd
# ECDSA       — ключ из реестра
# ECDSA-CERT  — сертификат

Если вход не проходит

Проверяйте по порядку: сверху — самые частые причины.

«Permission denied (publickey)», а в журнале Alatyr нет ни одного обращения к /keyholder/keys. Ваш сервер не спрашивает Alatyr. Проверьте, что файл alatyr.conf действительно прочитан (sshd -T | grep -i authorizedkeyscommand) и что sshd перезапущен. Если на сервере уже был другой AuthorizedKeysCommand, смотрите «Совмещение с FreeIPA».

Проверьте Keyholder отдельно от входа. Выполните на вашем сервере:

. /etc/ssh/alatyr.env
curl -fsS -H "Authorization: Bearer $KEYHOLDER_TOKEN" \
  "$ALATYR_URL/api/v1/keyholder/keys?principal=ivan"

Успешный ответ выглядит так:

{"keys": ["ecdsa-sha2-nistp256 AAAAE2VjZHNh... alatyr-agent"]}

Пустой список {"keys": []} означает «действующих ключей для этого имени нет». Он же приходит для несуществующего имени — так сделано намеренно, чтобы перебором нельзя было узнать состав сотрудников.

Обращения есть, ответ пустой. Сервер Alatyr не считает ключ действующим. Откройте раздел SSH-ключи: ключ должен быть в статусе active, а имя учётной записи в запросе (principal) — совпадать с учётной записью на вашем сервере.

principal — это логин сотрудника на его рабочей машине; агент присылает его сам при регистрации ключа, и он виден в разделе SSH-ключи. Если на вашем сервере учётная запись называется иначе, вход не пройдёт: сервер спросит ключи для ivan, а зарегистрированы они на i.petrov.

Ответ 403. Адрес вашего сервера не попал в разрешённые сети — либо токен включён, а в запросе его нет.

Окно агента показывает «Сервер отказал в регистрации ключа». Причина написана там же, рядом. Чаще всего дело в настройке «Требовать подтверждение identity у SSH-ключей» — смотрите примечание к шагу 1.

Ключ у сотрудника не появляется вовсе. Проверьте, назначена ли машине цель ssh и включён ли переключатель «SSH» в колонке «Выдаём» (шаг 1). Полоса на вкладке Политика выдачи перечисляет цели, у которых собственный переключатель сейчас выключен.

Что дальше