Как безопасно получить ключи хоста ssh с экземпляра Google Compute Engine?

Вопрос или проблема

Я хочу обновить свой ~/.ssh/known_hosts с информацией о ключе хоста для newly созданного экземпляра GCE. Но я не уверен, как безопасно получить эту информацию.

Я думал, что что-то вроде

gcloud compute ssh <GCEUSER>@<GCEHOST> --command='ssh-keyscan 127.0.0.1'

может сработать. Но это (согласно документации gcloud compute ssh) похоже просто на обертку для ssh (и, исходя из того, что я увидел StrictHostKeyChecking=no в параметрах, указанных в соответствующем журнале под $HOME/.config/gcloud/logs/, похоже, что не производится никакой проверки идентичности хоста).

Похоже, есть способ использовать веб-консоль для запуска ssh-сессии на базе браузера (и интерактивно/вручную запустить ssh-keyscan), но 1) я не вижу внутренних деталей, чтобы понять, действительно ли это так безопасно, как должно быть, и 2) это неэффективный API для интеграции со скриптом.

Существует ли API/gcloud механизм для безопасного получения ключа хоста экземпляра GCE?

ОП ссылался на ошибку 35907612 (первоначально упомянутую Рахи), которая была помечена как “исправленная” с ссылкой на документацию Хранение ключей хостов.

Чтобы получить ключ хоста, необходимо включить “атрибуты гостя” до или во время создания экземпляра GCE. Я включил это для всего проекта (не знаю, почему это было отключено по умолчанию). В качестве альтернативы, у вас есть возможность включить это при создании экземпляра.

Согласно документации, gcloud требуется для заполнения атрибутов гостя, но каким-то образом я смог перейти к шагу “Подтверждение, что ключи хостов сохраняются как атрибуты гостя” сразу после запуска экземпляра.

заметки

  1. На Шаге 2 (подтверждение ключей) я выбрал Вариант 2, потому что я не просил gcloud заполнить ~/.ssh/google_compute_known_hosts на последнем шаге, поэтому я хочу увидеть ключи, а не просто подтвердить, что они “где-то”.

  2. Когда вы запускаете get-guest-attributes подкоманду, оба флага --project и --zone являются необязательными, и они берут значения из конфигурации, установленной с помощью gcloud config.

  3. Чтобы получить SHA-256 хэш для ключей хоста непосредственно из get-guest-attributes, с помощью jq:

    gcloud compute instances get-guest-attributes my-instance --format json |
      jq -r '.[] | "\(.key) \(.value) my-server-name"' | ssh-keygen -l -f -
    

    Объясните: -r означает --raw-output в jq. -l означает перечисление ключей с хэшами. -f - означает файл из stdin. my-server-name является необязательным комментарием, который появляется в выходных данных (в противном случае вы увидите no comment).

“gcloud command” или “API” будут только извлекать информацию, связанную с конкретным проектом или продуктами Google, такими как метаданные экземпляра из экземпляра GCE. Невозможно получить конфигурацию экземпляра, такую как ключи хоста, через команду gcloud или API.

Обновление

SSH ключи хоста, приватный и публичный ключи хранятся на SSH сервере. Публичный ключ делится с SSH клиентом при каждом подключении. Это используется для аутентификации SSH сервера клиенту. После первого соединения “известный хост” обычно сохраняется в ~/.ssh/known_hosts на SSH клиенте (вашем компьютере, например), хотя gcloud хранит его в другом месте.

Когда вы используете gcloud compute ssh, ваш SSH клиент ведет себя немного иначе: публичный ключ хоста сервера автоматически принимается для вас в первый раз, когда вы подключаетесь, и записывается в ~/.ssh/google_compute_known_hosts вместо этого.

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

Проверка ключа хоста не удалась.

Когда вы видите это сообщение, то одно из следующих является верным:

  • Вы подключаетесь к другому серверу. Это не всегда зловредно. Например, если вы заменили сервер на новый, вы увидите это сообщение.
  • Вы подключаетесь к тому же серверу, но его SSH ключи хоста были сгенерированы заново. Опять же, это не автоматически указывает на злонамеренное поведение. Например, администратор мог использовать ssh-keygen для создания новой пары ключей хоста.

По умолчанию, gcloud compute ssh не выполняет строгую проверку ключей хоста. На это есть причины; однако вы можете включить строгую проверку ключей хоста, добавив опцию –oStrictHostKeyChecking=yes к gcloud compute ssh. Вот пример:

gcloud compute ssh [INSTANCE_NAME] –zone [ZONE] — -oStrictHostKeyChecking=yes

Это хороший пример того, как вы можете добавить произвольные аргументы SSH к gcloud compute ssh.

Пропуск проверки ключей хоста не является проблемой. Предположим, вы создали новый экземпляр, к которому вы никогда не подключались. Как вы сможете знать, что вы подключаетесь именно к этому экземпляру, а не к чему-то другому?

Рассмотрим следующий пример. Предположим, у вас нет SSH ключа пользователя, который мог бы использовать gcloud. (Если вы отложите оба файла ~/.ssh/google_compute_engine и ~/.ssh/google_compute_engine.pub в сторону, вы сможете это протестировать.) Предположим, вы не вошли в систему gcloud. Вы можете выйти с помощью gcloud auth revoke.

Теперь попробуйте подключиться к экземпляру с помощью gcloud compute ssh. Сначала вам нужно будет аутентифицироваться в gcloud. Выполните gcloud auth login и войдите. Теперь в вашей системе есть токен доступа, сохраненный в ~/.config/gcloud/. Этот токен используется для аутентификации каждый раз, когда вы делаете вызов API с помощью gcloud.

Теперь попробуйте снова подключиться к тому же экземпляру с помощью gcloud compute ssh. Без SSH ключа пользователя он вызовет ssh-keygen от вашего имени для создания нового SSH ключа пользователя. Приватный (пользовательский) ключ будет сохранен в ~/.ssh/google_compute_engine, а публичный (пользовательский) ключ будет сохранен в ~/.ssh/google_compute_engine.pub. Приватный ключ остается локальным для вашего компьютера, и вы несете ответственность за его безопасность. Содержимое публичного ключа отправляется через вызов API к projects.setCommonInstanceMetadata или instances.setMetadata. По умолчанию gcloud добавит ваш публичный ключ в метаданные проекта (для всех экземпляров), если экземпляр, к которому вы подключаетесь, не был настроен для блокировки SSH ключей на уровне проекта; в этом случае он добавит публичный ключ в метаданные экземпляра. Оба вызова API аутентифицированы с токеном, который вы получили, когда выполнили gcloud auth login. Публичный ключ шифруется при передаче, потому что команды gcloud выполняются через вызовы API по HTTPS.

На этом этапе у вас есть совершенно новый приватный ключ пользователя SSH. Если вы не скопировали его куда-нибудь еще, он локален для вашего компьютера. То же самое касается его соответствующего публичного ключа, за исключением того, что вы поделились им с Google, отправив его через аутентифицированную команду gcloud по HTTPS. Поэтому единственные системы, которые должны иметь доступ к публичному ключу, это те, которые вы запускаете в своем проекте GCP.

Только держатель приватного ключа пользователя SSH может успешно аутентифицироваться на SSH сервер(ах), работающих в GCP. Только SSH сервер(ы), работающие в GCP, имеют копию вашего публичного ключа пользователя SSH. Таким образом, безопасно автоматически принять публичный ключ хоста. Если бы вы подключались к злонамеренному серверу вместо вашего GCP SSH сервера, процесс аутентификации бы потерпел неудачу, потому что тот другой сервер не имел бы вашего публичного ключа пользователя SSH.

В GCP есть определенные ситуации, когда автоматически воссоздается пара ключей хоста SSH сервера. Например, если вы используете экземпляр для создания шаблона, из которого будут генерироваться другие экземпляры в группе. В каждом случае возникает необходимость обновить SSH ключ хоста. По этой причине выполнение строгой проверки SSH ключей хоста может вызвать вводящие в заблуждение сообщения об ошибках.

обновление 5 сентября 2018 года

Возможно подключиться к экземпляру без “gcloud”, и команда GCP осведомлена об этом и работает над ним. Открытая ошибка зарегистрирована здесь. Любой прогресс можно найти там.

Нет, нет простого способа сделать это (существует открытая проблема, чтобы устранить этот риск безопасности).

Ключи хоста уже извлечены для вас на компьютере, на котором вы запускаете gcloud, в ~/.ssh/google_compute_known_hosts.

Согласно –help, поведение проверки ключей хоста следующее:

 --strict-host-key-checking=STRICT_HOST_KEY_CHECKING
    Переопределите поведение по умолчанию для StrictHostKeyChecking для
    подключения. По умолчанию StrictHostKeyChecking устанавливается в 'no' при первом
    подключении к экземпляру и будет установлено в 'yes' для всех
    последующих подключений. STRICT_HOST_KEY_CHECKING должно быть одним из: yes,
    no, ask.

Что является поведением в журнале, если вы посмотрите на последующие подключения.

2018-08-04 14:48:29,222 DEBUG    root            Running command [/usr/bin/ssh -t -i /home/john/.ssh/google_compute_engine -o CheckHostIP=no -o HostKeyAlias=compute.1520573357386694112 -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/home/john/.ssh/google_compute_known_hosts [email protected]].

2018-08-04 14:51:06,249 DEBUG    root            Executing command: [u'/usr/bin/ssh', u'-t', u'-i', u'/home/john/.ssh/google_compute_engine', u'-o', u'CheckHostIP=no', u'-o', u'HostKeyAlias=compute.1520573357386694112', u'-o', u'IdentitiesOnly=yes', u'-o', u'StrictHostKeyChecking=yes', u'-o', u'UserKnownHostsFile=/home/john/.ssh/google_compute_known_hosts', u'[email protected]']

Это удобно, чтобы первое подключение не спрашивало о хосте, но будущие будут проверять.

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

В этом случае ваше доверие к системе должно зависеть от того, насколько вы доверяете службе метаданных GCE для маршрутизации к правильному хосту и перемещения вашего ssh ключа к нему.

Ответ или решение

Для безопасного получения SSH-хост-ключей с экземпляра Google Compute Engine (GCE) есть несколько методов, которые следует тщательно учитывать. Эти шаги помогут вам обновить ваш файл ~/.ssh/known_hosts и гарантировать защищенное взаимодействие с вашей облачной инфраструктурой.

Понимание контекста

SSH-хост-ключи — это ключи, которые аутентифицируют SSH-серверы, позволяя клиентам удостовериться, что они подключаются к ожидаемым серверам. При первом подключении эти ключи могут быть автоматически приняты и добавлены в файл ~/.ssh/known_hosts. В случае GCE, ключи могут быть специально добавлены с помощью метаданных экземпляров, что требует особого подхода.

Подготовка к подключению

  1. Включение атрибутов гостя: Прежде чем начать, убедитесь, что атрибуты гостя включены для вашего экземпляра GCE или проекта. Это обеспечит хранение ключей в метаданных, что важно для их безопасного получения.

  2. Использование gcloud для получения ключей:
    По умолчанию, при первом подключении к экземпляру GCE через команду gcloud compute ssh, SSH-клиент автоматически принимает публичный хост-ключ и записывает его в файл ~/.ssh/google_compute_known_hosts. Но для получения ключей для ручного обновления вашего файла known_hosts, вы можете использовать команду get-guest-attributes.

Процесс безопасного получения хост-ключей

  1. Проверьте, что ключи хранятся как атрибуты гостя:

    gcloud compute instances get-guest-attributes <INSTANCE_NAME> --zone=<ZONE> --project=<PROJECT_ID> --format=json
  2. Извлечение и вывод ключей:

    Для получения SHA-256 хэш-функции хост-ключей используйте jq:

    gcloud compute instances get-guest-attributes <INSTANCE_NAME> --format json |
    jq -r '.[] | "\(.key) \(.value) <имя_вашего_сервера>"' | ssh-keygen -l -f -

    В данном случае:

    • -r – выводит результат в "сыром" формате,
    • -l – выводит хэши ключей,
    • -f - – позволяет использовать стандартный ввод.
  3. Обновите ваш файл known_hosts:

    Если вы получили ключи таким образом, вы можете их вручную добавить в ваш файл ~/.ssh/known_hosts, чтобы защитить себя от будущих возможных атак подмены.

Настройки для улучшения безопасности

  • Включение строгой проверки ключей:
    При подключении можно использовать флаг --oStrictHostKeyChecking=yes, чтобы обеспечить строгую проверку хост-ключей. Это требует, чтобы ключ был заранее известен и записан в known_hosts перед подключением.
gcloud compute ssh <INSTANCE_NAME> --zone <ZONE> -- -o StrictHostKeyChecking=yes

Заключение

Соблюдение этих шагов обеспечит безопасное управление SSH-хост-ключами при работе с Google Compute Engine. Обязательно регулярно проверяйте и обновляйте ваши ключи, чтобы избежать утечек информации и снизить риск атаки. Убедившись в правильной настройке хост-ключей, вы сможете уверенно подключаться к вашим облачным ресурсам, защищая свою инфраструктуру и данные.

Оцените материал
Добавить комментарий

Капча загружается...