Session Manager Plugin

ローカル端末などから足場サーバー等を経由せずに、Session Manager Pluginを利用してインスタンスへsshの様にログインする

検証環境はWindows のWSL2(Ubuntu 22.04)

AWS CLIのインストール

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

role/policy

AmazonSSMManagedInstanceCore という名前のロールを作成し、同じ名前のポリシーを許可に追加する

EC2のセキュリティからIAMロールを変更する

Session Manager Pluginのインストール

ocarina@localhost:~/work/aws$  curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3598k  100 3598k    0     0  1271k      0  0:00:02  0:00:02 --:--:-- 1271k

ocarina@localhost:~/work/aws$ sudo dpkg -i session-manager-plugin.deb
以前に未選択のパッケージ session-manager-plugin を選択しています。
(データベースを読み込んでいます ... 現在 54928 個のファイルとディレクトリがインストールされています。)
session-manager-plugin.deb を展開する準備をしています ...
Preparing for install
session-manager-plugin (1.2.553.0-1) を展開しています...
session-manager-plugin (1.2.553.0-1) を設定しています ...
Creating symbolic link for session-manager-plugin
ocarina@localhost:~/work/aws$ session-manager-plugin

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

EC2インスタンスに接続する

aws ssm start-session --target インスタンスID --profile プロファイル名

ocarina@localhost:~/work/aws$ aws ssm start-session --target i-xxxxxxxxxxxxxxx --profile default
sh-4.2$
sh-4.2$ sudo -s

fargateのコンテナへ接続

フリートマネージャについて

「スタンダード階層からアドバンスト階層への変更」
が必要な記事がありましたが不要でした。

ssm-agentを有効にしたコンテナを作成する

mkdir files
mkdir files/etc
vi Dockerfile

Dockerfile

FROM public.ecr.aws/amazonlinux/amazonlinux:2023 as build

RUN dnf -y install https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm
#RUN dnf -y install httpd
RUN dnf -y install python3 python3-pip
RUN pip install supervisor

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

# ssm-user アカウントの sudo アクセス許可設定
RUN dnf -y install shadow-utils
ARG USERNAME=ssm-user
ARG GROUPNAME=ssm-user
ARG UID=1000
ARG GID=1000
#ARG PASSWORD=ssm-user
RUN groupadd -g $GID $GROUPNAME && \
    useradd -m -s /bin/bash -u $UID -g $GID $USERNAME && \
    echo $USERNAME:$PASSWORD | chpasswd && \
    echo "$USERNAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

# conf
ADD files/etc/supervisord.conf /etc/
ADD files/ssm-entrypoint.sh /usr/local/bin/

ENV TZ Asia/Tokyo

ENTRYPOINT ["/usr/local/bin/supervisord"]

supervisordにてssm-agentが起動できるようにしておく

docker exec -it amazonlinux2023-custom echo_supervisord_conf > files/etc/supervisord.conf
vi files/etc/supervisord.conf
[unix_http_server]
file=/tmp/supervisor.sock   ; the path to the socket file

[supervisord]
logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log
logfile_maxbytes=50MB        ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10           ; # of main logfile backups; 0 means none, default 10
loglevel=info                ; log level; default info; others: debug,warn,trace
pidfile=/tmp/supervisord.pid ; supervisord pidfile; default supervisord.pid
nodaemon=true               ; start in foreground if true; default false
silent=false                 ; no logs to stdout if true; default false
minfds=1024                  ; min. avail startup file descriptors; default 1024
minprocs=200                 ; min. avail process descriptors;default 200

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

;[program:httpd]
;command=/usr/sbin/httpd -DFOREGROUND
;stdout_logfile=/dev/stdout
;stdout_logfile_maxbytes=0
;stderr_logfile=/dev/stderr
;stderr_logfile_maxbytes=0
;autostart=true
;autorestart=true

[program:amazon-ssm-agent]
command=/usr/local/bin/ssm-entrypoint.sh
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
autostart=true
autorestart=true

Fargateのコンテナのssm利用の為のアクティベーションコードを取得するスクリプト

参考

vi files/ssm-entrypoint.sh
#!/bin/bash
set -e

# 自身のマネージドインスタンス ID が記載されているファイルの指定 (↓のパス固定で OK )
export REGISTRATION_FILE="/var/lib/amazon/ssm/registration"
cleanup() {
    # コンテナ終了時、マネージドインスタンス登録を解除
    echo "--- deregister managed instance"
    aws ssm deregister-managed-instance --instance-id "$(cat "${REGISTRATION_FILE}" | jq -r .ManagedInstanceID)" || true
    exit 0
}
trap "cleanup" EXIT  # コンテナ停止をトリガーに cleanup 関数を実行

# アクティベーションの作成
echo "--- create SSM activation"
ACTIVATION_PARAMETERS=$(aws ssm create-activation \
    --default-instance-name "ecs-task" \
    --description "ecs-task" \
    --iam-role "IAMRoleForSSM" \
    --region "ap-northeast-1")

# アクティベーションの作成結果からアクティベーションコード/ ID を抽出
export ACTIVATION_CODE=$(echo $ACTIVATION_PARAMETERS | jq -r .ActivationCode)
export ACTIVATION_ID=$(echo $ACTIVATION_PARAMETERS | jq -r .ActivationId)

# アクティベーションコード/ ID を利用してマネージドインスタンスを登録
echo "--- register SSM instance"
sudo amazon-ssm-agent -register -code "${ACTIVATION_CODE}" -id "${ACTIVATION_ID}" -region "ap-northeast-1" -y

# ハイブリッドアクティベーションのコードはもう必要ないため削除
echo "--- delete SSM activation"
aws ssm delete-activation --activation-id "${ACTIVATION_ID}"

# SSMエージェントの登録
echo "--- start SSM agent"
nohup sudo amazon-ssm-agent
chmod +x files/ssm-entrypoint.sh

build

ocarina@localhost:~/work/ecs/ecs-test$ docker build -t ecs-test:0.0.0 ./

test

ocarina@localhost:~/work/ecs/ecs-test$ docker run --rm --name test20242424-02 -i -t ecs-test:0.0.0

create ecr repository

プライベートレポジトリを作成

login ecr & tag & push

ocarina@localhost:~/work/ecs/ecs-test$ aws --profile=default ecr get-login-password | docker login --username AWS --password-stdin 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com
WARNING! Your password will be stored unencrypted in /home/ocarina/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

ocarina@localhost:~/work/ecs/ecs-test$ docker tag ecs-test:0.0.0 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-test:0.0.0
ocarina@localhost:~/work/ecs/ecs-test$ docker push 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/ecs-test:0.0.0

create ECS from cloudformation

IAM

ロール、AWSCloudFormationStackSetAdministrationRole へ以下のポリシーを付与しておく

  • AdministratorAccess

create VPC

今回は既存のVPC(public subnet * 2が最低必須)に作ることにします。

creat ECS fargate cluster

  • 今回はALB無しで作成します。
  • VPCのpublicsubnetを指定する
  • fargateコンテナで利用するECRのイメージを指定する

ローカル端末にてECSExecの有効化

aws ecs update-service --region ap-northeast-1 --cluster クラスター名 --service サービス名 --enable-execute-command

SSMを利用しコンテナに接続する

aws ecs execute-command --region ap-northeast-1 --cluster クラスター名 --task タスクID --container コンテナ名 --interactive --command "/bin/sh"
vi ~/bin/ecsssm.sh
profile=default
# 複数ある場合は適宜変更する
#cl=$(aws --profile=$profile ecs list-clusters | jq -r '.clusterArns[0]' )
cl=$(aws --profile=$profile ecs list-clusters | jq -r '.clusterArns[1]' )
prefix=`echo ${cl} | sed -E 's/.+cluster\///g' `
taskarn=$(aws ecs list-tasks --cluster ${cl} | jq -r '.taskArns[0]')
taskid=`echo ${taskarn} | sed -E 's/.+task\/.+\///g' `
# コンテナ名も適宜変更する
CONTAINER_NAME=ecstask

echo ${cl};     \
echo ${prefix} ; \
echo ${taskarn}; \
echo ${taskid};  \
echo ${CONTAINER_NAME};  \

aws ecs execute-command  \
 --region    ap-northeast-1 \
 --cluster   ${cl} \
 --task      ${taskarn} \
 --container ${CONTAINER_NAME}\
 --command "/bin/sh" \
 --interactive

起動に失敗


ocarina@localhost:~/work/ecs/ecs-test$ bash -x ~/bin/ecsssm.sh

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

An error occurred (InvalidParameterException) when calling the ExecuteCommand operation: The execute command failed because execute command was not enabled when the task was run or the execute command agent isn’t running. Wait and try again or run a new task with execute command enabled and try again.

check

ocarina@localhost:~/work/ecs/ecs-test$ aws ecs describe-tasks --region ap-northeast-1 --cluster arn:aws:ecs:ap-northeast-1:1234567890:cluster/ecscluster-test --task arn:aws:ecs:ap-northeast-1:1234567890:task/ecscluster-test/3babf98aa0d9446fbfa7c79f340a2933 | grep enableExecuteCommand
            "enableExecuteCommand": false,

enableExecuteCommandをtrueへ更新

ocarina@localhost:~/work/ecs/ecs-test$ aws ecs update-service --region ap-northeast-1 --cluster arn:aws:ecs:ap-northeast-1:1234567890:cluster/ecscluster-test --service ecsservice-test --enable-execute-command

サービスの再起動

ecs > タスク定義 > ecstask > サービスを更新

再実行でcrash

https://repost.aws/ja/knowledge-center/systems-manager-crash-reasons


ocarina@localhost:~/work/ecs/ecs-test$ bash -x ~/bin/ecsssm.sh

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

Starting session with SessionId: ecs-execute-command-xxxxxxx

SessionId: ecs-execute-command-xxxxxxx : document process failed unexpectedly: document worker timed out , check [ssm-document-worker]/[ssm-session-worker] log for crash reason

ocarina@localhost:~/work/ecs/ecs-test$
  • Dockerfileでbuildし直してエラーが出ていないか確認
    • 今回はuseraddコマンドが無くてssm-user が作成されていなかった

OK

ocarina@localhost:~/work/ecs/ecs-test$ bash -x ~/bin/ecsssm.sh

+ aws ecs execute-command --region ap-northeast-1 --cluster arn:aws:ecs:ap-northeast-1:1234567890:cluster/ecscluster-test --task arn:aws:ecs:ap-northeast-1:1234567890:task/ecscluster-test/xxxxxxx --container ecstask --command /bin/sh --interactive

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

Starting session with SessionId: ecs-execute-command-057fc4be6beae5753
sh-5.2# cat /etc/issue
\S
Kernel \r on an \m (\l)

sh-5.2# uname -n
ip-10-0-1-202.ap-northeast-1.compute.internal
sh-5.2# uname -r
5.10.213-201.855.amzn2.x86_64
sh-5.2#
sh-5.2# id
uid=0(root) gid=0(root) groups=0(root)
sh-5.2# pwd
/
sh-5.2#

Posted by ocarina