Ввод хост файлов SSH в докер-машину с помощью Docker Compose

Я использую Docker в Mac OS X с Docker Machine (с машиной boot2docker по умолчанию), и я использую docker-compose для настройки моей среды разработки.

Скажем, что один из контейнеров называется "stack". Теперь я хочу позвонить:

docker-composer run stack ssh [email protected]

Мой открытый ключ (который был добавлен в stackoverflow.com и который будет использоваться для аутентификации меня) находится на главной машине. Я хочу, чтобы этот ключ был доступен для контейнера Docker Machine, чтобы я смог аутентифицироваться против stackoverflow, используя этот ключ из контейнера. Предпочтительно без физического копирования моего ключа на Docker Machine.

Есть ли способ сделать это? Кроме того, если мой ключ защищен паролем, есть ли способ разблокировать его один раз, поэтому после каждой инъекции мне не нужно вручную вводить пароль?

Ответ 1

Вы можете добавить это в свой файл docker-compose.yml(если ваш пользователь внутри контейнера root):

volumes:
    - ~/.ssh:/root/.ssh

Также вы можете проверить более продвинутое решение с ssh-агентом (я сам не пробовал)

Ответ 2

Docker имеет функцию под названием секреты, которая может быть полезна здесь. Чтобы использовать его, можно добавить следующий код в docker-compose.yml:

---
version: '3.1' # Note the minimum file version for this feature to work
services:
  stack:
    ...
    secrets:
      - host_ssh_key

secrets:
  host_ssh_key:
    file: ~/.ssh/id_rsa

Затем к новому секретному файлу можно получить доступ в Dockerfile следующим образом:

RUN mkdir ~/.ssh && ln -s /run/secrets/host_ssh_key ~/.ssh/id_rsa

Секретные файлы не будут скопированы в контейнер:

Когда вы предоставляете вновь созданный или работающий сервис доступ к секрету, расшифрованный секрет монтируется в контейнер в файловой системе в памяти

Для более подробной информации, пожалуйста, обратитесь к:

Ответ 3

Вы можете перенаправить SSH-агент:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent

Ответ 4

Если вы используете OS X и зашифрованные ключи, это будет PITA. Вот шаги, которые я прошел, чтобы выяснить это.

Прямой подход

Можно подумать, что нет проблем. Просто смонтируйте вашу папку ssh:

...
volumes:
  - ~/.ssh:/root/.ssh:ro
...

Это должно работать, верно?

Проблема пользователя

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

...
volumes:
  - ~/.ssh:/root/.ssh-keys:ro
command: sh -c ‘./.ssh-keys.sh && ...
environment:
  SSH_USER: $USER
...

# ssh-keys.sh
mkdir -p ~/.ssh
cp -r /root/.ssh-keys/* ~/.ssh/
chown -R $(id -u):$(id -g) ~/.ssh

cat <<EOF >> ~/.ssh/config
  User $SSH_USER
EOF

Проблема с парольной фразой SSH

В нашей компании мы защищаем ключи SSH с помощью ключевой фразы. Это не сработает в Docker, поскольку вводить парольную фразу при каждом запуске контейнера нецелесообразно. Мы можем удалить фразу-пароль (см. Пример ниже), но есть проблема безопасности.

openssl rsa -in id_rsa -out id_rsa2
# enter passphrase
# replace passphrase-encrypted key with plaintext key:
mv id_rsa2 id_rsa

Раствор агента SSH

Возможно, вы заметили, что локально вам не нужно вводить парольную фразу каждый раз, когда вам нужен ssh-доступ. Это почему? Вот для чего нужен агент SSH. Агент SSH - это сервер, который слушает специальный файл, сокет unix, который называется "ssh auth sock". Вы можете увидеть его местоположение в вашей системе:

echo $SSH_AUTH_SOCK
# /run/user/1000/keyring-AvTfL3/ssh

SSH-клиент связывается с SSH-агентом через этот файл, так что вы должны ввести пароль только один раз. Как только он зашифрован, агент SSH сохранит его в памяти и отправит клиенту SSH по запросу. Можем ли мы использовать это в Docker? Конечно, просто смонтируйте этот специальный файл и укажите соответствующую переменную окружения:

environment:
  SSH_AUTH_SOCK: $SSH_AUTH_SOCK
  ...
volumes:
  - $SSH_AUTH_SOCK:$SSH_AUTH_SOCK

Нам даже не нужно копировать ключи в этом случае. Чтобы подтвердить, что ключи доступны, мы можем использовать утилиту ssh-add:

if [ -z "$SSH_AUTH_SOCK" ]; then
  echo "No ssh agent detected"
else
  echo $SSH_AUTH_SOCK
  ssh-add -l
fi

Проблема поддержки монтирования сокетов unix в Docker для Mac

К сожалению для пользователей OS X, Docker для Mac имеет ряд недостатков, одним из которых является невозможность совместного использования сокетов Unix между Mac и Linux. Theres открытый вопрос в D4M Github. По состоянию на февраль 2019 года он все еще открыт.

Так это тупик? Нет, есть хакерский обходной путь.

Решение для пересылки агента SSH

К счастью, эта проблема не нова. Задолго до Docker существовал способ использовать локальные ключи ssh в удаленном сеансе ssh. Это называется переадресацией агента ssh. Идея проста: вы подключаетесь к удаленному серверу через ssh, и вы можете использовать там все те же удаленные серверы, таким образом разделяя ваши ключи.

С Docker для Mac мы можем использовать хитрый прием: совместно использовать агент ssh с виртуальной машиной докера с помощью TCP-соединения ssh и монтировать этот файл из виртуальной машины в другой контейнер, где нам нужно это соединение SSH. Вот картина, чтобы продемонстрировать решение:

SSH forwarding

Сначала мы создаем сессию ssh на ssh-сервере внутри контейнера внутри виртуальной машины Linux через TCP-порт. Мы используем настоящий ssh auth sock здесь.

Затем сервер ssh пересылает наши ключи ssh агенту ssh в этом контейнере. Агент SSH имеет сокет Unix, который использует расположение, смонтированное на виртуальной машине Linux. Т.е. сокет Unix работает в Linux. Неработающий файл сокета Unix в Mac не имеет никакого эффекта.

После этого мы создаем наш полезный контейнер с SSH-клиентом. Мы делимся файлом сокетов Unix, который использует наш локальный сеанс SSH.

Существует множество скриптов, которые упрощают этот процесс: https://github.com/avsm/docker-ssh-agent-forward

Заключение

Заставить SSH работать в Docker могло бы быть проще. Но это может быть сделано. И это, вероятно, будет улучшено в будущем. По крайней мере, разработчики Docker знают об этой проблеме. И даже решил это для Dockerfiles с секретами времени сборки. И есть предложение, как поддерживать доменные сокеты Unix.