AWS-Systems-Manager

AWS Systems Manager セッションマネージャーを使って、SSH不要でEC2にシェルアクセスしてみた

こんにちは
冷房の効いた部屋でだらだらウクレレを弾いて過ごしているSRE課の栩野です。

AWS Systems Manager セッションマネージャーを使って、SSH不要でEC2にシェルアクセスしてみた

AWS Systems Manager(SSM)の機能について調べるている時に
Systems Managerのセッションマネージャーという機能を利用することで

SSHなしでEC2インスタンスにシェルアクセスできる
操作ログをS3やCloudWatch Logsに保存することができる

といった説明を見つけて、気になったので実際に使ってみたところ...

めちゃくちゃ良かったので、それを共有しようとセッションマネージャーの利用方法について今回は記事にしてみます。

AWS Systems Manager セッションマネージャーとは

そもそも、SSHを使わずにシェル操作???かつ操作ログを残せる???
セッションマネージャとは一体どんな仕組みなのか、不明点が多すぎたのでAWSのサービスページで確認したところ

Session Manager はフルマネージド型 AWS Systems Manager 機能であり、インタラクティブなワンクリックブラウザベースのシェルや
AWS CLI を介して、EC2 インスタンス、オンプレミスインスタンス、仮想マシン (VM) を管理できます。
Session Manager を使用すると、インバウンドポートを開いたり、踏み台ホストを維持したり、SSH キーを管理したりすることなく、
監査可能なインスタンスを安全に管理できます。

参考:AWS Systems Manager Session Manager

上記のような説明が記載されていました。
もっと簡単にまとめると...

  • フルマネージド型のSystems Managerの機能
  • ブラウザもしくはCLIでEC2インスタンスにシェルアクセスができる
  • SSH不要なので、SSHキーの管理やインバウンドポートの開放は不要で安全

これだけみてもSSHが不要でシェルアクセスできる仕組みがわからなかったので更に調べてみたところ

  • 対象サーバにSSMエージェントをインストールし稼働させる必要がある
  • SSMエージェントから、ネットワークもしくはエンドポイント経由でSystems Manager APIに対してポーリング処理を行う
  • これによりインバウンドポートは開放せず、エージェントを介してのシェル操作が可能

こういった動作と仕組みになっているようです。

そのためセッションマネージャを使うためには、インバウンドでのポート開放は不要ですが
インターネットに対してのアウトバンドの経路、もしくはSystems Managerのエンドポイントに対しての経路が必要になります。

実際に使ってみる

色々説明しても使ってみないとわからないので
実際にセッションマネージャーを利用できる環境を作成して、リモートからセッションマネージャーでシェルアクセスしてみようと思います。

今回は接続元としてMacOS、接続先としてCentOS7のイメージで作成したEC2インスタンスを利用して
シェルアクセスする環境を作成していきますので、適宜自分の環境に置き換えて確認ください。

  • 接続元環境:MacOS
  • 接続先環境:CentOS7のイメージで作成したEC2インスタンス

接続先環境となるEC2側での準備

シェルアクセス先となるEC2側でセッションマネージャを受け入れるための設定を行っていきます。

アクセス先となる環境は、SSMエージェントが稼働できる環境であればEC2でもオンプレのサーバでも設定可能です。

今回はCentOS7のイメージで作成したEC2インスタンス環境を前提に説明を進めていきます。

セキュリティグループの設定

上記でも説明した通り、SSMエージェントを介してSSMと通信を行うため
インターネットへのアウトバウンドの経路、もしくはSSMエンドポイントへの通信経路が必要になります。

今回はインターネット経由での接続を行うため、セキュリティグループはデフォルトでアウトバウンド
の通信は全て許可されているのでそのまま進めていきます。

またセッションマネージャーで接続できる環境が作成できれば、SSHのインバンウンドポートの開放は
不要ですが、今回はSSMエージェントのインストール作業が必要になるため開放しておきます。

▼インバウンドルール

▼アウトバウンドルール

SSMエージェントをインストールする

もしも対象サーバがAmazon Linux 2 の場合はデフォルトでSSMエージェントが
インストールされていますが、今回はCentOS7のイメージを利用しているので、エージェントの
インストールが必要になります。

CentOS7以外の環境の場合は、以下URLからインストール方法を確認お願いします。
参考:Linux 用の EC2 インスタンスに手動で SSM エージェント をインストールする

CentOS7へのSSMエージェントのインストールと設定方法は以下の通りです。

// サーバにSSHでログインし、yumコマンドでエージェントをインストールします。
// 現時点(2020/8/11)での最新バージョンは2.3.1569.0-1になっています。
# yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm

// インストール後は起動も、自動起動の設定も自動で設定されます。
// 念の為起動していることと、自動起動が有効になっていることを確認します。
# systemctl status amazon-ssm-agent

サーバにSSHログインしての設定は以上になります。
もうSSHのインバウンドポートは利用しないのでルールを削除してしまいます。

IAMロールの設定

EC2でSSMエージェントをインストールして稼働させましたが
SSMに接続を行うには、適切なIAMロールを設定する必要があります。

今回はこの後、S3とCloud Watch Logsにログ出力することを想定して
以下のポリシーを作成しロールにアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel",
                "ssm:UpdateInstanceInformation"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "*"
        }
    ]
}

ポリシー、ロールの作成とEC2へのアタッチ方法は以下の通りです。

  1. AWSマネージメントコンソールからサービスで[IAM]を検索し、[ポリシー]→[ポリシーの作成]とクリックする

  2. ポリシーの作成画面で[JSON]を選択し、上記記載のJSONの内容を貼り付けし[ポリシーの確認]をクリックする

  3. 名前と説明は任意で適当に入力し、概要が以下画像と同じようになっていることを確認し[ポリシーの作成]をクリックする

これでポリシーが作成できたので、次はポリシーをロールにアタッチします。

  1. IAMの画面から[ロール]→[ロールの作成]をクリックする

  2. [AWSサービス][EC2]を選択し[次のステップ:アクセス権限]をクリック

  3. 先ほど作成したポリシーを検索し、選択したうえで[次のステップ:タグ]をクリック

  4. タグは任意で設定し[次のステップ:確認]をクリック

  5. 任意のロール名をつけ[ロールの作成]をクリック

ロールも作成できたので対象のEC2にロールをアタッチします。

  1. サービスで[EC2]を選択し対象インスタンスにチェックをいれ[アクション]をクリックし[インスタンスの設定]→[IAM ロールの割り当て/置換]をクリック

  2. IAM ロールの割り当て/置換画面で先ほど作成したロールを選択し[適用]をクリック

これで対象EC2に対して、ロールのアタッチが完了しました。

GUIからの確認

ここまで設定すると、Systems Managerのセッションマネージャー画面から
すでにGUIでシェルアクセスが行えるようになっています。

サービスから[Systems Manager]を選択し左タブから[セッションマネージャー]を選択

この画面で[セッションの開始]をクリックします。

すると先ほどSSMエージェントをインストールしたサーバがターゲットインスタンスに登録されているので
チェックをいれ[セッションを開始する]をクリックします。

(この画面にインスタンスが表示されるまでに多少時間がかかる場合があります)

するとこのようにGUIからシェル操作が行えるようになりました。

[終了]をクリックするかexit等でセッションを切断することができます。

セッションマネージャーの画面から[セッション履歴]をクリックすることで過去の接続履歴を確認することもできます。

接続元環境となるPC側での準備

それではリモートからもシェルアクセスが行えるように
自分のPC側での設定作業をしていきます。

前提として、自PCではAWS CLIのバージョン 1.16.12 以降がインストールされており
すでにAWS CLIで利用するIAMユーザのアクセスキーとシークレットアクセスキーを設定しているものとして進めていきます。

条件を満たしていない方は以下URLを参考に設定をお願いします。
参考:AWS コマンドラインツールをインストールまたはアップグレードする

またMacOS前提で進めていくため、他のOSをご利用の場合は適宜自分の環境に置き換えてご確認ください。

AWS CLIの設定

リモートからセッションマネージャーを利用して接続するために、Session Manager Pluginを自PCにインストールします。

もし対象OSがWindowsまたはLinuxの場合は、以下URLからそれぞれの環境にあった設定方法をご確認ください。
参考:AWS CLI 用の Session Manager Plugin をインストールする

以下MacOSでのSession Manager Pluginインストール方法になります。

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
$ unzip sessionmanager-bundle.zip
$ sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin

上記3コマンドで設定完了になります。

【セッションマネージャーで接続できるサーバを絞りたい場合】IAMユーザに適切な権限を付与

もしCLIで利用するIAMユーザに対して、特定のEC2インスタンスに対してのみセッションマネージャーでの
接続を許可したい場合は、以下のようなポリシーを作成しIAMユーザにアタッチすることで実現できます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:対象インスタンスのarnに置き換え"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:username}-*"
            ]
        }
    ]
}

これによりResourceで指定したEC2インスタンスのみにセッションマネージャーでの接続を絞ることが可能になります。
利用するIAMユーザの権限を絞らない場合は特に設定不要になります。

接続元環境での設定は以上になります。
これでリモートからの接続が可能になりました。

実際にセッションマネージャーを利用してリモートからシェルアクセス

準備が整ったので、実際に自PCからセッションマネージャーを使用して
シェルアクセスをしてみます。

自PCから以下コマンドで、セッションマネージャー経由でシェルアクセスすることができます。

// インスタンスIDは対象のインスタンスのIDに置き換えてください。
$ aws ssm start-session --target インスタンスID


セッションマネージャーでリモート接続できました!

デフォルトでログイン時のユーザは、ssm-userになっており
このユーザはsudo権限が与えられているので、 sudo su - でrootに昇格することができます。

これでSSHのポートを開放せずに、リモートからシェルアクセスを行うことができるようになりました。

ログ出力の設定

セッションマネージャーの良い機能として、S3またはCloudWatch Logsに操作ログを出力する
といった機能があります。

適切なポリシーはすでにロールにアタッチ済みなので
セッションマネージャーの設定画面からログ出力の設定を有効にしてみたいと思います。
(事前にS3でログ出力用のバケットを作成しておく必要があります。)

  1. セッションマネージャーの[設定]タブを選択し[編集]をクリックします。

  2. Amazon S3 バケットにセッション出力を書き込む の設定でS3バケットにチェックを入れ、S3 バケット名でログ出力先のバケットを選択します。

  3. Cloud Watch Logsに出力する場合は、CloudWatch Logs にセッション出力を送信する のCloudWatch Logsにチェックを入れます。リストからロググループを選択するで、ログを出力するロググループを選択します。

設定が完了したら右下の[保存]をクリックします。

再度シェルアクセスし、色々とコマンド操作してみます。

セッション切断後に[セッション履歴]を確認すると
出力場所として、[Amazon S3][CloudWatch Logs]のボタンが追加されています。

[Amazon S3]を選択してバケットを確認すると
logファイルが作成されているので、中身を確認すると
先ほどのコマンド操作と出力結果がファイルに出力されています。

同様に[CloudWatch Logs]を確認すると、こちらのも操作ログが出力されています。

操作ログが手軽に保存できるのは、かなりありがたい機能です。

デフォルトのログインユーザの変更

またデフォルトでssm-userになっているログインユーザをIAMユーザ毎で変更させることも可能です。

設定方法として
ショッションマネージャ側の設定で、[Linux インスタンスの Run As サポートを有効にする]
のチェックボックスにチェックを入れます。

そこで直接デフォルトのログインユーザを設定することも可能なのですが
IAMユーザ毎で変更したい場合は、空白のまま設定を反映させ、IAMユーザ側で以下のポリシーを追加します。

IAMユーザの設定画面で対象ユーザを選択し[タグの編集]をクリックします。

以下のタグを追加します。
キー:SSMSessionRunAs
値 :デフォルトに設定したいユーザ名

(ユーザはあらかじめサーバ側で作成しておく必要があります)

設定後に対象のIAMユーザでシェルアクセスすると...

デフォルトのユーザが指定したユーザに変更されました。

ssm-userだとroot権限が付与されているため、権限を絞りたい場合にIAMユーザ毎でログインユーザを変更できる機能はかなりありがたいです。

あとがき

結構手軽にSSH不要でシェルアクセスが実現可能でした。
操作ログも残り、IAMユーザ毎でログインユーザを変更し権限を絞ることもできるのは、かなりありがたい機能でした。

今後もセッションマネージャーは重宝しそうです。

参考

・参考:AWS Systems Manager Session Manager
・参考:Linux 用の EC2 インスタンスに手動で SSM エージェント をインストールする