KAKEHASHI Tech Blog

カケハシのEngineer Teamによるブログです。

AWSのSession ManagerとFargateを用いた踏み台サーバー構築のTips

こんにちは。カケハシの Musubi AI在庫管理 チームで業務委託のエンジニアとして開発を行っております山田です。こちらの記事は カケハシ Advent Calendar 2021 の17日目の記事になります。

本記事では、AWS Systems Manager Session ManagerとAWS FargateでプライベートネットワークのRDSにアクセスするための踏み台サーバーを構築した際に、AI在庫チームが遭遇した問題の解決策や便利な設定をTipsとして紹介します。

上記技術スタックの選択を行うそもそものメリットや、実際の構築手順等の基本的な部分の情報に関してはネット上に多くの記事が存在するため、本投稿では導入当初参考にさせて頂いた記事を紹介するのみとします。

我々の構成も上記で紹介されているものと大きくは変わらず、各開発者が踏み台を使用する際Fargate cluster内にECSタスクを起動し、タスク内部でアクティベーションコードの発行やSession Managerのインスタンス登録が完了次第、AWS CLI等からサーバーに接続するようなフローとなっています。

Tip 1: 操作ログでassume role元のユーザを特定できるようにする

Session Managerの設定画面からCloudWatch Loggingを有効にすることで、踏み台サーバの操作ログをCloudWatchに残すことができます。以下はあるユーザが踏み台ログイン後に echo "hi" を実行したときのログエントリの例です。 eventTime, userIdentity, sessionData の項目に「いつ」「誰が」「何のコマンドを発行したか」の情報が記録されていることが確認できます。

{
    "eventVersion": "1.0",
    "eventTime": "2021-12-17T00:00:00Z",
    "awsRegion": "ap-northeast-1",
    "target": {
        "id": "..."
    },
    "userIdentity": {
        "arn": "<ログインユーザのARN>"
    },
    "runAsUser": "ssm-user",
    "sessionId": "<ログインユーザ名>-xxxxxxxxxxxxxxxxx",
    "sessionData": [
        "$ echo \"hi\"",
        "hi"
    ]
}

さて、僕らのチームでは開発メンバーがAWSリソースを操作する際には開発者用の特定のIAM Roleにassume roleした上で行う運用をしています。ただ、assume role経由でAWS CLIから踏み台サーバに接続した場合、操作ログの userIdentity の項目にはassumeされたrole名とrole session名のみが記載され、具体的に「誰が」操作を行ったのかの情報が不明瞭になってしまいます。

{
    "eventVersion": "1.0",
    "eventTime": "2021-12-17T00:00:01Z",
    "awsRegion": "ap-northeast-1",
    "target": {
        "id": "..."
    },
    "userIdentity": {
        "arn": "arn:aws:sts::<account id>:assumed-role/<role name>/<role session name>"
    },
    "runAsUser": "ssm-user",
    "sessionId": "<role session name>-xxxxxxxxxxxxxxxxx",
    "sessionData": [
        "$ echo \"hi\"",
        "hi"
    ]
}

AI在庫チームでは、各メンバーが開発者用のロールにassume roleする際のrole session nameに自身のユーザ名の設定を強制することでこの問題を解決しました。具体的には、assume roleされるIAM Roleの信頼ポリシーにCondition句として以下の設定を追加しました。role session nameに自身のユーザ名以外の文字列を指定した状態でこのロールにassume roleすると、エラーで失敗するようになります。

"Condition": {
  "StringLike": {
    "sts:RoleSessionName": "${aws:username}"
  }
}

参考: [アップデート] IAMロールセッション名にユーザー名を強制できる条件 sts:RoleSessionName が使えるようになりました

これにより、接続元IAMエンティティの形態に関わらずユーザのidentityがログに記録され、我々のようなassume roleを前提とした環境でも漏れなく操作ユーザの特定が行えるようになりました。

※ switch roleした状態でAWS Management ConsoleからSession Manager経由の接続をするケースでは上記の設定をしなくても元のユーザのidentityがログに表示されるようでした。

Tip 2: 踏み台サーバーが常時起動したままになることを防ぐ

Session Manager経由で動作する踏み台サーバを導入することで一定のセキュリティが担保できましたが、更なるセキュリティの向上とまたAWSのコスト削減のために、踏み台サーバーは開発者が作業を行う間のみ起動し作業終了後にはサーバーが停止するような状態を作ることが望ましいと考えました。ただ、「踏み台使用後は必ず開発者自身でサーバを停止するように心がけましょう」をREADMEに追加するような対応だと停止のし忘れが発生する可能性が否めず、辛いです。 そこでAI在庫チームでは、サーバ起動後に特定の時間が経過すると自動的にサーバが停止する仕組みを導入することによりこの問題を解決しました。実現方法は単純でECSタスク内のSSMエージェント起動処理をbackgroundで行い、その後起動時間分のsleep処理を挟むだけです。

e.g.

# entrypoint.sh

#
# ...踏み台に必要な処理
#

amazon-ssm-agent start &

sleep $DURATIOIN

exit 0

$DURATIONはデフォルトで1時間とし、それ以上作業が長引きそうなときは踏み台を起動するコマンドのオプションで必要に応じて起動時間を指定するような実装にしています。これにより開発者が作業後に都度サーバーを停止する手間が無くなり、また停止忘れによる起動しっぱなしのサーバーが出てくる心配も無くなりました。

まとめ

AWS Systems Manger Session Managerと、AWS Fargateを用いて踏み台サーバ構築を行う際のTipsを2つ紹介しました。 AI在庫チームで踏み台サーバを導入してから本記事執筆時点まで約6ヶ月ほどが経過していますが、今の所特に大きな不便や障害もなく運用できているかと思います。 本記事の内容が皆様の参考になれば幸いです。

最後まで読んでいただきありがとうございました。