AWS Systems ManagerのSession Managerで安全にEC2インスタンスに接続する
はじめに
こんにちは。@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で接続可能なインスタンスの条件は以下です。
- System Manager Agentがインストールされている
- System Managerに関するポリシーが適切にインスタンスのロールに設定されている
- 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を使う場合は自分でインストールする必要があります。詳しいセットアップについては公式ドキュメントをご覧ください。
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で入れるのが楽です。
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}-*"
]
}
]
}
使ってみる
準備が長くなりましたが早速使っていきましょう。
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に集約できます。
まとめ
EC2インスタンスに接続する方法としてAWS System Manager Session Managerを使用する方法を紹介しました。
利点としてはSSHのポートを開けたり、sshdを起動せずに(SSH接続しない場合)、踏み台インスタンスやECS、AWS Batchのインスタンスにログインし作業・デバッグが可能になります。
また、接続の権限管理をIAMに集約することができ、SSHログインのみキーペアでユーザごとに権限を管理する必要がなくなります。
今年も仕事・プライベートでたくさんAWSを使いました。
来年も素晴らしいAWSライフを!
Discussion