p0cli: SSH: GCP: SSH into a gcloud VM
Last updated: April 29, 2025
P0 CLI – SSH into Google Cloud VMs
Scope: Detailed, hands-on guide for engineers who have never used P0 with GCP
OS: macOS 13+, Windows 10/11
CLI versions: @p0security/cli v0.4.x+, gcloud SDK ≥ 460.0.0
1 Why use p0 ssh on GCP?
Traditional pain point How P0 solves it | |
⏱ Just-in-time access – permanent SSH keys expose risk. | p0 ssh injects a temporary key through Google OS Login only for the approved duration. |
🔐 Auditing & approvals – need Slack/Teams trace. | Every session becomes a Permission Request; approvers see who, when, why, sudo? |
🌐 Firewall/IAP hoops – configuring bastions is brittle. | CLI transparently drives an IAP TCP tunnel (no public IP needed). |
🔄 Propagation delay – OS Login can take ~60 s. | CLI retries automatically until access is usable, then continues. |
2 Prerequisites
Requirement macOS Windows | ||
Node.js 20+ | brew install node@20 or nvm install 20 | nvm install 20 or Node installer |
P0 CLI | npm i -g @p0security/cli | Same (PowerShell) |
Google Cloud SDK | brew install --cask google-cloud-sdk | Installer / choco install gcloudsdk |
Login to gcloud | gcloud auth login | Same |
Set default project | gcloud config set project <PROJECT_ID> | Same |
Org login to P0 | p0 login <P0_ORG_ID> | Same |
Why each item?
• Node & npm compile the TS binary.
• gcloud SDK provides the start-iap-tunnel sub-command used as an SSH ProxyCommand.
• gcloud auth login issues an OAuth 2 refresh token consumed by the tunnel.
• Project config tells IAP which project the target VM lives in.
3 Discover available VM aliases
p0 ls ssh destination --provider gcloud• Shows registered aliases your org mapped to real GCE instance names.
• Doesn’t guarantee you have access yet; you still request it next.
4 Command anatomy
p0 ssh <alias> --provider gcloud [p0-flags] -- [raw SSH flags]Token Purpose | |
<alias> | Friendly name of the VM (e.g. analytics-vm). |
--provider gcloud | Tells P0 to use the GCP driver. Required if your alias exists in multiple clouds. |
p0-flags | Influence the Permission Request (see §6). |
-- | Literal delimiter; everything right of it bypasses P0 and reaches ssh verbatim. |
raw SSH flags | Classic options like -L, -N, -o. |
5 Hands-on examples
5.1 Open an interactive shell
p0 ssh analytics-vm \
--provider gcloud \
--reason "Data-ad-hoc – run BigQuery client"What happens internally
1. Permission Request created with provider=gcloud, reason string.
2. Slack notifies approvers if needed.
3. Upon approval, backend adds your Google account (via OS Login) to the VM and uploads your ephemeral public key.
4. CLI builds a ProxyCommand:
gcloud compute start-iap-tunnel <INSTANCE_ID> 22 --listen-on-stdin --project <PROJECT_ID>5. CLI invokes:
ssh -v -o "ProxyCommand=<above>" -i ~/.p0/keys/<tmp>.pem <user>@<IAP_TUNNEL_HOST>6. When the shell terminates, CLI deletes the key and closes the tunnel.
5.2 Run a one-off diagnostic command
p0 ssh analytics-vm --provider gcloud -- "df -h /var"• SSH passes exact command to /bin/sh -c on the remote host.
• Exit status of df becomes the local process exit status (handy for scripts).
5.3 Reverse port-forward a web UI
p0 ssh analytics-vm \
--provider gcloud \
-- -NR '*:8080:localhost:9000' -o "GatewayPorts yes" -NFlag Purpose | |
-N | Tell SSH not to run a remote command – tunnel only. |
-R '*:8080:localhost:9000' | Expose port 9000 on your laptop as port 8080 on all VM interfaces. |
-o "GatewayPorts yes" | Allow remote hosts (not just localhost) to hit 8080. |
5.4 Request sudo access
p0 ssh db-maint --provider gcloud --sudo \
--reason "Patch openssl CVE-2025-12345"• --sudo adds your temp user to /etc/sudoers.d/p0-<id> with NOPASSWD unless your admin changed policy.
• Approvers see sudo=true tag and may elevate scrutiny.
6 P0 flag reference (GCP)
Flag When to use it Backend effect | ||
--provider gcloud | If not your org’s default. | Chooses GCP driver + IAP path. |
--reason "…" | Always recommended; often mandatory. | Stored in audit log & Slack. |
--sudo | You need root. | Adds you to sudoers; may lengthen approval. |
--debug | Investigating failures. | Prints every child command + extra SSH -v lines. |
--approved-only | CI can’t block waiting for manual approval. | Fails fast (exit 1) if request status ≠ approved. |
7 Windows quoting tips
PowerShell rules:
1. Wrap the entire trailing SSH block in double quotes.
2. Escape internal double quotes with back-slash.
p0 ssh analytics-vm --provider gcloud -- "-NR '*:8080:localhost:9000' -o \"GatewayPorts yes\" -N"8 Troubleshooting
Symptom Likely cause Fix | ||
Please log in to the gcloud CLI to SSH | Your OAuth token expired. | Run gcloud auth login again. |
Hangs >60 s at “Waiting for access to propagate” | OS Login entry not yet propagated. | Usually resolves in ≤90 s; CLI keeps retrying. If stuck, check VM has OS Login enabled. |
ssh: connect to host ... port 22: Connection refused | VM’s SSH daemon not on port 22 (Azure limitation note doesn’t apply). | Re-enable SSH or use default port. |
bind: Address already in use when port-forwarding | Local port busy. | Change local side (after last :) to free port. |
9 Security & cleanup
• Ephemeral key: ~/.p0/keys/<timestamp>.pem (or %USERPROFILE%\.p0\keys), removed on exit.
• IAM bindings: P0 auto-removes your OS Login profile at the end of the approved window (default 1 h).
• Abort safely: Ctrl-C triggers an AbortController → CLI tears down tunnel & key.
10 Quick command vault
# Interactive session with explicit project
p0 ssh bastion --provider gcloud --reason "ops"
# Copy local dir to VM (uses scp over IAP at 35 MB/s typical)
p0 scp -r ./dist bastion:/opt/apps --provider gcloud
# Generate debug repro commands
p0 ssh bastion --provider gcloud --debug -- -