EC2 Instance Connect EndpointとSSM Session Managerの使い分け

今月のAWS re:Inforce 2023で、EC2 Instance Connect Endpoint(EICE)が正式にリリースされました。これにより、Public IPアドレスを持たないEC2インスタンスへの接続がより簡単になりました。

Public IPアドレスを持たないEC2インスタンスに接続する方法は、以下があります。

  • プライベート接続(VPN、DirectConnect)で接続する
  • 踏み台(Bastion)サーバを立てる
  • SSM(System Managers)のSession Managerを利用する
  • 【今月から】EC2 Instance Connect Endpoint(EICE)を利用する

VPNや踏み台は手順が煩雑で余計にコストがかかるのですが、今までのSession Manager機能は今回のEICEと何が違うのでしょうか?どのように使い分けすれば良いでしょうか?

仕組みの比較

まずは、それぞれの接続方式の仕組みを見てみましょう。

SSM Session Managerの場合、EC2インスタンスにインストールされているSSM Agentが、SSMのEndpointと接続を確立した後、リモート接続要求をユーザから受け付ける仕組みとなります。以下の①~③までは、シェルに接続する際の流れを示しており、ポートフォワーディングの場合は更に、④のようにSSM Agentがローカルに接続を確立する形となります(例えばSSHの場合、$SSH_CLIENTを確認すると127.0.0.1になります)。

SSM Endpointから、EC2インスタンスに接続しに行くことは絶対にないのが特徴です(つまり①の方向は必ずEC2インスタンスからSSM Endpointへとなります)。

一方、EICE経由の接続は非常に自然な流れとなります。EC2 Instance Connect Endpoint(EICE)は、踏み台のような役割を果たしています。SSHの場合、$SSH_CLIENTを確認すると、EICEのENIのPrivate IPアドレスであることが分かります(EICEは、インターフェース型のVPC Endpointと同様に、Private SubnetのIPアドレスを占有します)。

詳細な情報については、AWSの公式ドキュメントを参照していただくことをお勧めします。ここでは、これら2つの接続方法の比較についてご紹介します。

SSM Session ManagerEICE
トラフィックの方向インスタンス→EndpointEndpoint→インスタンス
コスト3種類のPrivateLink型のVPC Endpoint
(ssm, ssmmessages, ec2messages)が必要なので、
最低限でも毎月30 USD
無償。PrivateLinkを利用していない
EC2に必要なエージェントSSM Agentec2-instance-connect
EC2に必要な権限SSM関連の権限(AmazonSSMManagedInstanceCore
で最低限の権限を定義)
不要
EC2に開放が必要なインバウンドポートなし22番(SSHの場合)、3389番(RDPの場合)など
可用性複数サブネットでインターフェースを作成可能1 VPCにつき1個のみ作成可能のため、AZ障害に弱い
アクセス制御の方法接続元のIdentity Policy、VPC Endpoint Policy接続元のIdentity Policy
ネットワーク制御の方法Security GroupSecurity Group
(ただし、通常全開のOutboundを絞る必要がある)
ログ出力APIコール:CloudTrail
コマンド:CloudWatch Logs、S3(ただし、logs/s3の
VPC Endpointが必要。またPort Forwarding時に非対応)
APIコール:CloudTrail
DNS要件Interface型のVPC Endpointは、DNSの書き換えを
行うため、VPCの「DNS解決を有効化」と
「DNSホスト名を有効化」をONにする必要がある
DNSの書き換えをしない。VPCのDNS設定は不要
接続対象EC2インスタンス
オンプレミスサーバ
EC2インスタンス、RDS、VPC内のプライベートIPを
持っているすべてのもの

上記のDNS要件について具体的に言うと、例えばSSMのEndpointの場合、作成前と作成後の、EC2インスタンスから見たIPアドレスが異なります。VPC Endpointを作成することによって、Internetにアクセスできない環境でもAWSサービスにアクセスできるようになります。

(VPC Endpoint作成前)
$ dig ssm.ap-northeast-1.amazonaws.com +short
99.77.60.93
(VPC Endpoint作成後)
$ dig ssm.ap-northeast-1.amazonaws.com +short
10.0.142.185

一方、EICEはEndpointがプライベート化になりません。

(VPC Endpoint作成前も作成後も)
$ dig ec2-instance-connect.ap-northeast-1.amazonaws.com +short
52.119.222.137

それぞれの利用シーン

EICEを利用するシーンは、

  • テスト用途など、コストや手軽さを最優先に考えるとき
  • EC2インスタンスだけでなく、プライベートなRDSなどに接続するとき

簡単でコストがかからないため、できるだけEICEを使いたいです。しかし、特にエンタープライズ環境において、SSM Session Managerの利用を推奨するシーンが多く存在します。

  • SSMの他の機能も利用しているとき
  • 接続の冗長性が必要なとき(EICEはVPCごとに1個のENIしか持たない)
  • ユーザが入力したコマンドをログに記録する必要があるとき(EICEはコマンド内容まで記録できない)
  • Internet経由ではなく、完全閉域のとき(接続元も接続先も閉域環境)
  • きめ細かなアクセス制御

操作ログの記録

SSM Session Managerのログ機能は、ユーザがセッション中に入力したコマンドやその実行結果を含めて記録することができます。以下の例では、「ls /etc/systemd」というコマンドがユーザによって入力され、その結果としてファイルの一覧が表示されています。

{
    "eventVersion": "1.0",
    "eventTime": "2023-06-24T16:30:58Z",
    "awsRegion": "ap-northeast-1",
    "target": {
        "id": "i-0683ba2d85e2a13aa"
    },
    "userIdentity": {
        "arn": "arn:aws:iam::123456789012:user/apiuser"
    },
    "runAsUser": "ssm-user",
    "sessionId": "apiuser-0a08b31c9539055ea",
    "sessionData": [
        "sh-5.2$ ls /etc/systemd",
        "coredump.conf  journald.conf  network      oomd.conf   resolved.conf  system       system.conf.d   user",
        "homed.conf     logind.conf    networkd.conf  pstore.conf  sleep.conf  system.conf  timesyncd.conf  user.conf"
    ]
}

完全閉域環境

「Internet経由ではなく、完全閉域のとき」になぜSSM Session Managerが必要かというと、EICEは、接続元がInternetから接続することを想定しています。例えば、aws cliを使って、EICE経由でEC2インスタンスに接続する際に以下のコマンドを使用します:

C:\>aws ec2-instance-connect ssh --instance-id i-02de068d44a67322b

この場合、接続元のWindows PCは「ec2-instance-connect.ap-northeast-1.amazonaws.com」というエンドポイントURLに接続しようとします。しかし、接続元のWindows PCがInternetに接続されていない環境にある場合、上記コマンドはエラーが発生し失敗します。

レアケースかもしれませんが、2つのAWSアカウントがあり、それぞれのAWSアカウントに1つのEC2インスタンスがPrivate Subnetに存在するとします。VPC PeeringやTransit Gatewayの設定がない場合、これらの2つのEC2インスタンス間でSSHセッションを確立するには、SSM Session Managerを使用することができますが、EICEではできません。

きめ細かなアクセス制御

EICEでもアクセス制御は可能ですが、記述方法はSSM Session Managerと異なります。EICEのIAM Policyを記述する際に、Resourceに記述するのはECIEのIDであり、EC2インスタンスのIDではありません。例えば以下のようなIAM Policyを作成します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstanceConnectEndpoints",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2-instance-connect:OpenTunnel",
            "Resource": "arn:aws:ec2:ap-northeast-1:123456789012:instance-connect-endpoint/eice-05106b3f84bb0c112"
        }
    ]
}

これはaws cliで、EICEのopen-tunnelサブコマンドを利用するのに必要最小限の権限です。この権限をユーザに付与し、そのユーザでaws cliで接続してみますと

C:\>aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id eice-05106b3f84bb0c112 --private-ip-address 172.10.20.100 --remote-port 22 --local-port 50022
Listening for connections on port 50022.
[1] Accepted new tcp connection, opening websocket tunnel.
(このメッセージが表示された後、TeraTermなどのSSHクライアントでローカルの50022番ポートに問題なく接続できました)

このように問題なく接続できます。

アクセスできるEC2インスタンスを制御したい場合、Conditionを使います。例えば特定のタグを持っているEC2インスタンスにのみアクセスできるようにするには、以下のようにIAM Policyを変更します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstanceConnectEndpoints",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": "ec2-instance-connect:OpenTunnel",
            "Resource": "arn:aws:ec2:ap-northeast-1:123456789012:instance-connect-endpoint/eice-05106b3f84bb0c112",
            "Condition": {
                "StringEquals": {
                    "ec2:ResourceTag/Division": "Finance"
                }
            }
        }
    ]
}

再度aws cliでトンネルを開いて、Division=Financeタグが付与されていないEC2インスタンスに、TeraTermなどで接続してみるとエラーが発生しました。

C:\>aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id eice-05106b3f84bb0c112 --private-ip-address 172.10.20.100 --remote-port 22 --local-port 50022
Listening for connections on port 50022.
[1] Accepted new tcp connection, opening websocket tunnel.
2023-06-25 13:29:40,260 - awscli.customizations.ec2instanceconnect.websocket - ERROR - {"ErrorCode":"AccessDeniedException","Message":"User: arn:aws:iam::123456789012:user/testuser is not authorized to perform: ec2-instance-connect:OpenTunnel on resource: arn:aws:ec2:ap-northeast-1:123456789012:instance-connect-endpoint/eice-05106b3f84bb0c112 because no identity-based policy allows the ec2-instance-connect:OpenTunnel action"}

AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE: Failed to upgrade HTTP connection to Websocket.

このように、EICEでも接続先の制御は可能です。ただし、現時点ではサポートされているアクセス先制御用のConditionキーは、タグやプライベートIPアドレスのみです。インスタンスIDなどでの指定はできません。将来的には追加される可能性もあるため、公式ドキュメントの更新に注目する必要があります。

EICEと比較して、SSM Session Managerのほうはより細かなアクセス制御が可能です。詳細については公式ドキュメントを参照してください。ただし、個人的にはほとんどの場合、EICEのアクセス制御でも十分ではないかと考えています。セキュリティ要件を考慮して選択することがおすすめです。

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top