AWS入門:Terraformで構築したEC2環境にSession Manager経由でSSH接続する

スポンサーリンク
AWS入門:Terraformで構築したEC2環境にSession Manager経由でSSH接続する 環境構築
AWS入門:Terraformで構築したEC2環境にSession Manager経由でSSH接続する
この記事は約10分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、EC2にセッションマネージャ経由でSSH接続する方法についてご紹介します。

スポンサーリンク

前提

この記事は下記の記事をベースにしています。

背景

先日、セッションマネージャでEC2環境に接続する方法をご紹介しましたが、今回は、セッションマネージャを経由して、SSH接続する方法をご紹介します。

EC2にセッションマネージャ経由でSSH接続する理由は以下の通りです:

  1. セキュリティの向上: セッションマネージャは、SSH接続を通常のポート(通常は22番ポート)を使用せずに行うため、ポートスキャンやボットの自動化攻撃から保護されます。これにより、EC2インスタンスへの不正なアクセスを防ぐことができます。
  2. セッションログの取得: セッションマネージャは、SSHセッションのログをAWS CloudTrailに自動的に記録します。これにより、誰がいつ、どのようなコマンドを実行したかなどの監査が可能になります。セキュリティインシデントの追跡と分析に役立ちます。
  3. IAMロールによるアクセス制御: セッションマネージャはIAMロールを使用してアクセス権を制御することができます。IAMロールを使用することで、必要な権限を持つユーザーにのみアクセスを許可し、不要な特権の付与を回避できます。
  4. パブリックIPの不要: 通常のSSH接続では、EC2インスタンスがパブリックIPを持っている必要がありますが、セッションマネージャを使用する場合は、パブリックIPが必要ありません。セッションマネージャは、AWS Systems Managerのエージェントを使用してインスタンスに接続し、VPC内のプライベートIPを使用して通信を行います。
  5. ポートフォワーディング: セッションマネージャを使用すると、ポートフォワーディングを簡単に設定できます。ポートフォワーディングを使用することで、セッションマネージャを経由してリモートサーバーにアクセスし、リモートサーバー経由で別のサーバーやリソースにアクセスすることができます。

これらの理由から、セッションマネージャを使用することでセキュリティを向上させ、効果的なリモートアクセスを実現できるのです。通常のSSH接続よりも安全であるため、セッションマネージャの使用が推奨されています。

修正内容

下記のファイルを更新します。下記の各セクションに各ファイルの修正内容を記載しています。

        modified:   security.tf

security.tf

8 – 15行目を削除します。

-resource "aws_security_group_rule" "learn_ec2_ingress" {
-  type              = "ingress"
-  from_port         = "22"
-  to_port           = "22"
-  protocol          = "tcp"
-  cidr_blocks       = ["0.0.0.0/0"]
-  security_group_id = aws_security_group.learn_ec2_sg.id
-}

~/.ssh/config

下記の内容を追記します。

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

動作確認

AWS環境構築

下記のコマンドを実行します。

terraform fmt
terraform validate
terraform apply

下記のような結果になれば成功です。

Apply complete! Resources: 17 added, 0 changed, 0 destroyed.

Outputs:
ec2_global_ips = [
        "xxx.xxx.xxx.xxx",
    ]
ec2_instance_id = [
        "xxx",
    ]
secretsmanager_secret = "xxx"
secretsmanager_secret_version = "xxx"

秘密鍵の取得

下記のコマンドで秘密鍵を取得します。

# 秘密鍵取得
aws secretsmanager --profile terraform get-secret-value --secret-id learn-awc-ec2-keypair | jq -r .SecretString > learn-awc-ec2-keypair.pem

# 秘密鍵のパーミッション修正
chmod 400 learn-awc-ec2-keypair.pem

SSH接続

下記のコマンドを実行して、秘密鍵を使用したSSH接続を試みる。xxx.xxx.xxx.xxxは、ec2_global_ipsに置き換えてください。

ssh -i learn-awc-ec2-keypair.pem ec2-user@xxx.xxx.xxx.xxx

下記のような結果になれば、想定通りです。

% ssh -i learn-awc-ec2-keypair.pem ec2-user@xxx.xxx.xxx.xxx
ssh: connect to host xxx.xxx.xxx.xxx port 22: Operation timed out

これは、22ポートの開放設定を削除したためです。

セッションマネージャ経由によるSSH接続

下記のコマンドを実行します。xxxは、ec2_instance_idに置き換えてください。

export AWS_PROFILE=terraform
ssh -i learn-awc-ec2-keypair.pem ec2-user@xxx

下記のような結果になれば成功です。

% ssh -i learn-awc-ec2-keypair.pem ec2-user@xxx                       
The authenticity of host 'xxx (<no hostip for proxy command>)' can't be established.
ED25519 key fingerprint is SHA256:---

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
7 package(s) needed for security, out of 7 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-1-151 ~]$ 

解説

security.tf

削除したTerraformコードは、AWSのセキュリティグループに対してインバウンドのSSHトラフィックを許可するルールを作成しています。以下は、このコードの詳細な解説です:

  1. resource "aws_security_group_rule" "learn_ec2_ingress": これはTerraformのリソースブロックで、AWSのセキュリティグループルールを作成するための設定を記述します。
  2. type = "ingress": これはセキュリティグループルールのタイプを指定しています。ここでは「ingress」を指定しているため、インバウンドトラフィックを許可するルールを作成します。
  3. from_port = "22": これは許可するトラフィックの送信元ポートを指定します。ここではSSHのデフォルトポートである22を指定しています。
  4. to_port = "22": これは許可するトラフィックの送信先ポートを指定します。SSHのデフォルトポートは22なので、from_portと同じく22を指定しています。
  5. protocol = "tcp": これは許可するトラフィックのプロトコルを指定します。SSHはTCPプロトコルを使用するため、「tcp」を指定しています。
  6. cidr_blocks = ["0.0.0.0/0"]: これは許可するトラフィックの送信元IPアドレス範囲を指定します。ここでは、どのIPアドレスからでもSSH接続を許可するために「0.0.0.0/0」を指定しています。ただし、これはセキュリティ上のリスクを伴う設定であるため、実際の運用ではより厳密な範囲を指定することが推奨されます。
  7. security_group_id = aws_security_group.learn_ec2_sg.id: これはセキュリティグループルールを適用する対象となるセキュリティグループのIDを指定します。aws_security_group.learn_ec2_sg.idは、別のTerraformリソースで作成されたセキュリティグループのIDを参照しています。

このコードの目的は、EC2インスタンスに対してSSH接続を許可するために、セキュリティグループのインバウンドルールを作成することです。ただし、セキュリティ上の理由から、実際の環境では「0.0.0.0/0」のような広範囲なIPアドレス範囲を指定せず、必要な範囲のみを許可するように設定することが重要ですが、セッションマネージャ経由にすることで、この設定自体を消すことができるようになり、IPアドレスの範囲を設定する必要がなくなります。

~/.ssh/config

このコードは、AWS Systems Managerを介してSSHセッションを確立するためのSSH ProxyCommand ディレクティブを定義しています。以下は、コードの説明です:

  1. host i-* mi-*: この行は、「i-」で始まる(EC2インスタンス)または「mi-」で始まる(DocumentDBクラスター)ホスト名にマッチするパターンを定義しています。これにより、対象のインスタンスやクラスターにSSHで接続しようとした際にマッチする対象が指定されます。
  2. ProxyCommand: このディレクティブは、プロキシ経由でSSH接続を確立するためのコマンドを指定します。この場合、次のようにコマンドが定義されています:
  3. sh -c: この部分はAWS CLIコマンドをサブシェルで実行するための部分です。
  4. "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'": これはAWS CLIコマンドであり、AWS Systems Manager(Session Manager)を使用してSSHセッションを開始します。このコマンドでは、start-session コマンドを使用して次のパラメーターを指定しています:
    • --target %h: %h は実際の対象ホスト名(EC2インスタンスまたはDocumentDBクラスターにマッチするもの)に置き換えられます。これにより、接続対象のインスタンスやクラスターが指定されます。
    • --document-name AWS-StartSSHSession: これはSSHセッションに使用されるSSMドキュメント(オートメーションドキュメント)を指定します。AWS-StartSSHSession はSSHセッションのための事前定義されたドキュメントです。
    • --parameters 'portNumber=%p': このパラメーターはSSH接続に使用されるポート番号を設定します。%p はSSHの設定に基づいて適切なポート番号に置き換えられます。

ProxyCommand ディレクティブにより、Session Managerをセキュアなバスティオンとして使用して、EC2インスタンスやDocumentDBクラスターに直接SSHポートを公開せずにアクセスできるようになります。これにより、IAMロールと細かい権限設定を使用してアクセスを管理できるだけでなく、セキュリティの追加レイヤーを提供します。

おわりに

今日は、EC2にセッションマネージャ経由でSSH接続する方法についてご紹介しました。

これで、SSH接続を安全に実施できるようになったと思います。従来の踏み台サーバも不要で助かりますね。

本記事でご紹介したソースは、下記のリポジトリにあります。

よっしー
よっしー

何か質問や相談があれば、遠慮なくコメントしてください。また、エンジニア案件についても、いつでも相談にのっていますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました