SSM セッションマネージャーによるBastion設計

# セッションマネージャー
Systems Managerの機能の一つにセッショ、ンマネージャーが存在する
これは、今まで行っていたEC2などの接続に用いていた`ssh`を不要とするマネージドインスタンスへの接続方法を可能とする

## メリット
- `ssh`で必要としていた公開鍵の保管が不要となる
- IAMによる認証・認可ができる
- SSHポートへのインバウンドアクセス許可が不要になる
> 443番アウトバウント許可のみ必要です。SSM AgentがSSMエンドポイントに対してポーリング行なう際に使用します。
- ターミナル内で行ったログが取れる

# 設計
今回はインスタンスにFargateを用いたBastion構築を行います
その時考慮するべき点がいくつか存在する

## アクティベーションコードの運用
マネージドインスタンス化するためにアクティベーションIDとコードが必要となるがアクティベーションコードには有効期限がありデフォルトでは24時間となっている。そのため、必要な時だけ踏み台サーバーを起動する運用方針の場合、期限切れ後に起動したインスタンスはアクティベーション化することができない。

そこで、今回はECSタスク内で起動時に都度アクティベーションコードを発行＆削除する方針とした

> EC2インスタンスへのアクセスには料金が掛からなかったり、アクティベーションコードなどを発行する必要がない
ECSは仮想VM?でありハイブリッドマネージドインスタンス(フリートマネージャーで`mi-`のプレフィックスが付けられていることからわかる)に属するためアクティベーションコードの発行及び、時間単位の料金が発生する

> アクティベーションの有効期限は、オンプレミスのマシンを Systems Manager で登録できる時間帯です。Systems Manager に以前に登録した、サーバーまたは仮想マシン (VM) に、アクティベーションの期限切れの影響はありません。アクティベーションが期限切れになると、その特定のアクティベーションを使用して、複数のサーバーまたは VM を Systems Manager に登録することはできません。新しいものを作成する必要があるだけです。

[AWS Systems Manager ハイブリッドアクティベーション](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/activations.html)

[ハイブリッド環境で AWS Systems Manager を設定する](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-managedinstances.html)

[アクティベーションの有効期限について](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-managed-instance-activation.html)

## 各種IAMロールの設定
先述のとおり今回ECSタスク内からアクティベーションコードを発行する必要があるのでタスクに権限を付与する必要がある
また、ECSタスクからSystems MsnagerにIAMロールを渡す必要がある`iam:PassRole`が必要となる


[ハイブリッド環境に IAM サービスロールを作成する](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-service-role.html)

## アドバンスドインスタンスティアへの変更
Session Managerで自前のインスタンスに接続するためには、アドバンスドインスタンスティアに変更する必要がある

> アドバンストインスタンスは、AWS Systems Manager Session Manager を使用してハイブリッドマシンに接続することも可能にします。

注意点として、Session ManagerでBastionホストに接続する際、従量制で課金が発生する

## Session Managerのセッションタイムアウト
Session Managerでは一定時間操作していないとタイムアウトされる
これは20分で固定されておりチューニングすることができない

# 実装手順
## ベースイメージ
Fargateで実行させるコンテナのベースイメージには`Amazon Linux2`を用います。
Dockerfileは以下のとおり

```docker
FROM amazonlinux:2

# yum update & iinstall
RUN yum update -y \
  && yum install -y which sudo jq tar unzip

# install aws cli v2
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
  && unzip awscliv2.zip \
  && sudo ./aws/install

# install aws-ssm-agent
RUN sudo yum install -y https://s3.ap-north-east-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm

# craete ssm-user
# -M => --no-create-home
RUN useradd ssm-user -M -u 1111 && echo "ssm-user ALL = (ALL) NOPASSWD:ALL"

COPY run.sh /run.sh

# create user
RUN useradd "ssm-user" && echo "ec2-user ALL=NOPASSWD: ALL" >> /etc/sudoers.d/ssm-user

# init
CMD ["bash", "run.sh"]
```


## タスク起動時スクリプト

```shell
#!/bin/sh

# PReparation
SSM_SERVICE_ROLE_NAME=
SSM_ACTIVATION_FILE="ssm.json"
AWS_REGION="ap-northeast-1"

# Create Activation Code on Systems Manager
aws ssm create-activation \
--description "Activation Code for Fargate Bastion" \
--default-instance-name bastion \
--iam-role ${SSM_SERVICE_ROLE_NAME} \
--registration-limit  1 \
--tags Key=Type,Value=Bastion \
--region ${AWS_REGION} | tee ${SSM_ACTIVATION_FILE}

SSM_ACTIVATION_ID=`cat ${SSM_ACTIVATION_FILE} | jq -r .ActivationId`
SSM_ACTIVATION_CODE=`cat ${SSM_ACTIVATION_FILE} | jq -r .ActivationCode`
rm -f ${SSM_ACTIVATION_FILE}

# Activate SSM Agent on Fargate Task
amazon-ssm-agent -register -code "${SSM_ACTIVATION_CODE}" -id "${SSM_ACTIVATION_ID}" -region "${AWS_REGION}"

# Delete Activation Code
aws ssm delete-activation --activation-id ${SSM_ACTIVATION_ID}

# Execute SSM Agent
amazon-ssm-agent
```

`jq`: json grepの略？jsonをいい感じにgrepしてくれる
`tee`: 標準出力と指定したファイルにマルチ出力してくれる

# 参考
- セッションマネージャー越しにSSHアクセスすると何が嬉しいのか
https://dev.classmethod.jp/articles/ssh-through-session-manager/
- 「Bastion ~ AWS Fargateで実現するサーバーレスな踏み台設計」
https://iselegant.hatenablog.com/entry/2020/09/28/012409
- AWS Black Belt Online Seminar AWS Systems Manager
https://d1.awsstatic.com/webinars/jp/pdf/services/20200212_AWSBlackBelt_SystemsManager_0214.pdf
- [ハイブリッド環境で AWS Systems Manager を設定する](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-managedinstances.html)
- AWS Systems Manager の料金
  https://aws.amazon.com/jp/systems-manager/pricing/