【SSH】公開鍵認証とEC2について

## はじめに

SSHについての記事はたくさんありますが、どうしてもイメージとして捉えられませんでした。
先日AWSのデプロイを行った際に、RUNTEQの講師の方に説明をしていただいて自分なりに解釈したので書き記しておきます。
なお、これは覚書であって手順書ではないのでご注意ください。実際に行う手順は一部省略しています。

### こんな人が読んだら腑に落ちるかもしれない
- SSHはコピペでなんとかするもの。
- どうして公開鍵をいろんなところに登録するんだろう。
- 鍵とか錠とか言うけど、なんか納得できない。

## SSH鍵事始め

```terminal:ローカル
$ cd ~/.ssh
$ ssh-keygen
```
このコマンドによって、`~/.ssh`ディレクトリに（特に指定をしなければ）`id_rsa`と`id_rsa.pub`が作成される。前者が秘密鍵、後者が公開鍵となる。
前提として、公開鍵を外部に登録することはあるが、秘密鍵を登録することはない。というか、秘密鍵が漏れるとやばい。

[【 ssh\-keygen 】コマンド――SSHの公開鍵と秘密鍵を作成する：Linux基本コマンドTips（327） \- ＠IT](https://www.atmarkit.co.jp/ait/articles/1908/02/news015.html)

### よく言う鍵と錠の関係

よく、公開鍵は南京錠で秘密鍵はその鍵だと言う。確かに、錠は見せてもいいが鍵は見せてはならないと言うイメージではしっくりくるが、この鍵と錠は一対一の関係ではない。
実際はその南京錠を複製することがよくある。例えば、私は`id_rsa.pub`をGitHubとEC2インスタンス内に登録している。どちらも`id_rsa`で開けることができる。
また、一つのドアに複数の南京錠が付いていることもある。例えば、私のGitHubには複数の公開鍵が登録されている。この場合、いずれかの対応する秘密鍵があれば開けることができる。
![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/a7f52d4f-3e7e-24a2-602d-f38ed7049f31.jpeg)
（追記）コメントにてここのイメージについてご指摘をいただきました。
はんこと印影のイメージがとてもわかりやすかったので、参照していただけると幸いです。

## EC2に接続するときの手順

EC2インスタンスを作成するときに、新規にキーペアを作成する。（すでに鍵がある場合はそれを使うこともできる）
<img width="750" alt="スクリーンショット 2020-03-23 21.26.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/d59e2687-926f-6c42-41d1-950cd96d1b7f.png">
このときにダウンロードしたプライベートキー（pemファイル）を~/.ssh配下に保存しておく。
作成したインスタンスを選択して「接続」ボタンを押すと、手順が表示されるので、基本的にはそれに従えばいい。ありがたいね。
<img width="750" alt="スクリーンショット 2020-03-23 21.40.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322882/fc000224-7c12-7b86-2633-11857477fe89.png">

## SSH認証のエラーいろいろ
せっかくなので手順に従わずいろいろやってみたら、見事に怒られたので紹介する。

### "aws-key.pem"を指定しない場合

```terminal:ローカル
$ cd ~/.ssh
$ ssh ec2-user@18.176.56.238

ec2-user@18.176.56.238: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

特に鍵の指定がない場合は、`~/.ssh/id_rsa`を用いて認証を行う。
「`id_rsa`の公開鍵は登録されていないぞ。アクセスさせるわけにはいかない」

### ディレクトリに"aws-key.pem"がない場合

```terminal:ローカル
$ ssh -i "aws-key.pem" ec2-user@18.176.56.238

Warning: Identity file aws-key.pem not accessible: No such file or directory.
ec2-user@18.176.56.238: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

「そんな名前のファイルもディレクトリも無いぞ。鍵がないから駄目だ」

### `chmod 400 aws-key.pem`していない場合

```terminal:ローカル
$ ssh -i "aws-key.pem" ec2-user@18.176.56.238

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'aws-key.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "aws-key.pem": bad permissions
ec2-user@18.176.56.238: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
```

「ばっかやろう！その鍵は誰でも見れることになってるじゃないか！そんな鍵は認めないぞ！！」
[パーミッションについて](http://web.tku.ac.jp/~densan/local/permission/permission.htm)

## 手順に沿った場合

```terminal:ローカル
$ ssh -i "aws-key.pem" ec2-user@18.176.56.238

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
No packages needed for security; 6 packages available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-11-209 ~]$ sudo yum update
```
SSH認証に成功した場合、EC2インスタンス内に入ることができ、このように表示される。


### 公開鍵の場所
> 起動時に、パブリックキーコンテンツは、`~/.ssh/authorized_keys`内のエントリに配置されます。
[Amazon EC2 のキーペア - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html)

ということなので、実際に確認してみる。

```terminal:インスタンス
[ec2-user@ip-10-0-11-209 ~]$ cd ~/.ssh
[ec2-user@ip-10-0-11-209 .ssh]$ ls
authorized_keys
[ec2-user@ip-10-0-11-209 .ssh]$ cat authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCyZDViLAZcA7F8N8ebO9KlYoKOFC9hlG1y7BB6/R8grwcvKRGVhVCBRrCvLIoijkDfv+NYJnCyPxPb7QWdjQ/apD6FPfdmk9fdunyFRC5IRuFwXW17TUeVnBQwnHmatW/S36ZsDJxiK3O4s+L+WuK8XEriyddEHS1xLZi8+vNaTiSmqhNdPhhP/ocdAE/yWvSQqmdmTL4/HFVqp+Hy4C3v8+sgztj+F2+vpbHMmlb8aArdTMTDKcqPryNtLEN/ib1opqJLv4zhrv7EteqtCeFR6OnQttiAO+32UD0XP2mtj9lzsskCZ1wnNwG38WJbRdgD2mM/Ap8kNx0k/4Tkg7W3 aws-key
```
`authorized_keys`に`aws-key.pem`のペアとなるパブリッシュキーが登録されていることがわかる。

## EC2インスタンスの中で行う推奨設定
### 編集用ユーザーを追加する

> デフォルトのユーザーアカウントを使用するのが多くのアプリケーションに適しています。ただし、個人が自分のファイルとワークスペースを持つことができるように、ユーザーアカウントを追加することを選択できます。さらに、新しいユーザー用にユーザーアカウントを作成することは、デフォルトユーザーのアカウントへのアクセス権を複数のユーザーに (経験のないユーザーも含めて) 与えるよりも、はるかに安全です。
[Linux インスタンスでのユーザーアカウントの管理 - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/managing-users.html)

`ec2-user`はデフォルトユーザーなので、編集用のユーザーを作成する。

```terminal:インスタンス
[ec2-user@ip-10-0-11-209 ~]$ sudo useradd username  # usernameは任意の名前
[ec2-user@ip-10-0-11-209 ~]$ sudo passwd username
ユーザー username のパスワードを変更。
新しいパスワード:  # 表示されないが問題ない
新しいパスワードを再入力してください:
passwd: すべての認証トークンが正しく更新できました。
[ec2-user@ip-10-0-11-209 ~]$ sudo visudo  # vimエディタが開くので、usernameの行を追加する。

  ## Allow root to run any commands anywhere
  root      ALL=(ALL)       ALL
  username  ALL=(ALL)       NOPASSWD: ALL

[ec2-user@ip-10-0-11-209 ~]$ su - username  # usernameに切り替える
パスワード:  # 先ほど設定したパスワードを入力
[username@ip-10-0-11-209 ec2-user]$ cd ~/ 
```

これで、編集用ユーザーである`username`を作成することができた。

### 公開鍵を登録する

しかし、このままではusernameの`~/.ssh/authorized_keys`に公開鍵の情報が登録されていないので、外部から直接アクセスすることはできない。
なので、`authorized_keys`に公開鍵を登録する必要がある。

> 各ユーザー用にキーペアを作成し、インスタンスの各ユーザー用の`.ssh/authorized_keys`ファイルに各キーペアからのパブリックキー情報を追加できます。その後、ユーザーに対してプライベートキーファイルを配布できます。この方法では、AWS アカウントルートユーザー用に使用しているプライベートキーファイル（補足：`aws-key.pem`のこと）と同一のファイルを複数のユーザーに配布する必要はありません。
[Amazon EC2 のキーペア - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html)

```terminal:インスタンス
[username@ip-10-0-11-209 ~]$ mkdir .ssh
[username@ip-10-0-11-209 ~]$ chmod 700 .ssh
[username@ip-10-0-11-209 ~]$ touch ~/.ssh/authorized_keys
[username@ip-10-0-11-209 ~]$ chmod 600 ~/.ssh/authorized_keys
```

`authorized_keys`を作成し、このファイルに公開鍵情報を記述することで公開鍵情報を登録する。
[Linux インスタンスでのユーザーアカウントの管理 - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/managing-users.html)では、EC2で鍵を新たに作る手順を紹介しているが、ローカルで作成した既存の`id_rsa.pub`を登録することもできる。
これで、次回からは`$ ssh -i "鍵の名前" username@18.176.56.238`で、usernameとしてインスタンスにアクセスできる。

## おわりに

これはSSHについて教えてもらったことを私なりにデフォルメして解釈したものです。
間違っている点や書き落としなどございましたら、是非ご指摘いただければと思います。
また、この記事で作成したEC2インスタンスとキーペアは現在削除済みです。

## 参考リンク

- [SSH アクセスを行える新しいユーザーアカウントを Amazon EC2 Linux インスタンスに追加する](https://aws.amazon.com/jp/premiumsupport/knowledge-center/new-user-accounts-linux-instance/)
- [Amazon EC2のキーペア生成について、本来あるべき形](https://dev.classmethod.jp/articles/amazon-ec2-keypair-security/)
- [Linuxで「su」と「su -」の違いは?
](https://news.mynavi.jp/article/20180207-linux_su/)（個人的にここは理解が浅い）