SSM Session Client
A single, self-contained binary for AWS SSM Session Manager. Access EC2 instances via shell, native SSH, port forwarding, or RDP β without bastion hosts, open inbound ports, or the AWS CLI plugin. Designed for restricted enterprise environments where installing the AWS CLI or Session Manager plugin is not an option.
Interactive Shell
Full terminal access to your instances via SSM. Supports ANSI colours and virtual terminal processing on Windows.
Native SSH β No Client Needed
Built-in SSH using Go's crypto library. No external SSH client, no ProxyCommand. Works on Windows out of the box.
VSCode Remote SSH
Drop-in replacement for the SSH executable in VSCode Remote SSH. Point remote.SSH.path at the binary and connect.
Port Forwarding
Tunnel TCP traffic to private instances. Multiplexed connections for SSM agents v3.0.196.0+, single-connection fallback for older agents.
RDP (Windows targets)
One command opens an RDP tunnel and launches mstsc.exe. Optional automatic password retrieval via the EC2 API.
PrivateLink Support
Override SSM, SSM Messages, EC2, STS, and KMS endpoints. Works in VPN/Direct Connect environments where AWS PrivateLink replaces public endpoints.
EC2 Instance Connect
Push an ephemeral public key via the EC2 Instance Connect API β no permanent SSH key management needed.
AWS Identity Center SSO
Automatic SSO device-code login with optional browser launch. No separate aws sso login step needed.
Flexible Target Lookup
Resolve targets by instance ID, EC2 tag, IP address, DNS TXT record, or short aliases defined in your config file.
Why use SSM Session Client instead of the AWS CLI?
| Capability | AWS CLI + Plugin | SSM Session Client |
|---|---|---|
| Interactive shell access | β | β |
| SSH ProxyCommand | β | β |
| Native SSH (no external client) | β | β |
| VSCode Remote SSH replacement | β | β |
| EC2 Instance Connect integration | β | β |
| Custom SSM Messages endpoint | β | β |
| Works in AppLocker/AirLock environments | β | β (single binary) |
| Built-in SSO login | Requires separate aws sso login | β built-in |
| Target lookup by tag / IP / DNS | β | β |
| RDP tunneling with auto password | β | β (Windows) |
| VPC endpoint overrides | β | β |
How it works
SSM Session Client uses the AWS SSM StartSession API to create an
encrypted WebSocket tunnel to your EC2 instance via the SSM Messages service.
All traffic flows through AWS β no inbound firewall rules, no bastion hosts,
no VPN to the instances themselves.
Access is controlled by IAM policy, not by distributing SSH keys. You grant (or revoke) access to an instance with a policy change, and every session is logged by AWS CloudTrail.
In environments where only AWS PrivateLink endpoints are reachable (VPN or
Direct Connect), the ssmmessages-endpoint flag replaces the public
StreamUrl returned by StartSession with your private endpoint.
This is the primary feature that makes SSM Session Client useful in air-gapped
or restricted networks.
Built for restricted enterprise environments
In many enterprise environments, application whitelisting and endpoint security tools prevent users from installing or running the AWS CLI, Python, or the Session Manager plugin. SSM Session Client is a single, statically compiled Go binary with zero runtime dependencies β it runs anywhere a standard executable is allowed.
Tested and used in environments protected by:
- Microsoft AppLocker β the binary can be deployed to an approved path and whitelisted by publisher or hash rule
- Airlock Digital β approved as a single file, no additional libraries or interpreters to trust
- ManageEngine / Endpoint Central β no installer, no registry changes, no service dependencies
- CrowdStrike, Carbon Black, SentinelOne β no child processes to spawn (unlike the AWS CLI which invokes Python and the plugin)
Because it ships as one file with everything built in β SSH client, SSM data channel, WebSocket transport, SSO login β there is nothing extra to install, configure, or get approved by your security team. Copy the binary, set your AWS credentials, and connect.
This also makes SSM Session Client ideal for complex network environments where
AWS service endpoints are only reachable via VPN or
Direct Connect through AWS PrivateLink. The
ssmmessages-endpoint flag lets you override the public
StreamUrl with your private VPC endpoint, keeping all session
traffic within your private network.
Install
SSM Session Client is a single binary with no runtime dependencies. Download
the binary for your platform, make it executable, and add it to your
PATH.
macOS
# Download the latest binary
curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-darwin-arm64 \
-o /usr/local/bin/ssm-session-client
# Make it executable
chmod +x /usr/local/bin/ssm-session-client
# Verify
ssm-session-client --version
# Download the latest binary
curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-darwin-amd64 \
-o /usr/local/bin/ssm-session-client
# Make it executable
chmod +x /usr/local/bin/ssm-session-client
# Verify
ssm-session-client --version
xattr -d com.apple.quarantine /usr/local/bin/ssm-session-client
Linux
sudo curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-linux-amd64 \
-o /usr/local/bin/ssm-session-client
sudo chmod +x /usr/local/bin/ssm-session-client
ssm-session-client --version
sudo curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-linux-arm64 \
-o /usr/local/bin/ssm-session-client
sudo chmod +x /usr/local/bin/ssm-session-client
ssm-session-client --version
sudo curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-linux-386 \
-o /usr/local/bin/ssm-session-client
sudo chmod +x /usr/local/bin/ssm-session-client
ssm-session-client --version
# For ARMv7 (Raspberry Pi 3/4, most modern ARM boards)
sudo curl -fsSL \
https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-linux-arm7 \
-o /usr/local/bin/ssm-session-client
# For ARMv6 (Raspberry Pi Zero/1)
# Replace "arm7" with "arm6" in the URL above
sudo chmod +x /usr/local/bin/ssm-session-client
ssm-session-client --version
Windows
# Download to a folder already on your PATH (e.g. C:\tools)
$url = "https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-windows-amd64.exe"
Invoke-WebRequest -Uri $url -OutFile "C:\tools\ssm-session-client.exe"
# Verify
ssm-session-client --version
$url = "https://github.com/alexbacchin/ssm-session-client/releases/latest/download/ssm-session-client-windows-arm64.exe"
Invoke-WebRequest -Uri $url -OutFile "C:\tools\ssm-session-client.exe"
ssm-session-client --version
No OpenSSH required. The
ssh-direct command and the
VSCode Remote SSH integration use a built-in Go SSH client β you do not need to
install the Windows Optional Feature "OpenSSH Client".
Optional: AWS Session Manager Plugin
The AWS Session Manager Plugin is not required.
ssm-session-client handles all SSM functionality natively, including
KMS-encrypted sessions. No additional software is needed.
If the plugin is installed, ssm-session-client can optionally use it
(controlled by the --ssm-session-plugin flag). Install instructions:
Install the Session Manager plugin for the AWS CLI.
Code Signing Certificate
Windows binaries are signed with an Authenticode code signing certificate. This allows enterprise security tools to verify the publisher and integrity of the binary. The certificate details below can be used to create whitelisting rules in AppLocker, Airlock Digital, and other endpoint security products.
| Property | Value |
|---|---|
| Subject | CN=Alex Bacchin, O=github.com/alexbacchin, C=AU |
| Issuer | CN=Alex Bacchin, O=github.com/alexbacchin, C=AU |
| Serial Number | 1B:B7:DA:54:2F:FA:C2:4E:A4:F3:9C:A5:71:D2:F6:EF:4E:EE:EC:D3 |
| Valid From | 21 February 2026 |
| Valid To | 20 February 2029 |
| Key Algorithm | RSA 4096-bit |
| Signature Algorithm | SHA-256 with RSA |
| Key Usage | Digital Signature |
| Extended Key Usage | Code Signing |
| SHA-256 Fingerprint | 75:89:E4:12:77:43:A6:9D:01:91:75:E0:B7:19:B9:FE:A7:7B:B4:5F:08:C5:35:55:41:7F:5F:B3:F2:F0:9B:6B |
| SHA-1 Fingerprint | 51:EC:2D:E1:25:26:AE:25:AF:DB:BC:10:4D:11:53:FD:4A:DC:18:27 |
| Subject Key Identifier | A3:46:9A:84:7D:7E:6C:69:9D:F1:48:55:6D:6E:D9:92:92:65:92:74 |
AppLocker β Publisher Rule
Create a publisher rule in your AppLocker EXE policy that allows binaries signed by this certificate. In Group Policy Editor:
- Navigate to Computer Configuration → Windows Settings → Security Settings → Application Control Policies → AppLocker → Executable Rules
- Right-click → Create New Rule → select Publisher
- Browse to the signed
ssm-session-client.exebinary - Set the slider to Publisher level to allow any binary signed by
O=github.com/alexbacchin, CN=Alex Bacchin
Alternatively, use a File Hash rule with the SHA-256 hash of the specific release binary.
Airlock Digital
Add the binary by certificate fingerprint or file hash. Use the SHA-256 fingerprint above to create a trusted publisher rule, or add the specific binary hash from the release checksums file.
Verifying the Signature
On Windows, right-click the .exe → Properties → Digital Signatures tab to inspect the certificate. From PowerShell:
# View the Authenticode signature
Get-AuthenticodeSignature .\ssm-session-client.exe
# Detailed certificate info
(Get-AuthenticodeSignature .\ssm-session-client.exe).SignerCertificate | Format-List
Configuration
ssm-session-client reads its configuration from three sources, in
order of precedence (highest first):
- Command-line flags β highest priority, override everything
- Environment variables β prefix
SSC_(e.g.SSC_AWS_REGION) - YAML config file β lowest priority, supplies defaults
AWS Credentials
ssm-session-client uses the standard AWS SDK credential chain. No
special configuration is needed beyond what you would set up for the AWS CLI.
Refer to the AWS documentation:
Authentication and access credentials for the AWS CLI.
Common methods:
- Named profiles in
~/.aws/credentialsand~/.aws/config - Environment variables:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN - EC2 instance metadata / ECS task role
- AWS Identity Center (SSO) β see SSO Login below
Configuration Options
| Description | Config file / Flag | Environment variable | AWS SDK variable |
|---|---|---|---|
| Config file path | config | SSC_CONFIG | β |
Log level (debug, info, warn, error) | log-level | SSC_LOG_LEVEL | β |
| AWS profile name | aws-profile | SSC_AWS_PROFILE | AWS_PROFILE |
| AWS region | aws-region | SSC_AWS_REGION | AWS_REGION / AWS_DEFAULT_REGION |
Trigger SSO login flow (true/false) | sso-login | SSC_SSO_LOGIN | β |
Open browser for SSO (true/false) | sso-open-browser | SSC_SSO_OPEN_BROWSER | β |
| STS endpoint override | sts-endpoint | SSC_STS_ENDPOINT | AWS_ENDPOINT_URL_STS |
| EC2 endpoint override | ec2-endpoint | SSC_EC2_ENDPOINT | AWS_ENDPOINT_URL_EC2 |
| SSM endpoint override | ssm-endpoint | SSC_SSM_ENDPOINT | AWS_ENDPOINT_URL_SSM |
| SSM Messages WebSocket endpoint | ssmmessages-endpoint | SSC_SSMMESSAGES_ENDPOINT | β |
| HTTP proxy URL | proxy-url | SSC_PROXY_URL | HTTPS_PROXY |
| Use Session Manager plugin | ssm-session-plugin | SSC_SSM_SESSION_PLUGIN | β |
| Enable auto-reconnect | enable-reconnect | SSC_ENABLE_RECONNECT | β |
| Max reconnection attempts | max-reconnects | SSC_MAX_RECONNECTS | β |
| Target aliases (config file only) | aliases | β | β |
| Target alias (CLI flag, repeatable) | --alias name=tag:val | β | β |
ssh-direct options (nested under ssh-direct: in config file) | |||
| SSH private key file path | ssh-direct.ssh-key-file | SSC_SSH_DIRECT_SSH_KEY_FILE | β |
| Skip host key verification | ssh-direct.no-host-key-check | SSC_SSH_DIRECT_NO_HOST_KEY_CHECK | β |
| Run a command instead of an interactive shell | ssh-direct.ssh-exec-command | SSC_SSH_DIRECT_SSH_EXEC_COMMAND | β |
| Push ephemeral key via EC2 Instance Connect | ssh-direct.instance-connect | SSC_SSH_DIRECT_INSTANCE_CONNECT | β |
| Disable Instance Connect even if set in config | ssh-direct.no-instance-connect | SSC_SSH_DIRECT_NO_INSTANCE_CONNECT | β |
proxy-url only applies to services that do not have a
custom endpoint set. ssmmessages-endpoint replaces the StreamUrl
returned by StartSession so that the WebSocket connection uses your private endpoint.
Config File
The default config file path is $HOME/.ssm-session-client.yaml (Linux/macOS)
or %USERPROFILE%\.ssm-session-client.yaml (Windows).
The file is searched in this order:
- Current working directory
- User home directory (
$HOME/%USERPROFILE%) - Directory containing the
ssm-session-clientexecutable
Pass a custom path with --config=/path/to/config.yaml.
Minimal config (AWS profile + region)
aws-profile: my-profile
aws-region: ap-southeast-2
AWS Identity Center SSO Login
ssm-session-client can trigger an AWS SSO device-code login automatically
before each session. This eliminates the need to run aws sso login separately.
-
Configure the AWS CLI for SSO. Follow the AWS guide: Configuring the AWS CLI to use AWS IAM Identity Center. This creates a profile section in
~/.aws/configwithsso_start_url,sso_account_id,sso_role_name, andsso_region. -
Set
aws-profileandsso-login: truein your config file (or pass them as flags/env vars). -
(Optional) Set
sso-open-browser: trueif your machine can open a browser. Otherwise, copy the verification URL printed to the terminal and open it in any browser.
SSO config file example
aws-profile: my-sso-profile
aws-region: ap-southeast-2
sso-login: true
sso-open-browser: true
VPC Endpoints (PrivateLink)
In environments where AWS services are only reachable via AWS PrivateLink (VPN or Direct Connect), you can override each service endpoint individually.
The ssmmessages-endpoint flag is the critical one: the StartSession
API always returns a public StreamUrl. This flag replaces that URL with
your private VPC endpoint so the WebSocket tunnel stays entirely within your private network.
Config file with VPC endpoint overrides
aws-profile: sandbox
aws-region: us-west-2
# VPC endpoint DNS names (from your VPC endpoint console/outputs)
ec2-endpoint: vpce-059c3b85db66f8165-mzb6o9nb.ec2.us-west-2.vpce.amazonaws.com
ssm-endpoint: vpce-06ef6f173680a1306-bt58rzff.ssm.us-west-2.vpce.amazonaws.com
ssmmessages-endpoint: vpce-0e5e5b0c558a14bf2-r3p6zkdm.ssmmessages.us-west-2.vpce.amazonaws.com
sts-endpoint: vpce-0877b4abeb479ee06-arkdktlc.sts.us-west-2.vpce.amazonaws.com
# Optional: HTTP proxy for services without a custom endpoint set
proxy-url: http://myproxy:3128
com.amazonaws.<region>.ssm,
com.amazonaws.<region>.ssmmessages,
com.amazonaws.<region>.ec2, and
com.amazonaws.<region>.sts.
See the AWS documentation:
Create VPC endpoints.
Target Lookup
All session commands accept a target as the first argument. Targets are resolved using the following chain (first match wins):
| Priority | Method | Example input | How it works |
|---|---|---|---|
| 1 | Instance ID | i-0abc1234def56789 | Passed directly to the SSM API |
| 2 | Alias | devbox | Looks up the alias in your config, queries EC2 by tag β errors if more than one match |
| 3 | EC2 tag | Name:web-server | Queries EC2 for running instances with tag key=value |
| 4 | IP address | 10.0.1.5 | Queries EC2 by private or public IPv4 |
| 5 | DNS TXT record | web.example.com | Resolves the hostname as a DNS TXT record expected to contain the instance ID |
Target Aliases
Aliases map a short friendly name to an EC2 tag key + value. They are unique β the lookup errors if more than one running instance matches, so the alias always refers to exactly one host.
Define aliases in the config file
aliases:
devbox:
tag-name: Name
tag-value: my-devbox
prod-web:
tag-name: Environment
tag-value: production
Define aliases on the command line (repeatable)
# Single alias on the fly
ssm-session-client shell devbox --alias devbox=Name:my-devbox
# Multiple aliases
ssm-session-client shell prod-web \
--alias devbox=Name:my-devbox \
--alias prod-web=Environment:production
CLI aliases override same-named aliases in the config file. Use aliases with any command:
ssm-session-client shell devbox
ssm-session-client ssh-direct ec2-user@devbox
ssm-session-client port-forwarding devbox:443 8443
Automatic Reconnection
ssm-session-client automatically reconnects when a WebSocket connection
drops. Configure it with:
--enable-reconnectβ enable/disable (default:true)--max-reconnectsβ maximum attempts before giving up (default:5, set0for unlimited)
Data Channel Encryption
When KMS encryption is enabled for SSM sessions, the data channel is encrypted using
AES-256-GCM. Encryption keys are derived from AWS KMS using the
GenerateDataKey API, with the session ID and target ID as encryption context.
SSM Session Client has built-in support for KMS-encrypted sessions
and does not require the AWS Session Manager plugin. The encryption is handled natively
using Go's crypto libraries. If the Session Manager plugin is installed and enabled
(ssm-session-plugin: true), it will be used instead, but it is not required.
com.amazonaws.<region>.kms) for the
key exchange to succeed within your private network.
Session Modes
Shell
Opens an interactive terminal session on the target instance. Equivalent to
aws ssm start-session.
ssm-session-client shell i-0bdb4f892de4bb54c
ssm-session-client shell i-0bdb4f892de4bb54c --config=~/.ssm-session-client.yaml
On Windows, the shell command supports virtual terminal processing with ANSI escape sequences for proper colour and formatting in remote shells.
IAM reference: Sample IAM policies for Session Manager
SSH (ProxyCommand)
Uses ssm-session-client as an SSH ProxyCommand, forwarding stdio to the
SSM data channel. The SSH client (system ssh) handles authentication and
encryption. Requires an SSH server on the target instance.
1. Configure SSH
Add to ~/.ssh/config (Linux/macOS) or %USERPROFILE%\.ssh\config (Windows):
Host i-* mi-*
ProxyCommand ssm-session-client ssh %r@%h --config=~/.ssm-session-client.yaml
2. Automatically configure SSH (optional)
ssm-session-client ssh add-proxy-command ec2-user@i-0bdb4f892de4bb54c
3. Connect
ssh ec2-user@i-0bdb4f892de4bb54c
IAM reference: Enabling SSH connections through Session Manager
SSH Direct (Native SSH Client)
A fully integrated SSH session over SSM using Go's native SSH library. No external SSH client, no ProxyCommand, no SSH server listening on an open port.
# Interactive session
ssm-session-client ssh-direct ec2-user@i-0123456789abcdef0
# With a specific key file
ssm-session-client ssh-direct ec2-user@i-0123456789abcdef0 --ssh-key ~/.ssh/my-key
# Run a single command
ssm-session-client ssh-direct ec2-user@i-0123456789abcdef0 --exec "uptime"
# Using EC2 Instance Connect (no SSH key management needed)
ssm-session-client ssh-direct ec2-user@i-0123456789abcdef0 --instance-connect
# Custom SSH port
ssm-session-client ssh-direct ec2-user@i-0123456789abcdef0:2222
Authentication chain (tried in order)
- Ephemeral key via EC2 Instance Connect (when
--instance-connectis used) - SSH agent (
SSH_AUTH_SOCK) - Private key file (
--ssh-keyor auto-discovered~/.ssh/id_ed25519/~/.ssh/id_rsa) - Password prompt (interactive)
~/.ssh/known_hosts. Use
--no-host-key-check to skip verification (not recommended for production).
Config file example
ssh-direct options live under the ssh-direct: section in the config file:
ssh-direct:
ssh-key-file: ~/.ssh/id_ed25519 # private key (omit to auto-discover)
no-host-key-check: false # set true only in trusted environments
instance-connect: true # push ephemeral key via EC2 Instance Connect
VSCode Remote SSH Integration
ssm-session-client can act as the SSH executable for VSCode Remote SSH,
eliminating the need for an external SSH client or ProxyCommand setup. This is
especially useful on Windows where OpenSSH may not be installed.
-
Configure the binary path in VSCode. Open Settings (
Ctrl+,) and search forremote.SSH.path, or add tosettings.json:// Linux / macOS { "remote.SSH.path": "/usr/local/bin/ssm-session-client" } // Windows { "remote.SSH.path": "C:\\tools\\ssm-session-client.exe" } -
Configure your SSH config file (
~/.ssh/configor%USERPROFILE%\.ssh\config):# A named host mapped to an instance ID Host my-server HostName i-0123456789abcdef0 User ec2-user # Wildcard for all instance IDs Host i-* User ec2-user StrictHostKeyChecking accept-new -
Set AWS credentials. Use a config file, environment variables (
AWS_PROFILE,AWS_REGION), or the standard credential chain. Thessm-session-clientconfig file is also honoured for VPC endpoint overrides. -
Connect. In VSCode, open the Command Palette (
Ctrl+Shift+P) β Remote-SSH: Connect to Hostβ¦ β select your configured host.
-T -o ConnectTimeout=15 -F /path/to/config hostname bash), the binary
detects SSH-compat mode, parses the SSH config to resolve the hostname to an EC2
instance ID, and establishes an SSH-over-SSM tunnel using the built-in Go SSH client.
Symlink mode: Alternatively, create a symlink named
ssh
pointing to ssm-session-client. When invoked as ssh, it
always operates in OpenSSH-compat mode.
Supported SSH Flags
When operating in OpenSSH-compat mode (VSCode or symlink), the following SSH flags are recognised:
| Flag | Description |
|---|---|
-T | Disable PTY allocation (used by VSCode) |
-t | Force PTY allocation |
-N | No remote command |
-o key=value | SSH options (StrictHostKeyChecking, UserKnownHostsFile, ConnectTimeout, etc.) |
-F <config> | SSH config file path |
-p <port> | Remote port |
-l <user> | Login username |
-i <keyfile> | Identity file (private key) |
-D <port> | Dynamic port forwarding (accepted but ignored) |
-v / -vv / -vvv | Verbosity (maps to log levels) |
SSH with EC2 Instance Connect
The instance-connect command combines SSM session tunnelling with
EC2 Instance Connect. It pushes an ephemeral SSH
public key to the instance before connecting, so no permanent key management is needed.
Authentication is controlled by the IAM action ec2-instance-connect:SendSSHPublicKey.
# SSH config using instance-connect as ProxyCommand
Host i-*
ProxyCommand ssm-session-client instance-connect %r@%h
# With a custom key pair
Host i-*
IdentityFile ~/.ssh/custom
ProxyCommand ssm-session-client instance-connect %r@%h --ssh-public-key-file=~/.ssh/custom.pub
# Automatically configure SSH
ssm-session-client instance-connect add-proxy-command ec2-user@i-0bdb4f892de4bb54c
# Then connect normally
ssh ec2-user@i-0bdb4f892de4bb54c
Port Forwarding
Securely tunnel TCP traffic to a port on a private instance without SSH, open firewall rules, or a bastion host.
# Forward local port 8888 β instance port 443
ssm-session-client port-forwarding i-0bdb4f892de4bb54c:443 8888
# Auto-assign local port
ssm-session-client port-forwarding i-0bdb4f892de4bb54c:443
smux),
allowing multiple concurrent TCP connections over a single SSM session. Older
agents fall back to single-connection mode automatically.
RDP (Windows targets only)
The rdp command (Windows build only) sets up a port-forwarding tunnel
to port 3389 and launches mstsc.exe automatically.
# Basic RDP connection
ssm-session-client rdp i-0bdb4f892de4bb54c
# Retrieve the Windows administrator password automatically
ssm-session-client rdp i-0bdb4f892de4bb54c --get-password --key-pair-file ~/.ssh/my-ec2-keypair.pem
# Custom RDP port and username
ssm-session-client rdp i-0bdb4f892de4bb54c --rdp-port 3390 --username admin
| Flag | Default | Description |
|---|---|---|
--rdp-port | 3389 | Remote RDP port on the EC2 instance |
--local-port | 0 (auto) | Local port for the SSM tunnel |
--get-password | false | Retrieve the Windows administrator password via the EC2 API |
--key-pair-file | β | EC2 key pair private key file (required with --get-password) |
--username | Administrator | RDP username |
When --get-password is used, the password is retrieved from the EC2 API,
decrypted with the provided key pair, and copied to the clipboard for pasting into the
RDP credentials prompt.
IAM: requires ec2:GetPasswordData in addition to standard SSM session permissions.
Troubleshooting
Log Files
Logs are written to both the console and a rotating log file. The log directory depends on your operating system:
| OS | Log directory |
|---|---|
| Windows | %USERPROFILE%\AppData\Local\ssm-session-client\logs |
| macOS | $HOME/Library/Logs/ssm-session-client |
| Linux / other Unix | $HOME/.ssm-session-client/logs |
Log files are rotated daily or when they reach 10 MB. The last three log files are kept.
Debug Mode
Set the log level to debug to capture verbose output including AWS API calls,
WebSocket messages, and connection lifecycle events.
Via environment variable (recommended for quick debugging)
SSC_LOG_LEVEL=debug ssm-session-client shell i-0bdb4f892de4bb54c
Via config file
log-level: debug
Via CLI flag
ssm-session-client shell i-0bdb4f892de4bb54c --log-level=debug
log-level: debug in your config file or via the environment variable.
Common Issues
macOS: "ssm-session-client cannot be opened"
macOS Gatekeeper quarantines downloaded binaries. Remove the quarantine flag:
xattr -d com.apple.quarantine /usr/local/bin/ssm-session-client
Windows: SmartScreen warning
Click More info β Run anyway. The binary is code-signed; SmartScreen may still warn on first run until the binary has sufficient reputation. Running from an Administrator PowerShell session bypasses this.
Connection times out / "target not connected"
- Verify the SSM Agent is running on the instance: in the EC2 console, check Systems Manager β Fleet Manager β instance status.
- Ensure the instance has the required IAM instance profile with the
AmazonSSMManagedInstanceCoremanaged policy. - If using VPC endpoints, confirm all four endpoints
(
ssm,ssmmessages,ec2,sts) are in place and their security groups allow traffic from the instance. - Enable debug logging (see above) and check the log file for API error details.
SSO: "no valid SSO token found"
- Ensure
sso-login: trueis set in your config (or--sso-loginflag). - If you cannot open a browser, copy the verification URL from the debug log or console and open it on another device.
- Verify the SSO profile in
~/.aws/confighassso_start_url,sso_account_id,sso_role_name, andsso_region.
Target not found
- Confirm the EC2 instance is in a running state.
- For tag-based lookup, ensure the IAM credentials have
ec2:DescribeInstances. - For alias lookup, confirm the alias is defined in the config file or
passed with
--alias.
Contributing
Contributions are welcome! Please open an issue to discuss significant changes before submitting a pull request. All code must pass the lint and unit tests before merging.
Prerequisites
- Go (version from
go.mod) - golangci-lint for linting
- Acceptance tests only: An AWS account, and OpenTofu (or Terraform) for provisioning test infrastructure
Building from Source
# Clone the repository
git clone https://github.com/alexbacchin/ssm-session-client.git
cd ssm-session-client
# Build for the current platform
go build -o ssm-session-client .
# Cross-compile
GOOS=linux GOARCH=amd64 go build -o ssm-session-client-linux-amd64 .
GOOS=darwin GOARCH=arm64 go build -o ssm-session-client-darwin-arm64 .
GOOS=windows GOARCH=amd64 go build -o ssm-session-client.exe .
Unit Tests
# Run all unit tests with the race detector and coverage
go test ./... -race -coverprofile=coverage.out -covermode=atomic
# View coverage summary
go tool cover -func=coverage.out
# Run a single test
go test ./ssmclient/... -run TestTargetResolver -race
Linting
golangci-lint run
Key lint constraints enforced in this project:
- Maximum function length: 75 lines / 50 statements
- Maximum cognitive/cyclomatic complexity: 15
- Maximum line length: 132 characters
- Active linters:
errcheck,gosec,funlen,gocognit,gocyclo,revive,bodyclose
Acceptance Tests
The acceptance test suite provisions real AWS infrastructure (an EC2 instance with
no inbound SSH access), runs end-to-end tests against it, and tears everything down.
Tests are tagged acceptance and are excluded from the standard
go test ./... run.
What the tests cover
- Shell access by instance ID, tag, alias, private IP, and DNS TXT record
- SSH direct and SSH proxy connections
- EC2 Instance Connect session
- Port forwarding (single and multiple concurrent connections)
- RDP tunnel (Windows runner, optional)
- SSO login with cached token (optional, requires an SSO profile)
- Error conditions: invalid target, missing region, session termination
1. Configure AWS credentials
The tests use standard AWS SDK credential chain. For CI, OIDC is recommended. For local runs, use a named profile or environment variables. The IAM principal needs permissions to manage EC2, SSM, IAM roles, and (optionally) Route53, KMS.
2. Provision infrastructure
cd test/scripts
make acceptance-prepare AWS_REGION=ap-southeast-2
# Wait for the SSM agent to come online
make acceptance-wait-ssm AWS_REGION=ap-southeast-2
3. Run the tests
make acceptance-run-local
4. Tear down
make acceptance-destroy AWS_REGION=ap-southeast-2
Full lifecycle (provision β test β destroy)
make acceptance AWS_REGION=ap-southeast-2
Interactive SSO test
# Requires a human to approve the device code in a browser
make acceptance-sso-interactive SSO_PROFILE=my-sso-profile
Windows / RDP tests
# Provision with a Windows instance
make acceptance-prepare TF_EXTRA_VARS="-var=create_windows_instance=true"
# Run on a Windows runner with the acceptance+windows build tags
go test ./test/acceptance/... -tags "acceptance windows" -run RDP -v