Private EKS Cluster kubectl Access via AWS SSM: Meet eks-tunnel
If your team runs private Amazon EKS clusters, you know the ritual: discover the API endpoint, find a free port, start an SSM session, patch kubeconfig, verify connectivity — then repeat every time credentials expire. eks-tunnel is the CLI that does all of it in one command.

The private EKS access problem every DevOps team hits
Locking down your Amazon EKS API server endpoint to private-only access is the right call. CIS benchmarks, SOC 2 controls, and basic network hygiene all point the same direction: a Kubernetes API server reachable from the public internet is a liability. In 2026, with exploits targeting exposed Kubernetes control planes rising, disabling the public endpoint is no longer optional for production clusters.
The catch is operational friction. Once the endpoint is private, the usual aws eks update-kubeconfig flow stops working from developer laptops. Reaching the control plane requires something inside the VPC to act as a relay — and the standard answer is an EC2 bastion host running the AWS Systems Manager (SSM) Session Manager agent, with a port-forwarding session bridging local traffic to the private API server.
Setting that up manually means running through several distinct steps every session: authenticate with AWS SSO or refresh IAM credentials, call aws eks describe-cluster to get the private endpoint URL, pick a free local port, fire the aws ssm start-session command with the right remote host and port flags, update kubeconfig, and then run kubectl get nodes to confirm everything worked. On a team of eight engineers accessing five clusters across three AWS accounts, this turns into a recurring support burden and a graveyard of slightly-different shell scripts.
Introducing eks-tunnel: one command, kubectl ready
eks-tunnel is a globally-installable Node.js CLI that encodes the entire private EKS access workflow — credential refresh, endpoint discovery, SSM port-forwarding, kubeconfig patching, and connectivity verification — into a single command.
$ eks-tunnel connect eu-west-1-productionAfter that command completes, kubectl is pointing at the right context and the cluster is reachable. No manual SSM commands, no port conflicts, no stale kubeconfig entries.
Open source, MIT licensed. eks-tunnel ships with 93 unit tests and 16 property-based tests (fast-check). Packages are published via GitHub Actions with npm Trusted Publishing and provenance attestation. The source is on GitHub and the package on npm.
Prerequisites
eks-tunnel is a thin orchestrator that calls existing AWS and Kubernetes tooling. You need these four tools on your PATH before installing:
| Tool | macOS | Linux / WSL |
|---|---|---|
| AWS CLI v2 | brew install awscli | AWS install guide |
| kubectl | brew install kubectl | sudo apt-get install -y kubectl |
| session-manager-plugin | brew install --cask session-manager-plugin | AWS install guide |
| jq | brew install jq | sudo apt-get install -y jq |
Your bastion EC2 instance must have the SSM agent installed and an IAM instance profile that permits SSM sessions. The official EKS-optimized AMIs ship with the SSM agent pre-installed.
Installing eks-tunnel
$ npm install -g @fusiontechsolution.ai/eks-tunnelVerify the install:
$ eks-tunnel --version
0.1.3Configuration: the cluster registry
eks-tunnel reads cluster details from a JSON registry. Scaffold it with the init command:
$ eks-tunnel init
# Creates ~/.eks-tunnel/clusters.json with placeholder valuesOpen ~/.eks-tunnel/clusters.json and fill in your accounts and clusters:
{
"accounts": [
{
"accountId": "123456789012",
"accountName": "my-production",
"profile": "my-aws-sso-profile",
"authMethod": "sso",
"clusters": [
{
"name": "eu-west-1-production",
"bastionInstanceId": "i-0abc123def456789",
"region": "eu-west-1"
}
]
}
]
}Three fields are required per cluster: the name you want to use on the command line, the EC2 instance ID of the bastion host, and the AWS region. The config path can be overridden with the --config flag or the EKS_TUNNEL_CONFIG environment variable — useful for CI or shared team configs stored in a secrets manager.
Connecting to a private EKS cluster
$ eks-tunnel connect eu-west-1-production
✔ Prerequisites verified
✔ Registry loaded — 1 account, 1 cluster
✔ Cluster resolved: eu-west-1-production
✔ Region inferred: eu-west-1
✔ EKS endpoint discovered
✔ Port assigned: 8443
✔ SSM tunnel established via i-0abc123def456789
✔ kubeconfig updated: context eu-west-1-production → localhost:8443
✔ Connectivity verified: 3 nodes ReadyThe connect command runs a nine-step pipeline in sequence:
- Verifies that
aws,kubectl,session-manager-plugin, andjqare on the PATH - Loads and validates your
clusters.jsonregistry - Resolves the cluster by exact name, substring, or interactive selection if multiple match
- Infers the AWS region from the cluster name prefix or explicit config
- Discovers the private EKS API endpoint via
aws eks describe-cluster - Assigns a free local port starting at 8443, auto-incrementing on conflict
- Opens an SSM
AWS-StartPortForwardingSessionToRemoteHostsession through the bastion - Patches your kubeconfig with a new context pointing to
localhost:<port> - Runs
kubectl get nodesto confirm the tunnel is working
If any step fails you get a specific exit code and a plain-English error message — not a raw AWS API error or an SSM plugin stack trace.
Pluggable authentication: SSO, IAM, and external providers
Real engineering teams rarely use a single AWS authentication method. eks-tunnel supports three strategies configured per account in the registry:
| Method | authMethod value | Behavior |
|---|---|---|
| AWS SSO | "sso" (default) | Uses your named AWS profile. Prompts aws sso login automatically on session expiry. |
| Static IAM credentials | "iam" | Reads long-lived credentials from ~/.aws/credentials. Useful for service accounts. |
| External provider | "provider" | Runs a configured CLI command to obtain or refresh credentials before connecting. |
The external provider option is the one teams using Opal, Teleport, or bespoke internal authorization systems reach for.
Managing multiple clusters simultaneously
eks-tunnel stores active tunnel state in ~/.eks-tunnel/state.json, so you can connect to several clusters in parallel on different ports and manage them by name.
# See all active tunnels with port, PID, and uptime
$ eks-tunnel status
# Stop one tunnel cleanly (terminates SSM session, removes kubectl context)
$ eks-tunnel stop eu-west-1-production
# Stop everything
$ eks-tunnel stop-allThe stop command performs proper cleanup: it terminates the SSM process, removes the kubectl context from your kubeconfig, and wipes the state entry. No stale contexts, no orphaned SSM sessions.
Watch mode: self-healing tunnels for long-running sessions
SSM sessions drop. AWS SSO tokens expire. For deployment pipelines or long debugging sessions, watch mode keeps the tunnel alive automatically:
$ eks-tunnel watch eu-west-1-productionThis polls the tunnel every 30 seconds. On failure it reconnects, refreshing credentials as needed, with up to three retries before reporting the failure. You can also enter watch mode immediately after connecting:
$ eks-tunnel connect eu-west-1-production --watchScripting and CI/CD integration
The --json and --quiet flags make eks-tunnel composable in automation pipelines. Every command emits structured output when --json is set, and --quiet suppresses all progress output so only the result reaches stdout.
All commands return one of six exit codes:
| Code | Meaning | Common cause |
|---|---|---|
0 | Success | Tunnel is up, kubectl is working |
1 | General error | Config missing, parse error, no cluster match |
2 | Missing dependency | aws / kubectl / session-manager-plugin not found |
3 | Authentication failure | SSO session expired, IAM creds invalid |
4 | Tunnel timeout | SSM session failed to establish within deadline |
5 | Verification failed | kubectl get nodes returned non-zero |
Build reliable pipelines around these codes — for example, check for exit code 3 to trigger a credential refresh step before retrying, or exit code 2 to fail fast with a dependency message in your CI runner output.
Supply chain security and provenance
Every eks-tunnel release is published via GitHub Actions using npm Trusted Publishing with OIDC — no long-lived npm tokens, no NODE_AUTH_TOKEN in CI secrets. The publish workflow generates provenance attestations that you can verify with:
$ npm audit signatures @fusiontechsolution.ai/eks-tunnelThe package has two runtime dependencies (commander and inquirer) and ships with a test suite of 93 unit tests plus 16 property-based tests covering cluster resolution, region inference, port assignment, and state management. CI runs the full matrix on Node 18, 20, and 22.
Cross-platform support
eks-tunnel is tested and supported on macOS (Apple Silicon and Intel) and Ubuntu/WSL. The platform detector adapts prerequisite check messages to the detected OS. Windows native (outside WSL) is not currently supported because the AWS Session Manager plugin does not ship a Windows npm-compatible binary.
Get started
# Install
$ npm install -g @fusiontechsolution.ai/eks-tunnel
# Scaffold config
$ eks-tunnel init
# Connect
$ eks-tunnel connect my-clusterThe repository and full documentation are at github.com/fusiontechsolution-ai/eks-tunnel. The package is on npm at @fusiontechsolution.ai/eks-tunnel. Bug reports and pull requests are welcome.
Need cloud or DevOps engineering help?
The team behind eks-tunnel builds cloud infrastructure, Kubernetes platforms, and DevOps tooling for engineering teams that need to move fast without breaking things. If you are running into problems with private EKS access, multi-account AWS architecture, or platform reliability, we should talk.