aws-ec2-sshでEC2の踏み台サーバのユーザ管理を楽にする

この記事は、[Business Bank Group Developers Advent Calendar](https://qiita.com/advent-calendar/2018/bbg_developers) 4日目の記事です。

---

こんにちは、ビジネスバンクグループでエンジニアをしている @bigplants です。
走る事に魂を燃やし、最近では帰宅ランを取り入れるようになりました。
死ぬまでにしたい事は走って本州縦断する事です。

# はじめに
みなさん、AWSのEC2で踏み台サーバを立てるとき、ユーザ管理どうしてますか？
特にSSH公開鍵の管理です。

実際にありそうなパターンをみていきましょう。

# 鍵管理のパターン
## キーペアを各メンバー間で共有
EC2のインスタンス作成時に作成するキーペアを共有する。
Amazon Linuxの場合、`ec2-user`というユーザがデフォルトで存在しますが、このユーザをみんなで共有する事になります。

このケースの場合は、そもそもユーザ管理ができていません。
さらにキーペアをどこかに保管しておかなければいけない為、セキュアとは言えません。
同じ鍵を全員に配布している時点で、鍵が流出しても経路を追えません。
不正アクセスがあった場合はキーペアを再発行する手続きが必要ですが、これが非常に面倒です。(以下リンクがヒント)
[SSH キーペアを紛失した場合、EC2 インスタンスへのアクセスを復旧するにはどのようにしたらよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/recover-access-lost-key-pair/)

## サーバ管理者がユーザ作成および鍵発行
キーペアの共有はそもそもユーザを管理できないので、チーム開発において採用される事はあまり無いでしょう。
次にとられる対応としては、サーバ管理者が予め踏み台サーバ上にユーザ作成と鍵発行を行うというものです。

このケースの場合、当然ですがサーバ管理者の負担が大きくなります。
メンバーの入れ替わりが激しいチームの場合は適切な運用をしないと古いユーザが残り続け、脆弱性を産む事もあり得るでしょう。
あと、メンバーに配布する秘密鍵をサーバ管理者が入手可能なのが気持ち悪い点です。
なのでメンバーが鍵生成して公開鍵をサーバ管理者に渡すのが一般的だと思いますが、これもまた運用が大変です。

# 理想的なユーザ管理
ここからが本題です。

理想的な運用は以下のようなものではないでしょうか？

* IAMのユーザと踏み台サーバのLinuxユーザを紐づける
* 鍵はIAMユーザ自身が管理し、サーバ管理者は関与しない
* メンバーの出入りの際、サーバ管理者はIAMユーザを作成および削除するだけ
* さらに、sudoユーザを絞る

これら全てを実現する方法を紹介します。

# aws-ec2-ssh

[aws-ec2-ssh](https://github.com/widdix/aws-ec2-ssh)というツールを使って前述の運用を実現します。

## インストール

```shell
# git clone https://github.com/widdix/aws-ec2-ssh.git
# cd aws-ec2-ssh
# ./install.sh
```

## IAMロール
以下のポリシーを持つEC2のIAMロールを作成し、該当するEC2インスタンスに紐づける。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListSSHPublicKeys",
                "iam:GetSSHPublicKey",
                "iam:GetGroup"
            ],
            "Resource": [
                "arn:aws:iam::*:user/*",
                "arn:aws:iam::*:group/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "iam:ListUsers",
            "Resource": "*"
        }
    ]
}
```
## IAMグループの作成
この例では、管理者グループを作成しそのグループに所属するユーザのみsudo権限を持つようにしたいと思います。

作成するグループ

* members
* admins

ポリシーは空で問題ありません。

## IAMユーザの作成
以下のユーザを作成します。

| ユーザ名       |       所属グループ |   
|:-----------------|------------------:|
| ichiro             |              members, admins |
| jiro           |            members |

## 各ユーザによるSSH公開鍵の登録
作業マシンで発行したSSH公開鍵を以下から登録します。
IAM -> ユーザ -> 該当のユーザ -> 認証情報タブ -> SSH公開キーのアップロード

## サーバ側の作業
以下のファイルを作成

```shell:/etc/aws-ec2-ssh.conf
IAM_AUTHORIZED_GROUPS="members" # IAMグループ(管理対象のグループ)
LOCAL_MARKER_GROUP="iam-synced-users" # 任意の名前
SUDOERS_GROUPS="admins" # IAMグループ(管理者のグループ)

# Remove or set to 0 if you are done with configuration
# To change the interval of the sync change the file
# /etc/cron.d/import_users
DONOTSYNC=0 # 0でユーザの同期が実行される。デフォルトで10分毎に同期。詳しくは/etc/cron.d/import_users
```

手動で同期

```shell
# sh /opt/import_users.sh
```

確認

```shell
# ls /home
ec2-user  ichiro  jiro
```

ユーザが作成されました。

sshdを再起動

```shell
# service sshd restart
Stopping sshd:                                             [  OK  ]
Starting sshd:                                             [  OK  ]
```

以上で作業は終わりです。

## 動作確認
### ichiro

```shell

$ ssh ichiro@<pub ip> -i <private_key>
Last login: Mon Dec  3 17:07:36 2018 from kd111099141246.ppp-bb.dion.ne.jp

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

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
[ichiro@ip-172-31-27-149 ~]$ sudo su
[root@ip-172-31-27-149 ichiro]#
```

ちゃんとsudoできています。

### jiro
```shell
$ ssh jiro@<pub_ip> -i <private_key>
Last login: Mon Dec  3 17:09:30 2018 from kd111099141246.ppp-bb.dion.ne.jp

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

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
[jiro@ip-172-31-27-149 ~]$
[jiro@ip-172-31-27-149 ~]$ sudo su
[sudo] password for jiro:
```

sudoできない事を確認しました。

# このツールの仕組み
## ユーザ管理
* cronで10分に一度、IAMユーザとLinuxユーザが同期される。
* IAMユーザと同名のLinuxユーザが作成される。IAMユーザを削除した場合はLinuxユーザも削除される。
* 管理対象のユーザは先ほどの設定ファイルの変数 `LOCAL_MARKER_GROUP` に指定したグループに紐づく。このグループに属さないユーザには一切影響はない。

## SSH認証
* `/etc/ssh/sshd_config` の `AuthorizedKeysCommand` でIAMからSSH公開鍵を取得し照合する

なので、ssh接続時に若干ラグがある。

# 運用
では実際に通常の運用がどうなるか見てみましょう。

## メンバーを参加させる場合
1. 管理者がIAMユーザを作成し、グループを紐づける
2. メンバーにアカウント情報を渡し、SSH公開鍵を登録するよう依頼
3. メンバーが鍵を自分のIAMユーザに登録し、ログイン確認
4. 以上

## メンバーを除外する場合
1. 管理者が該当IAMユーザを削除
2. 以上

このようなシンプルで素晴らしい運用ができます。

# さいごに

いかがでしたでしょうか？
楽じゃないですか？
イカしてないですか？？
サイコーじゃないですか？？？

これがIAMをうまく活用した、あるべき姿だと思っています。

この記事をキッカケに、あなたのAWSライフに小さな花が咲いたら幸いです。


明日は、 @Akiyah さんが担当です！
お願いします！