[AWS] SessionManagerでSSH可能に。だったらSSHだけに制限したい。

AWS Systems Manager の Session Manager で、 SSH（とSCP）が可能になりました。

＜参考＞
[[AWS] セッションマネージャーが SSH と SCP のトンネリングサポートを開始](https://aws.amazon.com/jp/about-aws/whats-new/2019/07/session-manager-launches-tunneling-support-for-ssh-and-scp/)
[[DevelopersIO] AWS Systems Manager セッションマネージャーでSSH・SCPできるようになりました](https://dev.classmethod.jp/cloud/aws/session-manager-launches-tunneling-support-for-ssh-and-scp/)

これまでの Session Manager は、誰が利用してもOS上では同じユーザー（ssm-user）でした。接続時に区別するものが無いので当然ですね。
さらに、デフォルト設定ではパスワードなしで root にスイッチ可能です。

これ、権限統制的には使いづらいですよね。
個人で使っているサーバならともかく、複数人で利用するものであればOSユーザーも別々に用意するはずで、権限も別々のはずです。
そしてrootにスイッチ可能なユーザーを誰でも使えては困るのです。
そのため「せっかくの機能なのに使わせられない」なんてケースもあったのではないでしょうか。

そこで今回登場したSSHトンネリング。
OSユーザーを分けて使うことが可能になります。

これを利用し

* 管理者は、従来のSessionManager接続でrootにスイッチできてもいい。
* その他のユーザーにはSSHだけ利用させたい。

という制御が実現できないかどうかを調べてみました。

# IAMポリシーで従来の接続方法を制限。



## 結論から
残念ながらIAMポリシーでは実現できませんでした。


## 調査内容

### 従来の接続とSSH接続の違いを見る。

接続時に発行するawsコマンドはそれぞれ以下になります。

```bash
# 従来の接続
aws ssm start-session --target i-XXXXXXXXXXXXXXXXX

# SSH接続
aws ssm start-session --target i-XXXXXXXXXXXXXXXXX --document-name AWS-StartSSHSession --parameters portNumber=22
```

パラメータ `--document-name` の有無が、違いになりますね。
これをポリシーで切り分け可能かどうかです、

### お試しポリシーその１

```json
{
    "Effect": "Allow",
    "Action": "ssm:StartSession",
    "Resource": [
        "arn:aws:ec2:*:*:instance/*",
        "arn:aws:ssm:*:*:document/AWS-StartSSHSession"
    ]
}
```

* `ssm:StartSession` を許可。
* 使用する `document` を `AWS-StartSSHSession` のみに制限。

#### 結果

```bash
# 従来の接続
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX
→接続可。

# SSH接続
$ ssh -i ~/.ssh/xxxxxxxxx.pem user-name@i-XXXXXXXXXXXXXXXXX -v
→接続可。
```

NGです。どちらも接続できてしまいます。
`document` を使わないコマンドに「 `document` を `AWS-StartSSHSession` のみに制限」は効かないんですね。


### お試しポリシーその２

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ssm:StartSession",
            "Resource": [
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ssm:*:*:document/AWS-StartSSHSession"
            ]
        },
        {
            "Effect": "Deny",
            "Action": "ssm:StartSession",
            "NotResource": [
                "arn:aws:ec2:*:*:instance/*",
                "arn:aws:ssm:*:*:document/AWS-StartSSHSession"
            ]
        }
    ]
}
```

* `ssm:StartSession` を許可。
* 使用する `document` を `AWS-StartSSHSession` のみに制限。
* `document` が `AWS-StartSSHSession` ではない場合は `StartSession` を禁止。


#### 結果

```bash
# 従来の接続
$ aws ssm start-session --target i-XXXXXXXXXXXXXXXXX
→接続可。

# SSH接続
$ ssh -i ~/.ssh/xxxxxxxxx.pem user-name@i-XXXXXXXXXXXXXXXXX -v
→接続可。
```

こちらもNGでした。どちらも接続できてしまいます。
理由は「その１」と同じと思われます。
`document` を使わないコマンドに `Resource / NotResource` の `document` 指定は効かないんでしょう。おそらく。


### Condition で何か使えるものは無いか？
`Resource` がダメなら `Condition` です。
サービス別の `Condition Keys` を見てみましょう。

[Actions, Resources, and Condition Keys for AWS Systems Manager - Condition Keys for AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/list_awssystemsmanager.html#awssystemsmanager-policy-keys)

Systems Manager って、tag くらいしか `Condition` に使えないんですね。
今回のケースには使えなさそう。

### ダメでした。
というわけで、IAMポリシーで実現する方法は無さそうでした。
妙案があればコメント頂けると嬉しいです。

# "Run As" を利用
コメントで情報を頂きました `Run As` を利用する方法です。

[Enable Run As Support for Linux Instances](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-preferences-run-as.html) 

## 結論から
できます。
ただし、いくつか制約事項があります。
というかユーザー（権限）を分けたいだけなら、SSHを利用しなくても `Run As` だけで実現できますね。

## 実現方法
結論に書いた通り、ユーザーを分けたいだけなら `Run As` だけで実現できてしまいますが、ここではお題目にしている『SSHに制限する（従来の接続を禁止する）』方法について記載します。

1. SessionManagerの設定で `Run As support enabled` を有効にする。
![2019-07-23 15_21_34-AWS Systems Manager - Session Manager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193715/7b4fe84f-99c6-cc9d-4964-46516e574b08.png)

これだけです。
`Enter operating system user name` は未入力のままにしておきます。
通常の `Run As` の利用方法としては、SessionManager を利用するIAMユーザー or IAMロールに `SSMSessionRunAsタグ` を付与してOSユーザー名を指定しますが、ここではその設定は行ないません。

こうすることにより

* 従来の接続を実行しても、OSユーザー名の指定が無いため接続できない。
* SSH接続はその設定とは無関係なので接続可能。

となります。


## 制約事項
* 設定画面に `for Linux` と記述があるとおり、Linuxでのみ利用可能。
* `Run As support enabled` はリージョン単位での設定になる。 設定を変更すると当該リージョンの全インスタンスに影響があるため注意が必要。
* 利用者自身が自分の利用する IAMユーザー or IAMロール のタグを編集できないように権限設定をしておく必要がある。編集権限を持っていると、自分で `SSMSessionRunAs = ssm-user` と設定して従来の接続を利用できてしまうため。

# ssm-userのsudoを禁止する。

"Run As" を利用できないときのための手段です。

SSH接続を認める以上は、従来の接続方法も制限はできない。
もうそれはどうしようもない。

であれば考え方を変えます。
従来の接続方法は認める。ただし sudo は許さない。

↓こうします。

| 利用者 | ユーザー＆権限 |
|:----|:----|
| (従来の接続方法) | ssm-user。sudo 禁止。実質、何もできない。 |
| 管理者 | 個別に用意したOSユーザーでSSH。sudo可。 |
| その他のユーザー | 個別に用意したOSユーザーでSSH。sudo禁止。 |

ssm-user の sudo を禁止する方法については、下記ドキュメントをご参照ください。
AWS側ではなくOS側での設定変更が必要です。

[[AWS] ステップ 6: (オプション) ssm-user アカウントの管理権限を無効または有効にする](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-ssm-user-permissions.html)