EC2からECS Execを実行

## 始めに
`ECS Exec`の環境構築記事は多数ありますが、
それを実行する環境を構築する記事が見当たらなかったので

`AWS CLI`を使うケースが多いかと思いますが、
ローカル環境などで実行するとセキュリティ的に怖いので、
踏み台の先の操作用サーバー(EC2)などに構築するケースが多いかと思います

今回はこのパターンの操作用サーバー(EC2)から`ECS Exec`を実行するために必要なことを記載していきます

## 前提 (この記事で説明しないこと)
- EC2のインスタンスの立ち上げ
- ECS Exec自体の環境構築

## 詳細
### AWS CLIの設定
#### PIPのインストール

```
sudo yum install pip
```

#### 最新版のAWS CLIのインストール

##### Ver1のアンインストール

```
sudo pip uninstall awsclihttps://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-linux.html#install-linux-pip
```

##### Ver2のインストール

```
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
```

##### AWS CLIの設定

```
aws configure
> AWS Access Key ID [None]: # <- 未指定でOK
> AWS Secret Access Key [None]: # <- 未指定でOK
> Default region name [None]: ap-northeast-1 # <- 任意のregionを指定
> Default output format [None]: json <- お好きなformatを指定
```

### AWS Session Managerのインストール

```
curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm" -o "session-manager-plugin.rpm"
sudo yum install -y session-manager-plugin.rpm
```

### (AWS IAM) 権限の付与

#### ポリシーの作成

名前は任意で

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iam:SimulatePrincipalPolicy"
            ],
            "Resource": [
                "arn:aws:iam::{account_id}:role/{operation_role}",
                "arn:aws:iam::{account_id}:role/{ecs_task_role}"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "ecs:ExecuteCommand",
                "ecs:DescribeTasks",
                "ecs:DescribeClusters"
            ],
            "Resource": [
                "arn:aws:ecs:{region}:{account_id}:task/*",
                "arn:aws:ecs:{region}:{account_id}:cluster/{ecs_cluster_name}"
            ]
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "iam:ListRoles",
                "ecs:DescribeTaskDefinition",
                "ecs:ListTasks"
            ],
            "Resource": "*"
        }
    ]
}
```

##### 注釈
- {operation_role} -> 後述のロールの名前を指定
- {ecs_task_role} -> ECSのタスクロールのロール名を指定
- ecs:ListTasks -> 後述の接続コードのshで必要な部分。利用しない場合は削って良い


#### ロールの作成

名前は任意
上記のポリシーの`operation_role`と合わせる
また、上記ポリシーをアタッチする

#### EC2へのロールのアタッチ

上記ロールをEC2インスタンスにアタッチする
参考: https://aws.amazon.com/jp/blogs/news/easily-replace-or-attach-an-iam-role-to-an-existing-ec2-instance-by-using-the-ec2-console/

### 接続確認
```
aws ecs execute-command \
    --cluster {cluster_name} \
    --task {task_id} \
    --container {container_id} \
    --interactive \
    --command /bin/sh

> The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.

> Starting session with SessionId: ecs-execute-command-xxxxxxxxxxxxxxxx

> / # <= ここからContainer内
```

## 補足

### 接続できない場合

ECS Exec Checkerを利用して接続確認すると便利
https://github.com/aws-containers/amazon-ecs-exec-checker

### 接続コードのsh
task_idを毎回調べるのは面倒なので、動的に取得するshを作成して利用しています

```
#!/bin/sh
# Amazon ECS ExecでECSコンテナに接続する
function usage() {
    echo
    echo "usage: ecs_exec.sh [-h] [cmd]"
    echo
    echo "options:"
    echo "  -h, --help    このメッセージを表示"
    echo
    echo "arguments:"
    echo "  cmd   実行したいコマンド。デフォルトは'/bin/sh'"
}

args=()
for option in "$@"; do
  case "${option}" in
    '-h' | '--help')
  usage
  exit 1
    ;;
  esac
done

ecs_task_id=`aws ecs list-tasks --cluster {cluster_name} | jq -r '.taskArns[0] | split("/") | .[2]'`

cmd="${1:-/bin/sh}"

aws ecs execute-command \
    --cluster {cluster_name} \
    --task "${ecs_task_id}" \
    --container {container_name} \
    --interactive \
    --command "${cmd}"
```