AR ホームベーカリー

オイラのアウトプット用ホームベーカリー!

ECS exec が動くかチェックする

RDS をメンテしようと思い立つも、 ECS exec でポートフォワードできない。

❯ aws ssm start-session \
--target ecs:stg-tf-example-ecs-cluster_00001111222233334444555566667777_00001111222233334444555566667777-99998888 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["example.example.ap-northeast-1.rds.amazonaws.com"],"portNumber":["3306"], "localPortNumber":["13306"]}' \
--profile stg-example

An error occurred (TargetNotConnected) when calling the StartSession operation: ecs:stg-tf-example-ecs-cluster_00001111222233334444555566667777_00001111222233334444555566667777-99998888 is not connected.

ファッキン! ということでデバッグ方法を調べた所、公式に以下のようなページが。

aws.amazon.com

AWS くんの公式ドキュメントめちゃくちゃ目が滑るんだよな」とずっと考えていたのだけど、日本語ドキュメントで <p> 的なアプローチをするのが良くないんだな、と最近思い始めている。

<br> で改行するタイプの言語だよ。

それはさておき、結局権限が不足しているという話一点張りなので、どうやって調べろってのよまさか IAM 片っ端から見ろってのか! と思っていたら、本文中に以下へのリンクが出ている。

github.com

試す

ということで、 git clone したのちに試した結果がこれ。

export AWS_PROFILE=stg-example; ./check-ecs-exec.sh stg-tf-example-ecs-cluster 00001111222233334444555566667777
-------------------------------------------------------------
Prerequisites for check-ecs-exec.sh v0.7
-------------------------------------------------------------
  jq      | OK (/opt/homebrew/bin/jq)
  AWS CLI | OK (/opt/homebrew/bin/aws)

-------------------------------------------------------------
Prerequisites for the AWS CLI to use ECS Exec
-------------------------------------------------------------
  AWS CLI Version        | OK (aws-cli/2.9.9 Python/3.11.0 Darwin/22.2.0 source/arm64 prompt/off)
  Session Manager Plugin | OK (1.2.398.0)

-------------------------------------------------------------
Checks on ECS task and other resources
-------------------------------------------------------------
Region : ap-northeast-1
Cluster: stg-tf-example-ecs-cluster
Task   : 00001111222233334444555566667777
-------------------------------------------------------------
  Cluster Configuration  | Audit Logging Not Configured
  Can I ExecuteCommand?  | arn:aws:iam::000011112222:user/donbulinux
     ecs:ExecuteCommand: allowed
     ssm:StartSession denied?: allowed
  Task Status            | RUNNING
  Launch Type            | Fargate
  Platform Version       | 1.4.0
  Exec Enabled for Task  | OK
  Container-Level Checks |
    ----------
      Managed Agent Status
    ----------
         1. RUNNING for "nginx"
         2. RUNNING for "sidekiq"
         3. RUNNING for "app"
    ----------
      Init Process Enabled (stg-tf-example-ecs-task-definition-backend:4)
    ----------
         4. Disabled - "nginx"
         5. Disabled - "app"
         6. Disabled - "sidekiq"
    ----------
      Read-Only Root Filesystem (stg-tf-example-ecs-task-definition-backend:4)
    ----------
         7. Disabled - "nginx"
         8. Disabled - "app"
         9. Disabled - "sidekiq"
  Task Role Permissions  | arn:aws:iam::000011112222:role/ecs_task_execution_role
     ssmmessages:CreateControlChannel: disabled
     ssmmessages:CreateDataChannel: disabled
     ssmmessages:OpenControlChannel: disabled
     ssmmessages:OpenDataChannel: disabled
  VPC Endpoints          | SKIPPED (vpc-09876543210987654 - No additional VPC endpoints required)
  Environment Variables  | (stg-tf-example-ecs-task-definition-backend:4)
       1. container "nginx"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: not defined
       - AWS_SECRET_ACCESS_KEY: not defined
       2. container "app"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: defined
       - AWS_SECRET_ACCESS_KEY: defined
       3. container "sidekiq"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: defined
       - AWS_SECRET_ACCESS_KEY: defined

ssmmessages が無効化されとるやんけ! ということでマネジメントコンソールから IAM たどっていくと、たしかに ECS タスク定義にくっつけたロールの中身から欠落していた。

直接の原因は過去に書いた以下だった。

donbulinux.hatenablog.jp

修正して再実行

というわけで、上記 ssmmessages を再度付与して新しいタスク定義作成してローリングアップデート、 check-ecs-exec.sh 再実行した結果がこう。

export AWS_PROFILE=stg-example; ./check-ecs-exec.sh stg-tf-example-ecs-cluster 00001111222233334444555566667777
-------------------------------------------------------------
Prerequisites for check-ecs-exec.sh v0.7
-------------------------------------------------------------
  jq      | OK (/opt/homebrew/bin/jq)
  AWS CLI | OK (/opt/homebrew/bin/aws)

-------------------------------------------------------------
Prerequisites for the AWS CLI to use ECS Exec
-------------------------------------------------------------
  AWS CLI Version        | OK (aws-cli/2.9.9 Python/3.11.0 Darwin/22.2.0 source/arm64 prompt/off)
  Session Manager Plugin | OK (1.2.398.0)

-------------------------------------------------------------
Checks on ECS task and other resources
-------------------------------------------------------------
Region : ap-northeast-1
Cluster: stg-tf-example-ecs-cluster
Task   : 00001111222233334444555566667777
-------------------------------------------------------------
  Cluster Configuration  | Audit Logging Not Configured
  Can I ExecuteCommand?  | arn:aws:iam::000011112222:user/donbulinux
     ecs:ExecuteCommand: allowed
     ssm:StartSession denied?: allowed
  Task Status            | RUNNING
  Launch Type            | Fargate
  Platform Version       | 1.4.0
  Exec Enabled for Task  | OK
  Container-Level Checks |
    ----------
      Managed Agent Status
    ----------
         1. RUNNING for "nginx"
         2. RUNNING for "sidekiq"
         3. RUNNING for "app"
    ----------
      Init Process Enabled (stg-tf-example-ecs-task-definition-backend:4)
    ----------
         4. Disabled - "nginx"
         5. Disabled - "app"
         6. Disabled - "sidekiq"
    ----------
      Read-Only Root Filesystem (stg-tf-example-ecs-task-definition-backend:4)
    ----------
         7. Disabled - "nginx"
         8. Disabled - "app"
         9. Disabled - "sidekiq"
  Task Role Permissions  | arn:aws:iam::000011112222:role/ecs_task_execution_role
     ssmmessages:CreateControlChannel: allowed
     ssmmessages:CreateDataChannel: allowed
     ssmmessages:OpenControlChannel: allowed
     ssmmessages:OpenDataChannel: allowed
  VPC Endpoints          | SKIPPED (vpc-09876543210987654 - No additional VPC endpoints required)
  Environment Variables  | (stg-tf-example-ecs-task-definition-backend:4)
       1. container "nginx"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: not defined
       - AWS_SECRET_ACCESS_KEY: not defined
       2. container "app"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: defined
       - AWS_SECRET_ACCESS_KEY: defined
       3. container "sidekiq"
       - AWS_ACCESS_KEY: not defined
       - AWS_ACCESS_KEY_ID: defined
       - AWS_SECRET_ACCESS_KEY: defined

無事 allowed になり、このあと ECS exec の利用もできるようになりましたとさ。

ということで、 ECS exec を利用できない時は公式が提供している、こちらのシェルスクリプトでチェックするようにしてみましょう。

default 以外のプロファイルを指定する

実行時に export環境変数からプロファイル名を与える以外は対応していないようです。 README にもそのようにやれと書いてあるので。

僕は複数行にするのが面倒なので、以下のようにワンライナーにしています。

export AWS_PROFILE=${プロファイル名}; ./check-ecs-exec.sh ${クラスタ名} ${タスクID}

disabled 全部潰したのに接続できない時

僕は本番向け prod- と検証向け stg- という prefix を利用しているのですが、接続文言をコピペで使いまわしており、以下のようなミスが原因でした。

# 検証に接続したい
❯ aws ssm start-session \
--target ecs:stg-tf-example-ecs-cluster_00001111222233334444555566667777_00001111222233334444555566667777-99998888 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["example.example.ap-northeast-1.rds.amazonaws.com"],"portNumber":["3306"], "localPortNumber":["13306"]}' \
--profile stg-example

# 本番に接続した
❯ aws ssm start-session \
--target ecs:stg-tf-example-ecs-cluster_00001111222233334444555566667777_00001111222233334444555566667777-99998888 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["example.example.ap-northeast-1.rds.amazonaws.com"],"portNumber":["3306"], "localPortNumber":["13306"]}' \
--profile prod-example

実際にミスったヤツです、目が滑りますね。 原因は ECS クラスタ名の指定の変更が間違っています。

検証は合っているけど、本番もコピペしたのち --profile の指定をかえただけで接続できずキレていました。 このあたり AWS 側の例外メッセージも不親切だったりするのですが、一番良いのはコマンドで済ませるより対話型 CLI などで選択する、という方がよさそうです。

探したら作っている人はいるのだった。

engineer.ashita-team.com

こちらもあるじゃん!と思っていたら EC2 対象でした……。

khasegawa.hatenablog.com