hop 如何免去複製 EC2 執行個體 ID,以及 CLI 為何拒絕猜測目標
How I stopped copying EC2 instance IDs (and why my CLI refuses to guess)
Morgan Seznec 開發的 hop CLI 可跨多個 AWS 帳戶及區域搜尋 EC2 執行個體,並透過 Session Manager 開啟 shell,免去逐一查找及輸入執行個體 ID。
I work across a lot of AWS accounts. Reaching one machine used to take several steps: remember which account it lives in, find the matching profile in ~/.aws/config, check the region, look up the instance ID in the console or with aws ec2 describe-instances, and finally type:
aws ssm start-session --target i-0ee8781d10780ec32 --profile acme-prod --region eu-west-3
A few times a day, over fifteen accounts and three regions, that adds up. I wrote some shell functions to shorten it. They kept growing, and they became hop.
Searching every account at once
hop reads every profile in ~/.aws/config and ~/.aws/credentials and queries each one in its own region. The queries run in parallel, 16 at a time, and the result stays in a local cache for 15 minutes. A fleet of a few dozen accounts comes back in a few seconds the first time, and instantly after that.
Then you type whatever you remember about the machine:
hop shop app # words of its name
hop 10.90.2.73 # a private IP, copied from an alert
hop i-0ee8781d... # an instance ID
hop # a fuzzy picker over the whole fleet
hop ls shows what it found, with the profile and region of each instance:
$ hop ls
NAME PROFILE REGION ENV IP AGENT LOGGING
shop-app acme-prod eu-west-3 prod 10.83.2.182 online yes
grafana globex-prod us-east-1 prod 10.90.2.73 online yes
tps-api initech-test ap-southeast-2 test 10.68.3.138 online yes
...
26 instances, 9 profiles, regions eu-west-3, eu-west-1, us-east-1, us-west-2, eu-central-1, ap-southeast-2
The shell goes through Session Manager. The instance needs the SSM agent and an instance role; port 22 can stay closed, and there are no SSH keys to hand out.
Why it refuses to guess
A tool that opens shells on production servers should not pick a machine on its own when the query is vague, and most of the design work went there.
hop connects without asking only when exactly one instance matches strongly: its exact name, ID or IP, or whole words of a single name. Everything looser goes through you.
- When two instances share the words, like
shop-appin production andshop-app-staging, hop opens the picker with both. - A typo such as
shop-apmakes hop ask whether you meantshop-app. - A private IP has to match exactly, so
10.0.1.2never lands on10.0.1.21. The same private IP can also exist in two accounts, sohop runandhop pushask before acting on an IP when several profiles are in scope. - Without a terminal (a script, a cron job, ssh's ProxyCommand), hop has nobody to ask. It prints the candidates and stops:
$ hop run "shop app prod" uptime < /dev/null
hop: "shop app prod" only partly matches shop-app (acme-prod, eu-west-3): give its full name, ID or IP, or narrow with -p, -r or -e (no terminal to confirm)
The cache brings its own risk. An instance can be replaced between two refreshes, and its old name or IP can then belong to another machine. So when the data for an instance is more than a minute old, hop looks it up again in its account before acting. If it is gone, stopped, renamed or has a new IP, hop says what changed and searches again:
hop: shop-app (i-0ee8781d10780ec32, acme-prod, eu-west-3) is now stopped: searching again
Knowing whether the session is recorded
Session Manager can record every shell to CloudWatch Logs or S3. The setting lives in the SSM-SessionManagerRunShell document, once per account and per region, and it often differs from one account to the next. hop reads it along with the inventory and tells you before the shell opens:
$ hop shop app
hop: session LOGGED on shop-app (i-0ee8781d10780ec32, acme-prod, eu-west-3) to /ssm-logs. Everything that follows is recorded.
On an account where no destination is set, hop warns and asks Open anyway? [y/N]. With transcript: require in its configuration, it refuses those sessions.
SSO across many accounts
With IAM Identity Center, dozens of profiles often share one portal and one token. hop groups the profiles by portal, so one hop login signs in to every account behind it. It also checks the token before connecting, and when it has expired, it offers to open the portal right away.
A profile can be defined twice, with SSO in config and with keys in credentials. The AWS CLI then uses SSO, while the Go SDK on its own would pick the keys. hop does what the CLI does. hop doctor lists these profiles, along with expired tokens, long-lived keys and profiles that need an MFA code.
The other commands
-
hop run tools uptimeruns a command and returns its exit code. If you stop waiting, hop cancels a command the instance has not picked up yet, so it does not run later behind your back. -
hop tunnel tools 5432 15432 --host db.internalforwards a port, here to a database that only the instance can reach. -
hop push ./app.conf tools /etc/app.confcopies a small file and compares the SHA-256 on both sides. -
hop init ssh >> ~/.ssh/configsendsssh ec2-user@tools.hop,scpandrsyncthrough Session Manager as well.
GCP support is experimental: with gcp_projects in the configuration, hop lists Compute Engine instances across your projects and opens shells on them through IAP. It only does shells there for now. If you would use it, or want Azure, tell me in this discussion.
A release you can check
hop opens shells on your servers, so what you install should be verifiable. Each release has its checksums signed with Sigstore from the GitHub Actions run, SLSA level 3 provenance, and GitHub attestations for the archives and the Docker image:
gh attestation verify hop_0.3.1_linux_amd64.tar.gz -R morganseznec/hop
slsa-verifier verify-artifact --provenance-path hop.intoto.jsonl \
--source-uri github.com/morganseznec/hop --source-tag v0.3.1 hop_0.3.1_linux_amd64.tar.gz
Trying it
On macOS:
brew install --cask morganseznec/tap/hop-cli
Linux packages (deb, rpm, apk, Arch), Windows archives and a Docker image are on the releases page, and go install github.com/morganseznec/hop/cmd/hop@latest works too. The README lists the IAM permissions hop needs.
The code is on GitHub under the MIT license: https://github.com/morganseznec/hop. I would like to hear from people who manage many accounts, especially about what is missing for your setup.
Built with Claude Code. This article was written with Claude.
來源:DEV Community · dev.to
