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" -N

Flag

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 -- -