Integration: SSH: Using the p0cli SSH command
Last updated: April 29, 2025
P0 CLI – Comprehensive SSH Guide
Audience: Engineers with zero prior experience of p0 + SSH
Platforms: macOS 13 (or later) • Windows 10/11
Providers supported in this guide: AWS EC2, Google Cloud (GCE)
CLI version: @p0security/cli v0.4.x (or later)
1 Why use p0 ssh instead of plain ssh?
Challenge (without P0)How P0 CLI solves it | |
🔒 Just‑in‑time access — you should not keep long‑lived users/keys on every VM. |
|
🗝 Key distribution — copying public keys to many hosts is painful. | P0 injects a temporary key pair only for the approved lifetime. |
📜 Audit trail — who accessed what, when, and why? | Every |
⏳ IAM propagation delays (AWS) / IAP tunnel setup (GCP) | The CLI automatically polls & retries until the cloud confirms access is live. |
💻 Multiple clouds & OSes | One syntax works on macOS, Windows (PowerShell/CMD), and Linux. |
Take‑away: p0 ssh wraps the cloud‑specific plumbing so you type one command and get a secure shell when—and only when—you’re authorised.
2 Install & log in
StepmacOSWindows | ||
Install Node 20+ |
|
|
Install P0 CLI |
| Same in PowerShell |
CLI in |
| Same |
Log in to your org |
| Same |
Why each step?
Node – The CLI is a TypeScript binary distributed via npm.
Global install – Makes
p0available in every terminal.Login – Stores an encrypted identity file that authenticates every CLI call.
Tip (Windows): Use the modern Windows Terminal; quoting is more predictable than the old console.
3 Anatomy of the p0 ssh command
p0 ssh <destination> [command [args…]] [p0‑options] -- [raw‑SSH‑options]
Segment by segment:
PartMandatory?Purpose | ||
| ✔ | A friendly alias registered with P0, not an IP/hostname. It tells the backend which VM you want. |
| ❌ | If supplied, P0 passes it to the remote shell non‑interactively and exits with the command’s status code. Omit to open an interactive shell. |
| ❌ | Flags interpreted by the P0 CLI itself (see next table). |
| ❌ | Literal double‑dash separates P0 flags from raw OpenSSH flags so they aren’t swallowed by yargs. |
| ❌ | Forwarded unchanged to the underlying |
3.1 Every P0‑specific flag explained
FlagWhy / when to use itEffect on backend | ||
| Alias exists in multiple clouds or your default differs from the alias prefix. | Pins the request to that cloud’s driver. |
| Your approvers need context. | Embeds the string in the Permission Request. May be mandatory by policy. |
| You’ll need root privileges once connected. | Backend flags the session; approvers see the elevated scope. The session user is added to |
| Troubleshooting, CI logs. | CLI prints verbose progress + repro commands you can replay manually. |
| Org uses hierarchical approvals (project, account…). | Routes the request to the right approver group. |
| You’re in a script that can’t wait for manual approval. | CLI fails fast if access isn’t already pre‑approved. |
4 SSH into AWS EC2 – step by step (with reasoning)
Discover aliases you could reach (optional but helpful):
p0 ls ssh destination --provider awsWhy: Lists registered instances, not necessarily ones you already have access to. Saves guessing.
Start a session:
p0 ssh web-prod --provider aws --reason "on‑call: investigate 5xx spikes"What happens under the hood
CLI calls P0 API → creates Permission Request tagged
sudo?reasonprovider=aws.Slack bot notifies approvers. CLI polls every 2 s.
Once Approved, P0:
Generates a short‑lived EC2 Session Manager (SSM) policy.
Injects your public key onto the instance.
IAM changes take ~8 min to propagate. CLI retries
aws ssm start-sessionuntil the error patterns disappear.OpenSSH finally connects via
-o ProxyCommand="aws ssm start-session …".
Interactive vs one‑off commands
# Interactive shell
a) p0 ssh app1-prod
Non‑interactive health check
b) p0 ssh app1-prod -- "cat /var/app/version.txt"
*Why*: scripts (CI/CD) can treat exit codes programmatically.
4. **Port forwarding example** (Mac):
```bash
p0 ssh db-prod --provider aws -- -L 5439:localhost:5432
Why: Tunnel local port 5439 → remote Postgres 5432 without opening security‑group rules.
Understanding automatic SSH options
Option injected by CLIWhy
-i <temp_key>Guarantees OpenSSH tries only the ephemeral key – avoids “Too many authentication failures”.
-o IdentitiesOnly=yesComplements
-i. Prevents agent from spraying other keys.-vAlways enabled so the parser can detect error patterns; echoed to screen only with
--debug.
5 SSH into Google Cloud (GCE) – step by step
Authenticate the gcloud CLI (first time / every 12 h)
gcloud auth login gcloud config set project <PROJECT_ID>Why:
p0 sshdrives IAP TCP Tunnel, which in turn relies on your local gcloud credentials.Open a session
p0 ssh analytics-vm --provider gcloud --reason "ad‑hoc data pull"Under the hood
Permission Request created.
Once approved, backend adds your account to the VM’s OS Login w/ SSH keys.
CLI spawns
gcloud compute start-iap-tunnelas a ProxyCommand. Propagation ≤ 1 min.
Reverse tunnel example (expose web UI running on VM → localhost:8080)
p0 ssh analytics-vm --provider gcloud -- -NR '*:8080:localhost:8088' -o "GatewayPorts yes"Flags explained
FlagWhy
-NNo remote command → keep tunnel open.
-R '*:8080:localhost:8088'Reverse‑forward all interfaces on VM :8080 → your laptop :8088.
-o GatewayPorts yesAllow remote users on VM to hit the bound port (needed for
*:).Sudo example
p0 ssh db-vm --provider gcloud --sudo --reason "apply emergency patch"Why: Adds your temp OS‑Login profile to
/etc/sudoers.d/p0‑<id>. Approvers see elevated scope.
6 Windows‑specific quoting pitfalls
PowerShell treats single quotes literally and uses double quotes for interpolation. When nesting quotes for the trailing SSH section, escape wisely:
p0 ssh web-prod --provider aws -- "-NR '*:8080:localhost:8080' -o \"GatewayPorts yes\""
👉 Rule of thumb:
Wrap the entire trailing part in double quotes.
Inside that, escape inner double quotes with backslashes.
7 Session teardown & security hygiene
Ephemeral key – stored in
~/.p0/keys(macOS/Linux) or%USERPROFILE%\.p0\keys(Windows). Deleted automatically after the process ends.Cloud role bindings – P0 schedules a reaper job that strips your IAM entry when the request expires (default 1 h).
Ctrl‑C – sends an
AbortControllersignal; CLI runs any provider teardown hooks (e.g., deleting IAP tunnel). Safe to kill.
8 Cheat‑sheet – common tasks (with purpose)
GoalCommandWhy it works | ||
List destinations you currently can request |
| Reads catalogue published by org admin. No IAM needed. |
Assume AWS role then SSH with same temp creds |
| First sub‑shell exports STS env vars consumed by second command. |
Copy build artefacts to VM |
|
|
Dry‑run and print reproducible commands |
|
|
9 Need more help?
Slack: #p0‑community
Email: support@p0.dev
Happy secure shelling! 🎉