Master/Slave 構成のクラスタにローカルPCからログインする (ssh-agent)

Master/Slave 構成のクラスタに、MasterのみがPublic IPを持っていて、Slaveはもっていない場合、一旦、マスタにログインしてから、スレーブにログインしますが、SSHのキーはどうしようということになると思います。PrivateKeyをマスターに転送するわけにもいかないですが、お約束のいい方法があります。`ssh-agent`を使う方法です。
　昔から知っていますが、使うたびに忘れるのでブログにメモしておくことにします。

* [ssh-agentの使い方](https://qiita.com/isaoshimizu/items/84ac5a0b1d42b9d355cf)

を参考にしています。

# ssh-agent

Man ページによると「ssh-agent」はPublic Key 認証(RSA, DSA, ECDSA, Ed25519)に使われる Private Keyを保持するプログラムです。ssh-agentは、Xセッションや、ログインセッションの最初で使われます。すべての他の Windowsや、プログラムは、ssh-agentのクライアントとしてスタートします。環境変数を通じて、agentは、自動的に配置され、ログイン時に認証に使われます。」とあります。何が環境変数なのでしょう？

> ssh-agent is a program to hold private keys used for public key authentication (RSA, DSA, ECDSA, Ed25519).ssh-agent is usually started in the beginning of an X-session or a login session, and all other windows or pro‐grams are started as clients to the ssh-agent program.  Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh(1).

# ssh-agentの起動

今回は、WSL(Windows Subsystem of Linux) を使っています。Macだと不要ですが、その場合の最初の手順は次のようです。なぜ`eval` なんでしょう？ 

```bash
eval `ssh-agent`
```

単独で、`ssh-agent` を実行すると次のようになります。これが、stdoutに出力されるだけです。だから、これを`eval`してあげることで、このスクリプトが動いて設定がされるようになります。`ssh-agent`のソケットやPIDなどの情報を環境変数として出力しています。おそらく、他のコマンドがこれを参照するのでしょう。

```bash
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-GTvAV4KkdXXT/agent.7611; export SSH_AUTH_SOCK;
SSH_AGENT_PID=7612; export SSH_AGENT_PID;
echo Agent pid 7612;
```

# ssh-agent に private key を追加する。
`ssh-agent` を起動したのちに、private key を追加します。`ssh-add`コマンドを使います。

```bash
$ ssh-add ~/ssh/id_rsa
```

# 設定を確認する

設定できたようです。設定されていないとここで何も表示されません。
```bash
$ ssh-add -l 
ssh-add -l
2048 SHA256:{SOME LETTERS} /home/ushio/.ssh/id_rsa (RSA)
```
他のオプションはどうでしょう？

```bash
usage: ssh-add [options] [file ...]
Options:
  -l          List fingerprints of all identities.
  -E hash     Specify hash algorithm used for fingerprints.
  -L          List public key parameters of all identities.
  -k          Load only keys and not certificates.
  -c          Require confirmation to sign using identities
  -t life     Set lifetime (in seconds) when adding identities.
  -d          Delete identity.
  -D          Delete all identities.
  -x          Lock agent.
  -X          Unlock agent.
  -s pkcs11   Add keys from PKCS#11 provider.
  -e pkcs11   Remove keys provided by PKCS#11 provider.
  -q          Be quiet after a successful operation.
```

`-L`が気になったのでたたいてみると、Public Key がかえってきました。

```bash
ssh-add -L    
ssh-rsa {Some value} /home/ushio/.ssh/id_rsa
```
これは、プライベートキーのパブリックキーなので、内容がid_rsa.pub とかと同じになりました。（私は private key を一つしか登録していないので）

# Master ノードでログインする

`ssh-agent` を使ってログインするときは、例えばsshだと`-A`オプションを使います

```bash
$ ssh -A azureuser@some.domain
```

ssh は 先ほどの `ssh-agent` の設定（環境変数）をリスペクトする機能があるようです。下記はsshのManの抜粋です。ホストごとにコンフィグレーションファイルでも設定できるようです。今回は負荷びりしませんが。

```
     -A      Enables forwarding of the authentication agent connection.  This can also be spec‐
             ified on a per-host basis in a configuration file.

             Agent forwarding should be enabled with caution.  Users with the ability to bypass
             file permissions on the remote host (for the agent's UNIX-domain socket) can
             access the local agent through the forwarded connection.  An attacker cannot
             obtain key material from the agent, however they can perform operations on the
             keys that enable them to authenticate using the identities loaded into the agent.
```

> -A 認証エージェントのコネクションのフォワーディングを可能にします。コンフィグファイルのなかで、pre-hostベースで指定することが可能です。
　エージェントフォワーディングは、注意しながらつかってください。リモートホストで、リモートファイルのパーミッションをバイパス出来るユーザは、フォワードコネクションを使って、ローカルエージェントにアクセス可能です。アタッカーは、エージェントから、キーマテリアルを取得できませんが、エージェントにロードされたIdentityを使って、認証が必要になるオペレーションが可能です。

# Slave ノードでログインする

`-A` オプション付きでsshでログインするとエージェントフォワーディング機能が有効になります。ですので、プライベートIPを使って、他のノードに`-A`で同じようにログインします。キーを転送する必要はありません。

```bash
ssh -A azureuser@10.0.0.4
```
でログインできます。

# git 
git は普通にサポートしているようです。本当はサポートしてるぜと明確に書いているリソースを探したのですが、うまく探せませんでした。しかし、普通になんのオプションも追記せず、プライベートリポジトリのクローンが、slave 側でも可能になります。

Slave側で、env を叩くと、`SSH_AUTH_SOCK` が設定されているのがわかります。

```bash
$ env
SSH_AUTH_SOCK=/tmp/ssh-czWFbuHunV/agent.87078
```

# scp
scp も何も指定しなくても動作しました。

```bash
$ scp ./DocumentApi.csv azureuser@10.0.0.5:/home/azureuser
DocumentApi.csv           
```


# リソース

調べている経過でいろいろ有用なブログを見つけたのではっておきます。

* [ssh agent forwardingを行うサーバー側の要点の備忘録](https://qiita.com/hirotaka-tajiri/items/5197c8fa7f32d766c9cc)
* [【SSH】ssh-agent の使い方](https://laboradian.com/how-to-use-ssh-agent/)