Skip to content

Retry access propagation when sshd offers auth methods besides publickey (CUS-800) - #446

Merged
MichaelDimitras merged 1 commit into
mainfrom
michaeldimitras/CUS-800
Jul 18, 2026
Merged

Retry access propagation when sshd offers auth methods besides publickey (CUS-800)#446
MichaelDimitras merged 1 commit into
mainfrom
michaeldimitras/CUS-800

Conversation

@MichaelDimitras

Copy link
Copy Markdown
Contributor

Problem

p0 ssh to an Azure VM behind a jump host fails permanently when connecting right after a fresh grant, instead of retrying while the access role propagates.

The access-propagation retry loop (up to 180s) is keyed on each provider's unprovisionedAccessPatterns. The Azure jump-host provider (and the GCP provider) matched the literal string Permission denied (publickey) — but sshd lists every auth method it allows, so a VM whose sshd also permits password auth reports:

michael.dimitras@permz.us@10.1.0.6: Permission denied (publickey,password).

The pattern misses, isAccessPropagated() returns true, and the CLI treats the first failed attempt as a completed session — it submits an ssh.session.end audit log and exits after a single try. Since Azure RBAC role assignments take up to ~1 minute to propagate to AAD SSH login, connecting immediately after a grant always fails on such VMs. Reproduced twice against a live jump-host setup (grant at 15:04:12, cert minted at 15:04:14, one attempt, immediate termination, zero retries).

Fixes CUS-800.

Change

Loosen the pattern to tolerate any parenthesized method list that includes publickey:

/Permission denied \([^)]*publickey[^)]*\)/

Applied to src/plugins/azure/ssh-jump-host.ts and src/plugins/google/ssh.ts (same latent bug; GCP OS Login VMs are usually publickey-only, which is why it hasn't bitten there yet).

Testing

  • New pattern tests: jump-host provider retries on (publickey,password) and (publickey,gssapi-keyex,gssapi-with-mic,password); GCP provider retries on (publickey,password). Both written first and observed failing against the old patterns.
  • Full suite: 302 tests pass across 37 files; tsc clean.

🤖 Generated with Claude Code

…key (CUS-800)

The propagation retry loop is keyed on unprovisionedAccessPatterns, and
the Azure jump-host and GCP providers matched the literal string
"Permission denied (publickey)". sshd lists every auth method it
allows, so a VM that also permits password auth reports
"Permission denied (publickey,password)." — the pattern missed, the
CLI treated the first failed attempt as a completed session, and
connections right after a fresh grant always failed instead of
retrying through the RBAC propagation window.

Tolerate any parenthesized method list that includes publickey.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c22651ba-0da5-4967-9f38-91d171e29d3b

📥 Commits

Reviewing files that changed from the base of the PR and between f644e75 and de27336.

📒 Files selected for processing (4)
  • src/plugins/azure/__tests__/ssh-jump-host.test.ts
  • src/plugins/azure/ssh-jump-host.ts
  • src/plugins/google/__tests__/ssh.test.ts
  • src/plugins/google/ssh.ts

Walkthrough

Azure and Google SSH unprovisioned-access detection now recognizes publickey within authentication-method lists that include additional methods. Azure adds retry coverage for certificate rejection messages with multiple methods, while Google adds tests for both single-method and multi-method permission-denied messages.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: broadening SSH access-propagation retries for non-publickey auth lists.
Description check ✅ Passed The description covers the problem, change, and testing with enough context for review, even though some template sections are omitted.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch michaeldimitras/CUS-800

Comment @coderabbitai help to get the list of available commands.

@MichaelDimitras
MichaelDimitras merged commit a94fde5 into main Jul 18, 2026
4 checks passed
@MichaelDimitras
MichaelDimitras deleted the michaeldimitras/CUS-800 branch July 18, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants