Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Amazon EC2 Instance Connect Endpointでプライベート RDS へ安全にアクセス

By Richard KangJun 29, 20237 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

aws security best practices

Postgres RDSへのpsqlコマンド実行など、プライベートなAWSリソースへの接続は通常、踏み台ホストを介して行います。しかし踏み台ホストはコストがかさみ、運用も手間がかかります。本記事では、Amazon EC2 Instance Connectを使って、低コストかつ手軽に、安全に接続する方法をご紹介します。

AWSのセキュリティのベストプラクティスでは、ネットワークを確実に分離するため、データベースへのアクセスをプライベートIPアドレス範囲のみに限定することが推奨されています。つまり、RDSなどのデータベースはプライベートサブネットに配置するのがベストプラクティスです。

プライベートリソースへのアクセス方法のひとつが、踏み台ホストの利用です。

ただし踏み台ホストにはコストがかかります。たまにしか使わないにもかかわらず24時間365日稼働させていることが多く、定期的なセキュリティパッチの適用やネットワークファイアウォールの例外ルール管理など、単発のインスタンスを維持するための運用負荷も発生します。管理が行き届かない踏み台ホストは、システムの攻撃対象領域を広げる原因にもなります。たとえば、ビジネスパートナーと事前共有した踏み台ホストアクセス用の長期間有効なSSHキーが、サイバーセキュリティ上の脅威となるケースが考えられます。

2023年6月13日に発表されたAmazon EC2 Instance Connect Endpointの新機能を使えば、踏み台ホストを運用しなくても、プライベートサブネット上のworkloadsにアクセスできるようになります。

目次

· 目次

· 概要

· 手順

· 前提条件

· EC2 Instance Connect Endpoint用のセキュリティグループを作成する

· EC2 Instance Connect Endpointを作成する

· 接続用のIAMポリシーを設定する

· コンテナDevOpsでプライベートRDSに接続する

· EC2 Instance Connect Endpoint経由でRDSに接続する

· トラブルシューティング

· aws ec2-instance-connect open-tunnelで発生するInvalidParameter

· まとめ

概要

aws security best practices

EC2 Instance Connectからプライベートサブネット上のRDSへ接続する全体アーキテクチャ

  1. ユーザーはインターネットから、AWS CLIのaws ec2-instance-connect open-tunnelでEC2 Instance Connect Endpointサービスに接続します。
  2. EICの接続にはIAMによる権限制御が適用され、必要に応じてログを取得することもできます。
  3. EC2 Instance Connect Endpointからの接続は、workload側のセキュリティグループでインバウンド許可が必要です。
  4. EC2 Instance Connect EndpointからRDSへは、プライベートIP経由で接続されます。

手順

前提条件

  1. インターネットを介さずに接続できることを示すため、RDSのサブネットルートテーブルにInternet Gatewayへのルートが設定されていないことを確認してください。
  2. RDSのセキュリティグループ(例:sg-012345)を控えておきます。
  3. RDSのVPC(例:vpc-012345)を控えておきます。

上図のとおり、EC2 Instance Connect Endpointは同じVPC内に作成します。 4. RDSが配置されているプライベートサブネット(例:subnet-0abc101subnet-0abc102)を控えておきます。

EC2 Instance Connect Endpointは、いずれかのサブネットに作成します。 5. RDSのプライベートIP(例:10.0.128.61)を控えておきます。

インターネットからAWS CLIでEC2 Instance Connectに接続しますが、AWS CLI バージョン2.12.1時点では、open-tunnelはトンネルを開く際にIPアドレスしか受け付けません。

RDSインスタンスのプライベートIPは、EC2ダッシュボードの「Network interfaces」で「 Description=RDSNetworkInterface」のフィルタを適用すると確認できます。

結果が複数表示される場合は、VPCで絞り込んでください。

該当するNetwork Interfaceを選択すると、「IP addresses」パネルにPrivate IPv4アドレスが表示されます。

ec2 security group

RDSNetworkInterfaceのプライベートIPを検索する

EC2 Instance Connect Endpointで接続したいプライベートAWSリソースの情報がそろったら、まずEC2 Instance Connect Endpoint用のセキュリティグループを作成し、続けてEC2 Instance Connect Endpoint本体を作成します。

EC2 Instance Connect Endpoint用のセキュリティグループを作成する

EC2 Instance Connect Endpoint専用のセキュリティグループを作成します。このセキュリティグループはインバウンドルールを持たず、RDSセキュリティグループを宛先とするRDSへの接続用アウトバウンドルールを1つだけ設定します。

  • EC2コンソールの「Create security group」(https://console.aws.amazon.com/ec2/v2/home#CreateSecurityGroup)を開きます。
  • 分かりやすい「Security group name」と「Description」を入力します。
  • RDSが属するVPCを選択します。本例ではvpc-012345です。
  • 「Inbound rules」は空のままにします。
  • 「Outbound rules」で、以下の内容のアウトバウンドルールを設定します。

a. Type: Customer TCP

b. Port range: RDSの接続ポート(PostgreSQLなら5432など)

c. Destination: RDSのセキュリティグループを選択。本例ではsg-012345です。

d. Description: Outbound connection from EC2 Instance Connect Endpoint to RDS

  • ページ右下の「Create Security Group」をクリックします。
  • 専用のセキュリティグループ(例:sg-0abcde)が作成されます。

"ec2-instance-connect"

EC2 Instance Connect Endpoint用の新しいセキュリティグループを作成する

EC2 Instance Connect Endpointを作成する

  1. VPCコンソールの「Create endpoint」(https://console.aws.amazon.com/vpc/home#CreateVpcEndpoint)を開きます。
  2. 分かりやすいエンドポイント名を入力します。
  3. Service Categoryで「EC2 Instance Connect Endpoint」を選択します。
  4. VPCリストでRDSのVPCを選択します。本例ではvpc-012345を選択します。
  5. 「Security groups」で、EC2 Instance Connect Endpoint用に作成したセキュリティグループを選択します。本例ではsg-0abcdeです。
  6. RDSが配置されているサブネットのいずれかを選択します。本例ではsubnet-0abc101またはsubnet-0abc102です。
  7. 「Create endpoint」をクリックします。

"aws

EC2 Instance Connect Endpointを作成し、専用のセキュリティグループを割り当てる

接続用のIAMポリシーを設定する

EC2 Instance Connect Endpointの作成と、セキュリティグループの紐付けによる接続経路の確保ができたので、続いてこの接続を利用するための最小権限IAMユーザーを作成します。

  1. IAMコンソールの「Create Policy」(https://console.aws.amazon.com/iamv2/home#/policies/create?step=addPermissions)を開きます。
  2. JSON Policy Editorに切り替え、以下のポリシーを入力します。EC2 Instance Connect EndpointのResourceは該当するARNに、山括弧で囲まれた変数はご自身の環境の値に置き換えてください。
{
"Version": "2012-10-17",
"Statement": [\
{\
"Effect": "Allow",\
"Action": "ec2-instance-connect:OpenTunnel",\
"Resource": "arn:aws:ec2:<AWS Region>:<AWS Account>:instance-connect-endpoint/eice-<EICE ID>",\
"Condition": {\
"NumericEquals": {\
"ec2-instance-connect:remotePort": "5432"\
},\
"IpAddress": {\
"ec2-instance-connect:privateIpAddress": [\
"<CIDR of subnet-0abc101>",\
"<CIDR of subnet-0abc102>"\
]\
}\
}\
},\
{\
"Sid": "Describe",\
"Action": [\
"ec2:DescribeInstances",\
"ec2:DescribeInstanceConnectEndpoints"\
],\
"Effect": "Allow",\
"Resource": "*"\
}\
]
}

コンテナDevOpsでプライベートRDSに接続する

EC2 Instance Connectと、IAMユーザーに紐付けた最小権限ポリシーがそろったので、実際に接続をテストします。

ここではコンテナDevOpsのアプローチに沿って、Postgresコンテナイメージから起動したPostgresクライアントで接続します。

コンテナDevOpsは、信頼性・再現性・セキュリティの確保に役立ちます。

  • 信頼性:ツールのバージョン、依存関係、設定をパッケージ化したコンテナイメージにより、常に同じ環境で実行できます。
  • 再現性:CICDパイプラインと同じコンテナイメージを使うことで、DevOpsのデバッグ環境でも同じエラーを再現できます。
  • セキュリティ:DevOpsチームやCICD自動化で利用する前に、コンテナイメージのセキュリティスキャンや、自動化スクリプトのSCATスキャンを実施できます。

EC2 Instance Connect Endpoint経由でRDSに接続する

  1. 上記で作成したポリシーをアタッチしたIAMユーザーのAWSプロファイルを使用します。
  2. Dockerから次のコマンドでPostgresクライアントを起動し、プライベートRDSに接続します:docker run -it — rm — network=bridge postgres psql -h host.docker.internal -U <db user>
  3. db userのパスワードを入力します。
  4. 問題なく進めば、postgresプロンプトが表示されます。
% docker run -it --rm --network=bridge postgres psql -h host.docker.internal -U postgres
Password for user postgres:
psql (15.3 (Debian 15.3-1.pgdg120+1), server 14.7)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.
postgres=>

トラブルシューティング

awsec2-instance-connect open-tunnelで発生するInvalidParameter

aws ec2-instance-connect open-tunnelを実行した際、以下のエラーが発生しました。

% aws ec2-instance-connect open-tunnel --instance-connect-endpoint-id <EIC ID> --private-ip-address <RDS Endpoint DNS> --local-port 5432 --remote-port 5432
Listening for connections on port 5432.
[1] Accepted new tcp connection, opening websocket tunnel.
2023-06-20 23:32:09,666 - awscli.customizations.ec2instanceconnect.websocket - ERROR - {"ErrorCode":"InvalidParameter","Message":"The specified PrivateIpAddress is not valid. Specify a valid IPv4 PrivateIpAddress and retry your request."}
AWS_ERROR_HTTP_WEBSOCKET_UPGRADE_FAILURE: Failed to upgrade HTTP connection to Websocket.

このエラーは、AWS CLIが利用しているWebSocketの実装がプライベートIPを要求するために発生します。RDSエンドポイントを内部IPに名前解決したうえで、aws ec2-instance-connect open-tunnel--private-ip-addressパラメーターに指定してください。

EC2 Instance Connectは、RDSなどのプライベートリソースへの接続方法を大きく改善してくれる仕組みです。マネージドサービスのため、セキュリティが高まり、コストを抑えられ、運用負荷も軽減されます。

そして何より、手軽に使えるのが大きな魅力です。