AWS Session Manager ことはじめ

# はじめに

AWSのEC2インスタンスに接続する際、今まではEC2インスタンス作成時にssh鍵を作成し鍵を用いてssh接続していたが、鍵の管理が面倒であり、鍵の紛失等によるセキュリティ面の懸念があった。
このため、ssh接続を禁止し、Session Managerを用いてEC2に接続することとする。
また、Session Managerを使用することで、セキュリティグループにてssh（ポート22番）の許可設定も不要になる。

前提として、EC2のOSは`Amazon Linux 2`を採用している。

# 準備

Session Managerを使用するには、EC2上に専用のアプリ`ssm-agent`をインストールし、適切なロールをアタッチする必要がある。
Systems ManagerのHost Managementの「作成」ボタンを押す（下記画面）ことで、選択したリージョンのEC2に`ssm-agent`が自動でインストールされ（プロセスとして`amazon-ssm-agent`と`ssm-agent-worker`の2つが起動する）、`ssm-user`アカウントが作成される。今回はこれを利用した。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229057/a9273071-e1a7-c61f-ce04-8757624d6b13.png" width=60% />

EC2には自動で作成された`AmazonSSMRoleForInstancesQuickSetup`ロールが付与される。ロールを変更する場合には、EC2コンソールから可能（下記画面）。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229057/5079f4db-f26f-3be4-99f6-2c725ca0ea78.png" width=60% />

Session Managerを使用するIAMアカウントには適切なポリシー設定が必要になる。今回は、下記のポリシーを作成し、IAMアカウントにこのポリシーを適用した。
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ssm:GetConnectionStatus",
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:ssm:<region>:*:document/*",
                "arn:aws:ec2:<region>:<account id>:instance/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ssm:DescribeInstanceInformation",
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "ssm:ResumeSession",
                "ssm:TerminateSession"
            ],
            "Resource": "arn:aws:ssm:*:*:session/${aws:username}-*"
        }
    ]
}
```

# 接続

Session ManagerによるEC2への接続は、EC2コンソールや社内のPCから可能。EC2コンソールではブラウザ内での接続、開発PCでは`aws-cli`コマンドを利用しての接続となる。

## EC2コンソールから

EC2コンソールからは、接続したいEC2を選択後、「接続」ボタンを押すことで接続可能（下記画面参照）。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229057/075e8a64-99eb-932f-8886-d94011498e2f.png" width=60% />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229057/72ae6d2f-7cb9-6b7d-a2a2-9f37270751c1.png" width=60% />

下図のようにブラウザから接続できる。`ssm-user`でログインされ、`sudo`コマンドは利用可能となっている。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229057/2b1b8d34-9e4c-43eb-2494-1e18e9d2ad60.png" width=75% />

## 社内PCから

社内のPCから接続する場合は、AWSのコマンドラインツール`aws-cli`が必要で、少しの設定が必要になってくる。
`aws-cli`は適宜インストールする。また、別途`session-manager-plugin`が必要とのことなので、こちらもインストールしておく。

[AWS CLI の最新バージョンをインストールまたは更新します。](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)

[(オプション) AWS CLI 用の Session Manager プラグインをインストールする - AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)

（筆者のmacOSでは、`aws-cli`を`brew`にてインストールしたが、`session-manager-plugin`は別途インストールの必要はなかった。）

### セッショントークンの取得

社内のポリシーとして、各IAMアカウントにはMFA（多要素認証）を設定しているため、AWSにアクセスするためにはまずセッショントークンを取得し、これを使用する必要がある。
セッショントークン取得のためには、各IAMアカウントのアクセスキー（`AccessKeyId`と`SecretAccessKey`）が必要なため、払い出しておく。このアクセスキーを`default`プロファイルとして利用するには、下記のコマンドを実行。

```
$ aws configure

AWS Access Key ID [******************00]: 
AWS Secret Access Key [******************AA]: 
Default region name [ap-northeast-1]: 
Default output format [json]: 
```

下記のコマンドを実行すると、AWSにアクセスするための一時的なセッショントークンが払い出される。
`<account id>`には「012345678901」などのオーナーアカウントのIDを、`<iam username>`には、「yamada.taro」などの各IAMアカウントに割り当てられているユーザー名を、`<token code>`には「123456」などのAuthenticatorなどの2段階認証アプリが払い出したトークンコードを指定する。
このセッショントークンの期限はデフォルトで43,200秒（12時間）となっており、`--duration-seconds`オプションで最大129,600秒（36時間）まで指定可能（最小は900秒（15分））。

```
$ aws sts get-session-token --serial-number arn:aws:iam::<account id>:mfa/<iam username> --token-code <token code>

{
    "Credentials": {
        "AccessKeyId": "...",
        "SecretAccessKey": "...",
        "SessionToken": "...",
        "Expiration": "2022-10-03T21:08:46+00:00"
    }
}
```

取得した`AccessKeyId` `SecretAccessKey` `SessionToken`を使用して、Session Manager経由でEC2に接続することになる。
これらの値を環境変数やらAWSプロファイルにセットする必要があるが、手動で行うのは面倒なので自動化する。`mfa`プロファイルに自動でセットするコマンドを記す。

下記はmacOSで動作するコマンド。デフォルトシェルである`zsh`を使用している。コマンドを実行すると入力待ち状態になるので、Authenticatorなどのトークンコードを入力する。`jq`コマンドは別途インストールが必要。

```:macOSで確認
$ aws sts get-session-token --serial-number arn:aws:iam::<account id>:mfa/<iam username> --token-code "$(read v; echo $v)" | jq -r '.Credentials | to_entries[] | [.key, .value] | join(" ")' | sed "s/AccessKeyId/aws_access_key_id/;s/SecretAccessKey/aws_secret_access_key/;s/SessionToken/aws_session_token/; s/^/aws configure set --profile mfa /" | zsh
```

下記はWindowsで動作するコマンド。`PowerShell`で実行する。コマンドを実行すると入力待ち状態になるので、Authenticatorなどのトークンコードを入力する。
```:Windowsで確認
PS > $json = (aws sts get-session-token --serial-number arn:aws:iam::<account id>:mfa/<iam username> --token-code "$(Read-Host token-code)" | ConvertFrom-Json); aws configure set aws_access_key_id $json.Credentials.AccessKeyId --profile mfa; aws configure set aws_secret_access_key $json.Credentials.SecretAccessKey --profile mfa; aws configure set aws_session_token $json.Credentials.SessionToken --profile mfa
```

### 接続

上述で自動セットされた`mfa`プロファイルを用いて、Session Manager経由でEC2接続するには、下記コマンドを実行する。
`<instance id>`には、「i-123456789012」などのEC2のインスタンスIDを指定する。

```
$ aws ssm start-session --target i-<instance id> --profile mfa

Starting session with SessionId: yamada.taro-12345678901234567
sh-4.2$ 
```

以上で、`ssm-user`でログイン、接続される。`sudo`コマンドは利用可能となっている。

### sshセッション接続（主にファイル転送のため）

Session Manager経由して、EC2上の`sshd`に接続することも可能であり、ファイル転送する際にはssh接続して`scp`を利用する。この場合、EC2上でsshdが稼働している必要がある。
ただし、EC2上のsshdは、`localhost`からの接続のみを許可していればよく、セキュリティグループの設定は必要ない。
また、ssh接続するにはssh鍵が必要にはなる。が、従来のように各EC2用に鍵を払い出すのではなく、Session Manager経由のssh接続のために、鍵を1つ用意しておいたのでいいかもしれない。

ssh接続には、ssh設定の`ProxyCommand`を利用する。`.ssh/config`に以下のように記述する。

```conf:~/.ssh/config
# EC2 instances via Session Manager
Host i-*
    ProxyCommand sh -c “aws ssm start-session --profile mfa --target %h --document-name AWS-StartSSHSession --parameters ‘portNumber=%p’”
```

[ステップ 8: (オプション) Session Manager を通して SSH 接続のアクセス許可を有効にして制御する - AWS Systems Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html)

下記のようなコマンドで、ssh接続や`scp`によるファイル転送が可能となる。

```
$ ssh -i via_ssm.pem ec2-user@i-123456789012

$ scp -i via_ssm.pem ec2-user@i-123456789012:~/hoge.log ./
```

# さいごに

ssh鍵管理など煩雑な処理から解放されるはず。。
ポリシー設定により様々な制限も可能なので、今後試してみます。