AWS ECS経由でRDSに簡単接続のためのセキュアなポートフォワーディングCLIツールを作ってみた
はじめに
AWS環境でRDSにアクセスしたいとき、セキュリティを考慮すると直接インターネット経由でアクセスするのは推奨されません。通常は踏み台サーバーを使ったり、VPN接続を設定したりしますが、設定が複雑だったり管理が大変だったりします。
そこで、AWS ECSとSSM Session Managerを使って、セキュアで簡単にRDSに接続できるCLIツールを作ってみました!
このツールの特徴
- ✅ インタラクティブな操作: 使いやすいzoxideスタイルの検索付きCLI
- ✅ セキュア: AWS SSM Session Managerを使用した暗号化通信
- ✅ 簡単設定: 複雑な設定ファイル不要
- ✅ 自動取得: ECSクラスター・タスク・RDSインスタンスを自動で取得
- ✅ TypeScript製: 型安全で保守性の高いコード
仕組み
[ローカルPC] → [SSM Session Manager] → [ECSタスク] → [RDS]
↑ ↑
localhost:8888 プライベートサブネット
このツールは以下の仕組みで動作します:
- AWS SSM Session Managerでセキュアな接続を確立
- 指定したECSタスクを踏み台として使用
- ローカルポートからRDSへのポートフォワーディングを実行
📊 なぜこのツールを作ったのか
従来の方法の課題
- 踏み台サーバー管理: EC2インスタンスの管理・監視が必要
- VPN設定の複雑さ: Client VPNの設定・維持コスト
- セキュリティリスク: SSH鍵管理・セキュリティパッチ適用
- 操作の煩雑さ: 毎回コマンドを手動入力する手間
このツールで解決できること
- 管理不要: ECSタスクを踏み台として利用(既存リソース活用)
- 簡単操作: 対話的UIで誰でも簡単に使用可能
- セキュア: SSM Session Managerによる暗号化通信
- コスト効率: 追加インフラ不要
🚀 インストールと使用方法
前提条件
- AWS CLI設定済み
- Session Manager Plugin
- Node.js (v18以上)
# AWS CLI (macOS)
brew install awscli
aws configure
# Session Manager Plugin (macOS)
brew install session-manager-plugin
実行
# npmから直接実行
npx ecs-pf connect
🎮 実際の使用例
$ npx ecs-pf connect
🚀 AWS ECS経由RDS接続ツールを開始します...
📋 AWS設定を確認しています...
🌍 利用可能なAWSリージョンを取得しています...
💡 zoxide-style: リストは入力に応じてフィルタされます (↑↓で選択, Enterで確定)
? 🌍 AWSリージョンを検索・選択: ap-northeast-1
✅ リージョン: ap-northeast-1
🔍 ECSクラスターを取得しています...
? 🔍 ECSクラスターを検索・選択: production-cluster
🔍 ECSタスクを取得しています...
? 🔍 ECSタスクを検索・選択: web-service: 12345678...
🔍 RDSインスタンスを取得しています...
? 🔍 RDSインスタンスを検索・選択: production-db (postgres) - xxx.rds.amazonaws.com:5432
? RDSポート番号を入力 (postgres): 5432
? ローカルポート番号を入力: 8888
🚀 ポートフォワーディングセッションを開始します...
選択されたタスク: ecs:production-cluster_123456789
実行コマンド:
aws ssm start-session --target ecs:production-cluster_123456789 --parameters {"host":["xxx.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["8888"]} --document-name AWS-StartPortForwardingSessionToRemoteHost
🎯 localhost:8888 でRDS接続が利用可能になります
セッションを終了するには Ctrl+C を押してください
接続が確立されたら、別のターミナルでデータベースに接続できます:
# TablePlusや DBeaver などのGUIツールでも接続可能
# PostgreSQLの場合
psql -h localhost -p 8888 -U myuser -d mydatabase
# MySQLの場合
mysql -h localhost -P 8888 -u myuser -p mydatabase
🛠️ 技術詳細
使用している技術スタック
- 言語: TypeScript + Node.js (ESModules)
- AWS SDK: @aws-sdk/client-*シリーズ
- CLI: Commander.js
- 対話UI: Inquirer.js + Fuse.js (あいまい検索)
- ビルドツール: TypeScript Compiler
- リンター/フォーマッター: Biome
主要な実装ポイント
1. zoxideスタイルの検索機能
const selectedCluster = await search({
message: "🔍 Search and select ECS cluster:",
source: async (input) => {
return await searchClusters(clusters, input || "");
},
pageSize: 12,
}) as ECSCluster;
Fuse.jsを使って、リアルタイムでファジー検索ができる使いやすいUIを実装しました。
2. AWS SDK v3の活用
const ecsClient = new ECSClient({ region });
const clusters = await ecsClient.send(new ListClustersCommand({}));
最新のAWS SDK v3を使用して、モジュラーで効率的なAWS APIの呼び出しを実現。
3. エラーハンドリングと再試行機能
export async function connectToRDS(): Promise<void> {
let retryCount = 0;
const maxRetries = 3;
while (retryCount <= maxRetries) {
try {
await connectToRDSInternal();
return;
} catch (error) {
retryCount++;
displayFriendlyError(error);
if (retryCount <= maxRetries) {
const shouldRetry = await askRetry();
if (!shouldRetry) return;
}
}
}
}
🔧 必要なAWS権限
このツールを使用するには、以下のIAM権限が必要です:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:ListClusters",
"ecs:ListServices",
"ecs:ListTasks",
"ecs:DescribeTasks",
"rds:DescribeDBInstances",
"ssm:StartSession",
"ec2:DescribeRegions"
],
"Resource": "*"
}
]
}
🔒 セキュリティの考慮点
1. セキュアな通信
- SSM Session Managerによる暗号化通信
- インターネットゲートウェイ不要
- セキュリティグループでの厳密なアクセス制御
2. 最小権限の原則
- 必要最小限のIAM権限のみ要求
- 一時的な接続(セッション終了で自動切断)
3. 監査ログ
- AWS CloudTrailでセッション開始/終了を記録
- Session Managerによる接続ログ
🚧 今後の改善予定
- 引数対応: コマンドライン引数での接続先指定
- 設定ファイル対応: よく使う接続先の保存機能
🌟 まとめ
AWS ECS経由でRDSに接続するCLIツール「ecs-pf」を紹介しました。
このツールの特徴:
- セキュア: SSM Session Managerによる暗号化通信
- 簡単: 対話的UIで直感的な操作
- 効率的: 既存のECSタスクを踏み台として活用
- 保守性: TypeScriptによる型安全なコード
開発者の皆さん、ぜひ試してみてください!
npx ecs-pf connect
🔗 リンク
🏷️ タグ
AWS ECS RDS CLI TypeScript ポートフォワーディング SSM セキュリティ DevOps