🌐

AWS Systems ManagerのSession Managerで安全にEC2インスタンスに接続する

2024/12/27に公開

https://adventar.org/calendars/10481

はじめに

こんにちは。@PEmugiです。普段はGO株式会社で地図周りのデータエンジニアをしています。好きなAWSサービスはAWS CDK。
今日は普段AWSを使っていて便利だなと思うSession Managerについて紹介したいと思います。

最近はあまりEC2インスタンスを立てて直接ログインして作業することは少なくなってきましたが、それでも以下のような用途でログインして調査、開発することがあります。

  • AWS BatchやECSで構築されたサービスのECSクラスターを構成するインスタンス上での調査・デバッグ
  • テンポラリで起動した作業用インスタンスへのログイン
  • GPUインスタンスで機械学習モデルの学習・開発
  • RDSやその他インスタンスへ接続するための踏み台サーバーへのログイン

以前はこのようなケースで、SSHで直接もしくは踏み台サーバーを経由してログインしていましたが、以下のような課題・問題がよく発生します。

  • SSHの秘密鍵の扱いで困ることが多い
    • インスタンス作成するたびにキーペアを新規作成し管理できなくなる
    • 秘密鍵をだれが持っているのかわからずドラクエしなければならない
    • Slackでライトにぺたぺた秘密鍵貼りだす人がでる
    • 秘密鍵がなんか無い
    • メンバーの増減で鍵の登録・削除が必要
  • Security GroupでSSHを許可しなければならない
    • 拠点の変更や増加のたびに接続ソースの管理が必要
    • 設定ミスのリスクがでかい
    • 常に22番がインターネットに向けてオープンされていると思うと夜しか眠れない

こういった課題・問題を解決するために、個人開発では最近AWS Systems Manager Session Managerを使用しています。

AWS Systems Manager Session Managerとは

AWS Systems Manager Session Managerは、EC2インスタンスにマネージメントコンソールやAWS CLIからセッションを開始し、インスタンスにログインできるサービスです。セッションを開始する際にSSHキーやポートの設定が不要で、安全な通信が行えるため、セキュリティを強化しながら管理作業を効率化できます。(powered by ChatGPT)
また、他のAWSサービスと同様に権限管理をIAMで行えるのも魅力です。

Session Managerの準備

Session ManagerをAWS CLIから使用するための準備をします。

インスタンスの準備

Session Managerで接続可能なインスタンスの条件は以下です。

  1. System Manager Agentがインストールされている
  2. System Managerに関するポリシーが適切にインスタンスのロールに設定されている
  3. System Managerと通信できる

1. System Manager Agentがインストールされている

インスタンスとAWS System ManagerのAPIとのやりとりをSystem Manager Agent(SSM Agent)で行うので、SSM Agentが動作している必要があります。
Amazon Linux 2やAmazon Linux 2023などの公式のAMIであればプリインストールされています。
インストールされていないAMIを使う場合は自分でインストールする必要があります。詳しいセットアップについては公式ドキュメントをご覧ください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ssm-agent.html

2. System Managerに関するポリシーが適切にインスタンスのロールに設定されている

細かくポリシーを定義してもいいですが、管理ポリシー「AmazonSSMManagedInstanceCore」が付与されているロールをインスタンスに設定するのが簡単です。
AWS Batchのコンピューティング環境やECSのクラスターにおいてもインスタンスロールに「AmazonSSMManagedInstanceCore」を設定すれば、AutoScaling Groupによって起動されるインスタンスに付与されます。

3. System Managerのエンドポイントと通信できる

System Managerの以下エンドポイントと通信をするため、パブリックなIPを持つかプライベートサブネット内であればNATゲートウェイ経由でインターネットに出られる必要があります。
Security Groupではアウトバウンドのみ許可されていればOKです。インバウンドは何も空ける必要がないので安心ですね。

  • ec2messages.{region}.amazonaws.com
  • ssm.{region}.amazonaws.com
  • ssmmessages.{region}.amazonaws.com

接続元クライアントの準備

接続元のクランアントではAWS CLIの準備と、IAMユーザに付与するポリシーの設定が必要です。

クライアントの準備

AWS CLIに加えてSession Managerプラグインのインストールが必要です。それぞれ公式の説明に従って導入しましょう。
AWS CLIについてはMacならbrewで入れるのが楽です。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-getting-started.html\nhttps://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html

IAMポリシーの設定

AWS CLIでシェルのセッションやポートフォワーディングのセッションを開始するには以下のようなポリシーを設定します。詳細は公式ドキュメントを参考に設定してみてください(公式に丸投げするスタイルを乱用)。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:ec2:us-east-2:123456789012:instance/i-1234567890EXAMPLE",
                "arn:aws:ssm:us-east-2:123456789012:document/SSM-*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:userid}-*"
            ]
        }
    ]
}

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/getting-started-restrict-access-examples.html

使ってみる

準備が長くなりましたが早速使っていきましょう。

CLIからログイン

まずは、AWS CLIからログインしてみます。

コマンド

aws ssm start-session --target i-0abcabsample

結果

とても簡単です。--targetはインスタンスのIDです。
インスタンスのリプレイスなどを考えるとSystemManagerのParameter StoreにIDを保存しておいてセッションスタートするシェルを書いておくと便利です。

ポートフォワーディング

VPCのプライベートサブネットに配置したRDSのデータベースに手元から接続したい場面、ありますよね?
こういった時にもSession Managerを利用できます。
--document-nameにポートフォワード用のSSMドキュメントAWS-StartPortForwardingSessionToRemoteHostを指定し、設定でリモートホスト、ポート、ローカルポートを指定するだけです。

RDSのpostgresqlデータベースにポートフォワードする例

aws ssm start-session \
    --target i-0abcabsample \
    --document-name AWS-StartPortForwardingSessionToRemoteHost \
    --parameters '{"host":["samplepgdb.cluster-sample.ap-northeast-1.rds.amazonaws.com"],"portNumber":["5432"], "localPortNumber":["5432"]}'

i-0abcabsampleは踏み台のEC2インスタンスです。もちろんSSHのインバウンドを許可する必要もありませんし、キーペアなしでも大丈夫です。
これでpsql -h localhsot -p 5432 -U postgres -d postgres等で接続できちゃいます。

Session Manager経由でSSHする

最後に、Session Manager経由でSSHする方法を紹介します。
Session Managerだけでシェルにログインできてポートフォワードもできるのであまり使う場面はないかもしれませんが、たとえばSFTPでEC2にファイルを転送したい場合などに便利です。S3経由でもいいですが面倒臭いですからね。
SSHする場合でもインスタンスのセキュリティグループのSSHのポートを解放する必要はありません。ただしSSHデーモンは動いている必要があります。

まず、~/.ssh/configに以下のような設定を追記します。
この例ではi-で始まるホスト(インスタンスID)に接続するときに、Session Manager経由でSSHすることを設定しています。

host i-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

あとは以下コマンドで接続できます。もちろんSFTPも可。

ssh -i /key/pair.pem ec2-user@i-abcabsample

ここで気付いたと思います。キーペアいるんじゃんと。
安心してください。EC2 Instance Connectで手元で作成したキーペアの公開鍵を一時的にEC2インスタンスに配置することができます。
(EC2 Instance ConnectでSSHできちゃうことはおいておこう)

キーペアの作成

ssh-keygen -t rsa -f my_key

キーペアの配置

aws ec2-instance-connect send-ssh-public-key \
    --region ap-northeast-1 \
    --availability-zone ap-northeast-1b \
    --instance-id i-abcabsample \
    --instance-os-user ec2-user \
    --ssh-public-key file://key/pair.pub

このコマンドで60秒間、インスタンス上で公開鍵が維持されますのでその間に接続します。

キーペアを一時的に作成してインスタンスに配置し、SSHコマンドを発行するようなシェルを用意しておくとインスタンス作成時にキーペアを作成せずとも一時的なキーペアで接続できるようになります。
接続の許可に関してはIAMで制御できるので、権限管理をすべてIAMに集約できます。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html#connect-linux-inst-eic-cli-ssh

まとめ

EC2インスタンスに接続する方法としてAWS System Manager Session Managerを使用する方法を紹介しました。
利点としてはSSHのポートを開けたり、sshdを起動せずに(SSH接続しない場合)、踏み台インスタンスやECS、AWS Batchのインスタンスにログインし作業・デバッグが可能になります。
また、接続の権限管理をIAMに集約することができ、SSHログインのみキーペアでユーザごとに権限を管理する必要がなくなります。

今年も仕事・プライベートでたくさんAWSを使いました。
来年も素晴らしいAWSライフを!

Discussion