tnnl

command module
v0.6.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 10 Imported by: 0

README

tnnl

tnnl は、Amazon ECS の実行中タスクとコンテナを対話的に選び、ECS Exec、 ポートフォワード、リモートホストへのポートフォワードを開始するCLIです。 同じservice/groupのタスクが複数あっても、完全なTask ARNで選択対象を区別します。

Quickstart

Go 1.25+、AWSの認証情報とRegion、Session Manager Pluginを用意します。

go version
go install github.com/wim-web/tnnl@latest

session-manager-plugin --version

export AWS_PROFILE=dev
export AWS_REGION=ap-northeast-1

tnnl version
tnnl exec --wait 30 --command sh

最後のコマンドでは、cluster、readyなtask、containerを順に選択します。qまたは Ctrl+Cで選択を中止できます。tnnlが見つからない場合は、次のインストール節で PATHを確認してください。

インストール

Goからインストール

このリポジトリはGo 1.25+を必要とします。

go install github.com/wim-web/tnnl@latest
tnnl version

go installには、実行したGo toolchainが対応するmodule versionが埋め込まれます。 tnnl: command not foundになる場合は、インストール先とPATHを確認します。

go env GOBIN
go env GOPATH
export PATH="$(go env GOPATH)/bin:$PATH"
command -v tnnl

GOBINを明示している場合は、そのディレクトリをPATHへ追加してください。

Release archiveからインストール

GitHub ReleasesからOS/architectureに合う tnnl_<os>_<arch>.tar.gzchecksums.txtを取得します。対応対象はDarwin/Linuxの amd64/arm64です。archiveを展開し、tnnlを自分のPATH上の書き込み可能な ディレクトリへ配置してください。

tar -xzf tnnl_linux_arm64.tar.gz
mkdir -p "$HOME/.local/bin"
install -m 0755 tnnl "$HOME/.local/bin/tnnl"
command -v tnnl
tnnl version

配布物を手動で検証する場合は、checksums.txtにある対象archiveのSHA-256と ダウンロードしたファイルを照合してください。

AWSコンテキスト

AWS context is caller-owned. 認証情報とRegionはAWS SDKのdefault configuration chainから読み込みます。環境変数、共有config/credentials、SSOや実行環境の IAM roleなど、AWS SDKが通常利用する設定を呼び出し前に用意してください。

tnnl intentionally has no profile/region flags(--profile--region)です。 clusterとserviceは入力JSONで指定するか、実行時に対話選択します。

環境変数を使う例:

export AWS_PROFILE=dev
export AWS_REGION=ap-northeast-1
tnnl exec --wait 0

aws-vaultを使う例:

aws-vault exec dev -- env AWS_REGION=ap-northeast-1 tnnl exec

実行前の確認:

aws sts get-caller-identity
aws configure list
session-manager-plugin --version

Session Manager Pluginの導入方法はAWS公式の Install the Session Manager plugin for the AWS CLI を参照してください。

IAM: callerとECS task role

tnnlを起動するcallerのIAM権限と、対象containerが利用するECS task roleの権限は 別物です。以下はtnnlが呼び出すaction inventoryであり、全環境向けの copy-and-paste policyではありません。実際のResourceConditionはaccount、 cluster、task、session document、KMS keyに合わせて最小権限に絞ってください。

Caller IAM
Action 使用箇所
ecs:ListClusters 全session commandのcluster選択
ecs:ListTasks 全session commandのtask検索
ecs:DescribeTasks readiness確認。execではsession作成後のruntime再取得にも使用
ecs:ExecuteCommand tnnl execのみ
ssm:StartSession portforwardremoteportforward
ssm:TerminateSession remote session作成後のhandoff/plugin失敗時のcleanup。拒否された場合、そのcleanup errorは元のerrorへjoinされる

Customer managed KMS keyでECS Exec通信を追加暗号化する場合、callerには kms:GenerateDataKeyが必要です。

ECS task role

対象taskのtask role(task execution roleではありません)には、managed SSM agentが channelを作成・接続するための次のactionが必要です。

  • ssmmessages:CreateControlChannel
  • ssmmessages:CreateDataChannel
  • ssmmessages:OpenControlChannel
  • ssmmessages:OpenDataChannel

Customer managed KMS keyによるECS Exec暗号化を使う場合は、task roleに kms:Decryptも必要です。

権限と前提条件の一次資料:

Target readinessと選択表示

execportforwardremoteportforwardはいずれも、次をすべて満たすtargetだけを 候補にします。

  • taskのenableExecuteCommandtrueで、task statusがRUNNING、Task ARNが存在する。
  • container nameとruntime IDが存在し、container statusがRUNNINGである。
  • containerのmanaged agent名がExecuteCommandAgentで、そのstatusがRUNNINGである。

taskの表示labelにはservice/groupとshort task IDを含めます。内部のhidden valueは full unique Task ARNです。同じservice/groupを持つ複数taskでも、選択した行のARNが そのまま利用されます。

候補が1件なら自動選択し、複数なら一覧を表示します。eligibleなtaskまたはcontainerが ない場合、remote sessionを作成せずに理由を返します。

コマンド

exec

container内でinteractive commandを実行します。command defaultはshです。

tnnl exec --command sh
tnnl exec --wait 30 --command "sh -l"
tnnl exec --input-file exec-input.json --command bash

--waitの詳細は後述します。明示した--command--waitは入力ファイルの値より 優先されます。

portforward

containerのportへlocal portをforwardします。--local-portを省略するか、入力JSONの local_port_numberを空文字にすると、一時的に確保して解放した空きportを自動選択します。 literal 0は自動選択の指定ではなく、範囲外としてerrorになります。

tnnl portforward --target-port 5432 --local-port 15432
tnnl portforward --target-port 5432
tnnl portforward --input-file portforward-input.json
remoteportforward

ECS taskを経由してremote hostのportへforwardします。--host--remote-portは 必須です。local portはflagを省略するか入力JSONを空文字にすると自動選択され、literal 0は範囲外としてerrorになります。

tnnl remoteportforward --host db.internal.example --remote-port 3306 --local-port 13306
tnnl remoteportforward --host db.internal.example --remote-port 3306
tnnl remoteportforward --input-file remoteportforward-input.json
update

最新releaseを検証してから、実行中のtnnlを置換します。

tnnl update

配置先ディレクトリへの書き込み権限と、GitHub Releasesへのnetwork accessが必要です。 検証順序と失敗時の挙動は「Updateの検証と置換」を参照してください。

Strict input JSONと優先順位

設定の優先順位は次のとおりです。

explicit CLI flag > input file > default

この優先順位はcommand固有のflagに適用されます。clusterとserviceは入力JSONに書くか、 空のまま対話選択します。入力ファイルは--input-fileで指定します。

decoderはstrictです。unknown keyと、1つ目のJSON objectに続くtrailing JSON documentは errorになり、AWS APIを呼ぶ前に終了します。portはASCII decimal 1-65535のみ有効です。 waitは0以上でなければなりません。

入力フィールド:

Command JSON fields
共通 clusterservice
exec commandwait
portforward target_port_numberlocal_port_number
remoteportforward remote_port_numberlocal_port_numberhost

templateは次のコマンドで生成します。

tnnl exec make-input-file
tnnl portforward make-input-file
tnnl remoteportforward make-input-file

default outputはそれぞれexec-input.jsonportforward-input.jsonremoteportforward-input.jsonです。既存ファイルは暗黙に上書きしません。 置換する場合だけ--forceを明示します。

tnnl exec make-input-file --output exec-input.json --force

Waitの正確な挙動

--waitexecだけが持ち、cluster選択後のeligible task検索を制御します。

  • tnnl exec --wait 0は論理的なeligible task lookupを一度だけ実行し、eligible taskが なければ直ちにerrorを返します。その1 lookup内でもpaginationとDescribeTasksの chunkingにより、AWS API callは複数回になり得ます。
  • tnnl exec --wait 30のようなpositive waitは、eligible taskが現れるまでreadinessを pollし、指定秒数のtimeoutまたはcaller contextのcancellationで終了します。
  • 入力JSONにserviceがあれば全pollをそのserviceへ絞り、なければ選択cluster内の eligible taskを待ちます。
  • 成功時のtask/container候補は最後のDescribeTasks結果から作るため、wait前の古い runtime IDを再利用しません。

Updateの検証と置換

tnnl updateはlatest releaseのarchiveとchecksums.txtをprivate temporary directoryへ downloadし、対象asset名のSHA-256を選びます。

  1. archiveをSHA-256で検証する。checksum mismatchなら展開しない。
  2. 検証済みarchiveからcandidate binaryを展開する。
  3. candidateのversionをrelease tagと比較する。candidate version mismatchなら 現行binaryを置換しない。
  4. executableと同じdirectoryにunique temporary fileを作り、copy、chmod、sync、close後に atomic renameする。

checksum、展開、candidate version検証、rename前の置換処理で失敗した場合は、現行binaryの 内容とmodeを維持し、update自身が作ったtemporary fileだけをcleanupします。置換には executable fileだけでなく、その親directoryへの書き込み権限が必要です。

SHA-256 checksumは破損やrelease manifestとの不一致を検出しますが、cryptographic signature(署名)ではありません。tnnl updateはsignature verificationや自動rollbackを 提供すると主張しません。

トラブルシューティング

症状 主な原因 次に確認するコマンド・設定
credentialsまたはRegionが見つからない caller-owned AWS contextが未設定、profile名違い、Region未設定 aws sts get-caller-identityaws configure listを実行し、effectiveなprofile・Region・取得元を確認して、AWS_PROFILEAWS_REGIONまたは共有AWS configを修正する
plugin not found、またはversion check失敗 Session Manager Pluginが未導入、古い、PATH command -v session-manager-pluginsession-manager-plugin --versionを実行し、AWS公式install手順で導入・更新する
AccessDenied caller IAMまたはtask roleのaction/resource/condition不足 aws sts get-caller-identityでprincipalを確定し、errorに出たactionを上のCaller IAM/task role inventoryと照合する
eligible taskがない task停止、ECS Exec無効、service指定違い aws ecs list-tasks --cluster CLUSTERで候補を確認し、続けてaws ecs describe-tasks --cluster CLUSTER --tasks TASK_IDを実行する
agentまたはruntimeがreadyでない container停止、ExecuteCommandAgent停止、container name/runtime ID欠落 aws ecs describe-tasks --cluster CLUSTER --tasks TASK_ID --query "tasks[].{exec:enableExecuteCommand,status:lastStatus,containers:containers[].{name:name,status:lastStatus,runtime:runtimeId,agents:managedAgents}}"を実行する
wait timeout 指定時間内にeligible taskが現れない、入力JSONのserviceが違う 入力JSONのserviceを確認し、tnnl exec --wait 30の秒数を調整する。上のdescribe-tasksでもreadinessを確認する
local port conflict explicit local portを別processがlisten中 macOSではlsof -nP -iTCP:15432 -sTCP:LISTEN、Linuxではss -ltnを確認する。必要なら--local-portを省略して自動選択する
checksum mismatch download破損、proxy/cache、release assetとmanifestの組み合わせ違い 同じreleaseのassetとchecksums.txtを再取得し、sha256sum ASSET_NAMEまたはshasum -a 256 ASSET_NAMEの結果をmanifestの対象行と比較してからtnnl updateを再実行する
candidate version mismatch archiveのbinary versionとlatest tagが一致しない uname -suname -mtnnl versionを確認し、GitHub Releasesのtagと対象assetを照合する
executable directoryへのpermission failure symlink解決後のtnnl親directoryに書き込み権限がない ls -l "$(command -v tnnl)"でsymlinkを確認し、tnnl updateのerrorに表示された解決済みpathをPATH_FROM_ERRORへ置き換えてls -ld "$(dirname "PATH_FROM_ERROR")"を実行する。必要ならuser-ownedなPATHへ再配置する

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
cmd
internal
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL