Session Manager と SSH

Session Manager と SSH

SSH over Session Manager

ローカルのシェルから EC2 にログインする際、以下の SSH 設定で Session Manager をプロキシとして使えます。

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

Session Manager はネットワーク経路を置き換えるだけで、SSH 鍵は引き続き必要です。

接続方式の比較

  通常の SSH SSH over Session Manager Session Manager のみ
ネットワーク経路 port 22 直接 SSM トンネル SSM トンネル
SSH 鍵 必要 必要 不要
認証 SSH 鍵 SSH 鍵 IAM ロールのみ
port 22 開放 必要 不要 不要

踏み台サーバーが不要になる理由

踏み台サーバーが必要になるのは、EC2 がプライベートサブネットに配置されており、外部から直接 TCP で到達できない場合です。

【踏み台サーバーが必要な構成】
インターネット
    │
    ▼
踏み台 EC2(パブリックサブネット、port 22 open)
    │
    ▼
対象 EC2(プライベートサブネット)

Session Manager では SSM Agent(EC2 側)が AWS の SSM エンドポイントに対してアウトバウンド接続を張りに行くため、インバウンドの port 22 が不要になります。

【Session Manager を使った構成】
EC2(プライベート)─── アウトバウンド HTTPS ───▶ SSM エンドポイント(AWS)
                                                        ▲
ローカル ─────────────────────────────────────────────┘

「外から EC2 に入る」のではなく「EC2 が外(SSM)に繋ぎに行く」構造のため、プライベートサブネットでも踏み台なしで接続できます。

SSM エンドポイントの位置づけ

SSM エンドポイント(ssm.ap-northeast-1.amazonaws.com)は VPC とは独立して AWS が提供するサービスエンドポイントです。

AWS グローバルネットワーク
┌──────────────────────────────────────────────────────┐
│  SSM エンドポイント(ssm.ap-northeast-1.amazonaws.com)│
└──────────────────────────────────────────────────────┘
         ▲
         │ HTTPS(アウトバウンド)
┌────────────────────────┐
│  VPC                   │
│  ┌──────────────────┐  │
│  │ EC2(プライベート)│  │
│  └──────────────────┘  │
└────────────────────────┘

EC2 から SSM エンドポイントへの疎通方法は2つあります。

方法 概要
NAT Gateway プライベートサブネット → NAT GW → インターネット → SSM エンドポイント
VPC エンドポイント(PrivateLink) VPC 内に SSM 用のエンドポイントを作り、インターネットを経由しない

SSH over Session Manager

ローカルのシェルから EC2 にログインする際、以下の SSH 設定で Session Manager をプロキシとして使えます。

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

この方法では Session Manager はあくまでネットワーク経路を置き換えるだけで SSH 鍵は引き続き使われます。

通常の SSH:
ローカル ---TCP port 22]---▶ EC2
         └─ SSH 鍵で認証

SSH over Session Manager:
ローカル ---[SSM トンネル]---▶ EC2
                              └─ SSH 鍵で認証(変わらず必要)

何が変わって何が変わらないか

  通常の SSH SSH over Session Manager Session Manager のみ(start-session)
ネットワーク経路 port 22 直接 SSM トンネル SSM トンネル
SSH 鍵 必要 必要 不要
認証 SSH 鍵 SSH 鍵 IAM ロールのみ

なぜ SSH over Session Manager を使うか

SSH 鍵が残るにもかかわらず使う理由:

  • SG の port 22 を開けなくてよい(ネットワーク攻撃面の縮小)
  • 踏み台サーバー不要
  • SCP / SFTP / ポートフォワードなど SSH の機能をそのまま使える

「長期認証情報の排除」という観点では

Session Manager のみ(aws ssm start-session)で shell に入る方法であれば SSH 鍵も不要になり、IAM ロールだけで完結します。SSH over Session Manager は「セキュリティを改善しつつ SSH の利便性を保つ」折衷案という位置づけです。

Session Manager による接続

GitHub Action

準備

  1. vars.XXX が登録されていること
  2. AWS に deployment-role を作成して信頼関係でリポジトリを許可していること

deployment-role の信頼関係

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam:::oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "sample-org/sample-repo:*"
                }
            }
        }
    ]
}

.github/deployment.yaml

name: Deployment

#...
jobs:
  deployment
    name: Deployment
    runs-on: ubuntu-22.04
    environment: $
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-duration-seconds: 1800
          role-to-assume: deployment-role # AWS の IAM ロールに同名のロールを作成。ロールの信頼で
          aws-region: ap-northeast-1

      - name: Setup SSH through AWS SSM
        run: |
          mkdir -p ~/.ssh
          echo "$ ssh-ed25519 $" >> ~/.ssh/known_hosts
          cat >> ~/.ssh/config <<EOT
            Host i-* mi-*
                StrictHostKeyChecking no
                ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
          EOT
          ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''
          aws ec2-instance-connect send-ssh-public-key \
              --instance-id $ \
              --instance-os-user github-actions \
              --availability-zone $ \
              --ssh-public-key file://~/.ssh/id_ed25519.pub
          until ssh github-actions@$ exit; do
              echo "Waiting for SSH connection..."
              sleep 3
          done
EC2 が GitHub を認証
  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-duration-seconds: 1800
      role-to-assume: deployment-role # AWS の IAM ロールに同名のロールを作成。ロールの信頼で
      aws-region: ap-northeast-1
GitHub が EC2 の正当性を認証

GitHub が不正なサーバーにアクセスしないため。

echo “i-1234567890 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyDataHere1234567890abcdefghijklmnopqrstuvwxyz” » ~/.ssh/known_hosts

AAAAC3NzaC1lZDI1NTE5AAAAIExampleKeyDataHere1234567890abcdefghijklmnopqrstuvwxyz は EC2 サーバーの公開鍵(値はダミー)。

プラグイン

ローカルのターミナルで Session Manager を仕様するには Session Manager プラグイン が必要。
macOS での Session Manager プラグインのインストール