web-dev-qa-db-ja.com

Docker Composeを使用して、ホストのSSHキーをDocker Machineに注入する

Mac OS XでDocker Machine(デフォルトのboot2dockerマシンを使用)でDockerを使用しており、docker-composeを使用して開発環境をセットアップしています。

コンテナの1つが「stack」と呼ばれるとしましょう。今私がしたいのは電話です:

docker-composer run stack ssh [email protected]

私の公開鍵(stackoverflow.comおよび私を認証するために使用されます)は、ホストマシンにあります。このキーをDocker Machineコンテナーで使用できるようにして、コンテナー内からそのキーを使用してstackoverflowに対して自分自身を認証できるようにします。できれば、物理的にキーをDocker Machineにコピーせずに。

これを行う方法はありますか?また、キーがパスワードで保護されている場合、一度ロックを解除する方法はありますか?

20
Ruslan

これをdocker-compose.ymlに追加できます(コンテナ内のユーザーがrootであると仮定):

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

また、 sshエージェントを使用したより高度なソリューション (自分で試していませんでした)を確認することもできます

37
Anton Serdyuk

Dockerにはsecretsという機能があります。これはここで役立ちます。それを使用するには、次のコードを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

秘密ファイルはコンテナにコピーされません:

新しく作成されたサービスまたは実行中のサービスにシークレットへのアクセスを許可すると、復号化されたシークレットはインメモリファイルシステムのコンテナにマウントされます

詳細については、以下を参照してください。

21
Anton Styagun

OS Xと暗号化されたキーを使用している場合、これはPITAになります。 手順は次のとおりです 私はこれを理解しました。

簡単なアプローチ

問題ないと思うかもしれません。 sshフォルダーをマウントするだけです:

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

これでうまくいくはずですよね?

ユーザーの問題

次に気付くのは、間違ったユーザーIDを使用していることです。 sshキーの所有者をコピーして変更するスクリプトを作成します。また、sshサーバーがだれが接続しているかを知るために、設定で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エージェントは基本的に、「ssh auth sock」と呼ばれる特別なファイル、unixソケットをリッスンするサーバーです。システム上の場所を確認できます。

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

SSHクライアントはこのファイルを介してSSHエージェントと通信するため、パスフレーズは1回だけ入力します。暗号化されていない場合、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

Mac用DockerでのUNIXソケットマウントサポートの問題

OS Xユーザーにとって残念なことに、Docker for Macにはいくつかの欠点があります。その1つは、MacとLinuxの間でUnixソケットを共有できないことです。 D4M Githubの未解決の問題 があります。 2019年2月の時点ではまだ開いています。

それで、それは行き止まりですか?いいえ、ハッキーな回避策があります。

SSHエージェント転送ソリューション

幸いなことに、この問題は新しいものではありません。 Dockerよりもずっと前に、リモートsshセッション内でローカルsshキーを使用する方法がありました。これは、sshエージェント転送と呼ばれます。アイデアは簡単です。sshを介してリモートサーバーに接続し、そこにあるすべての同じリモートサーバーを使用して、キーを共有できます。

Docker for Macでは、TCP ssh接続を使用してsshエージェントをdocker仮想マシンと共有し、そのファイルを仮想マシンからそのSSH接続が必要な別のコンテナにマウントします。ソリューションを示すための写真を次に示します。

SSH forwarding

まず、linux VM through a TCP port。ここで実際のssh auth sockを使用します。)内のコンテナー内のsshサーバーへのsshセッションを作成します。

次に、sshサーバーはsshキーをそのコンテナのsshエージェントに転送します。 SSHエージェントには、Linux VMにマウントされた場所を使用するUnixソケットがあります。つまりUnixソケットはLinuxで動作します。 Macで動作しないUnixソケットファイルは効果がありません。

その後、SSHクライアントを使用して便利なコンテナを作成します。ローカルSSHセッションが使用するUnixソケットファイルを共有します。

そのプロセスを簡素化するスクリプトがたくさんあります: https://github.com/avsm/docker-ssh-agent-forward

結論

DockerでSSHを機能させるのは簡単だったでしょう。しかし、それはできます。そして、今後改善される可能性があります。少なくともDocker開発者はこの問題を認識しています。そして ビルド時の秘密を持つDockerfilesのためにそれを解決した 。そして 提案があります Unixドメインソケットをサポートする方法。

9
Vanuan

SSHエージェントを転送できます:

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