p0cli: SSH: AWS: SSH into a AWS EC2 via SSM
Last updated: April 29, 2025
P0 CLI – SSH into AWS EC2
Audience: Engineers new to P0 + AWS
Platforms: macOS 13+, Windows 10/11
CLI version: @p0security/cli v0.4.x+
AWS tooling: AWS CLI v2, Session Manager Plugin v1.2+
1 Why wrap AWS SSH with P0?
Traditional hurdleHow | |
🔑 Key rotation – distributing & revoking public keys on hundreds of hosts. | Generates an ephemeral key pair and injects it only for the approved session duration. |
📝 Change control / approvals – Slack tickets drafted manually. | Each invocation creates a Permission Request with reason + sudo scope; approvers click to grant. |
🛂 Audit trail – who connected, when, and as which OS user? | P0 logs are exported to your SIEM; session ID captured. |
⏳ IAM propagation delay (~8 min for SSM policies). | CLI detects transient AccessDenied errors and transparently retries until access is live. |
🌍 Bastion management – public IPs, security groups. | Uses AWS SSM Session Manager as a tunnel – zero inbound ports required. |
2 Prerequisites & installation
RequirementmacOSWindows | ||
Node.js ≥ 20 |
|
|
P0 CLI |
| Same in PowerShell |
AWS CLI v2 |
| Official MSI or |
Session Manager Plugin |
| Installed with AWS CLI v2 MSI, or get separate MSI |
Login to AWS |
| Same |
Login to P0 |
| Same |
Why each piece?
AWS CLI provides the
aws ssm start-sessioncommand that acts as an SSH ProxyCommand.Session Manager plugin translates the bidirectional stream into websockets consumed by SSM.
AWS credentials (SSO or keys) authorise the tunnel; P0 does not supply them – it only grants the policy.
P0 identity authenticates you to the P0 back‑end so it can file requests on your behalf.
3 Discover EC2 instance aliases
p0 ls ssh destination --provider aws
Why run this first? – It reveals the alias → EC2 instance‑ID mapping configured by your platform team, so you know the correct <destination> token.
4 Command anatomy
p0 ssh <destination> --provider aws [p0-flags] -- [raw SSH flags]
SegmentPurpose | |
| Friendly alias (e.g. |
| Forces AWS driver (needed only when org has multi‑cloud aliases). |
| Influence Permission Request (reason, sudo…). |
| Literal double-dash – marks the start of flags passed untouched to |
| Classic OpenSSH options: |
4.1 P0-specific flags (full AWS list)
FlagWhen to useBackend effect | ||
| Give context: on‑call, deploy, audit. | Shown in Slack + audit JSON. |
| Need root privileges. | Tags request |
| Org uses nested approval scopes. | Routes request to correct approver group. |
| Diagnose or copy commands. | CLI prints every child process incl. fully‑formed |
| Scripts must not hang waiting for manual sign‑off. | Immediate failure (exit 1) if access isn’t already approved. |
5 Hands‑on walkthroughs
5.1 Open an interactive shell
p0 ssh web-prod \
--provider aws \
--reason "on-call: investigate 5xx spikes"
Under the hood
CLI ➡ P0 API → Permission Request created with fields
{dest:web-prod,provider:aws,reason:"…"}.Slack message posts → approver clicks Approve.
P0 grants you a temporary SSM session policy + uploads your public key to the instance.
IAM propagates (~8 min). CLI keeps launching
aws ssm start-sessioninside the ProxyCommand until it no longer seesAccessDeniedin stderr.OpenSSH handshake succeeds; shell opens.
5.2 Run a one‑off remote command
p0 ssh web-prod --provider aws -- "hostname && uptime"
Why? – Good for CI health checks; exit code bubbles up to pipeline.
5.3 Forward a local port
p0 ssh db-prod --provider aws -- -L 5432:localhost:5432
ElementPurpose | |
| Expose remote Postgres on local 5432. (Traffic travels over SSM tunnel.) |
5.4 Request sudo privileges
p0 ssh bastion --provider aws --sudo \
--reason "rotate TLS certs"
Effect – Backend writes a short‑lived file in /etc/sudoers.d/p0-<requestId> granting NOPASSWD ALL to your temp user.
5.5 Generate reproducible commands (for debugging)
p0 ssh api-vm --provider aws --debug -- -v
--debugprints both:Fully resolved AWS CLI command with region/profile.
Final ssh command (with escaped options) you could run manually if you already had the temp key + policy.
Extra
-vfeeds more handshake logs to your terminal.
6 Automatic SSH options that P0 injects (and why)
OptionRationale | |
| Force OpenSSH to present only the temp key – avoids Too many authentication failures. |
| Complements |
| Reroutes traffic through SSM. |
| Always added so parser can detect error strings; printed only if |
7 Windows quoting primer
PowerShell rules:
Surround the entire SSH tail in double quotes.
Escape inner double quotes with back‑slash.
p0 ssh web-prod --provider aws -- "-L 8080:localhost:80 -o \"ConnectTimeout=5\""
8 Troubleshooting matrix
SymptomLikely causeResolution | ||
| IAM policy hasn’t propagated yet. | Wait – CLI keeps retrying up to 8 min. See progress logs with |
| AWS CLI can’t find env vars/SSO profile. | Run |
| Plugin missing. | Install Session Manager Plugin (see §2). |
SSH connects but port forward won’t bind | Forgot | Add |
9 Security & cleanup
Ephemeral key: stored in
~/.p0/keys(mac) or%USERPROFILE%\.p0\keys(Win) → auto‑deleted on exit.SSM policy & OS account: P0 schedules a reaper job (default TTL = 1 h) to revoke both.
Abort:
Ctrl‑Ctriggers anAbortController; CLI tears down SSM tunnel & runs provider teardown.
10 Quick command vault
# List aliases you can request (any provider)
p0 ls ssh destination
# Copy build artefact to EC2 (uses SSM + scp)
p0 scp ./app.tgz web-prod:/opt \
--provider aws \
--reason "deploy app 2025‑04‑29"
# Dry‑run – print full aws+ssh for replication
p0 ssh web-prod --provider aws --debug -- -v
11 Need help?
Slack: #p0-community
Email: support@p0.dev
GitHub Issues: https://github.com/p0-security/cli
Happy secure shelling into AWS! 🎉