Skip to content

feat(pam): heartbeats - #379

Open
bernie-g wants to merge 10 commits into
mainfrom
bernie/pam-385-implement-heartbeat-feature-to-validate-stored-credentials
Open

feat(pam): heartbeats#379
bernie-g wants to merge 10 commits into
mainfrom
bernie/pam-385-implement-heartbeat-feature-to-validate-stored-credentials

Conversation

@bernie-g

Copy link
Copy Markdown
Contributor

Description 📣

The test-connection and WinRM handlers returned the same 502 for a refused credential and an unreachable target, so the control plane could not tell them apart. They now classify the failure at the source and return it as auth, transport, or unknown.

Also routes MSSQL Windows-auth logins through the session proxy's handshake, which already speaks NTLM and Kerberos.

Type ✨

  • Bug fix
  • New feature
  • Improvement
  • Breaking change
  • Documentation

Tests 🛠️

Unit tests for the MSSQL auth routing, plus a live NTLM check (env-gated, skipped in CI) verified against a real SQL Server 2022 instance: correct password authenticates, wrong password is rejected.

go test ./packages/gateway-v2/ ./packages/pam/handlers/mssql/

A Windows-auth SQL Server login has no SQL-managed password, so the
database/sql path cannot carry it and the connection test fell back to a
plain TCP check. Route ntlm and kerberos through the session proxy's own
handshake instead, which already speaks both.

The live NTLM test is env-gated and skips unless a server is provided.
The test-connection and WinRM handlers returned 502 with a message for
every failure, so a dial timeout and a refused password were
indistinguishable upstream. The control plane needs them apart: a refused
credential stops the schedule, an unreachable target keeps retrying.

Classify at the source, where the driver error still exists, using typed
errors where the drivers provide them and message matching only where they
don't. WinRM already separated ErrAuth from ErrConnect internally and was
flattening both; that now survives the response too.
@linear

linear Bot commented Aug 27, 2026

Copy link
Copy Markdown

PAM-385

@infisical-review-police

Copy link
Copy Markdown

💬 Discussion in Slack: #pr-review-cli-379-feat-gateway-classify-probe-failures-as-auth-or-transport

Posted by Review Police — reviews, comments, new commits, and CI failures will stream into this channel.

Comment thread packages/gateway-v2/test_connection_handler.go Outdated
@veria-ai

veria-ai Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 2 · PR risk: 0/10

@bernie-g bernie-g changed the title feat(gateway): classify probe failures as auth or transport feat(pam): heartbeats Aug 27, 2026
@greptile-apps

greptile-apps Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds structured auth, transport, and unknown failure kinds to gateway connection-test and WinRM responses, and routes MSSQL NTLM/Kerberos tests through the PAM handshake.

  • Adds typed and message-based connection failure classification.
  • Extends RPC error responses with an optional failure kind.
  • Reuses MSSQL proxy authentication for Windows-auth credential tests.
  • Adds routing and live NTLM tests.

Confidence Score: 2/5

The PR should not merge until TLS-enabled Windows authentication, probe cancellation, and non-credential failure classification are corrected.

The new MSSQL route deterministically rejects TLS-enabled tests, can leave authentication goroutines and sockets blocked after request timeout, and marks valid-credential resource-access failures as authentication rejection.

Files Needing Attention: packages/gateway-v2/test_connection_handler.go, packages/gateway-v2/test_connection_failure_kind.go, packages/pam/handlers/mssql/proxy.go

Important Files Changed

Filename Overview
packages/gateway-v2/test_connection_handler.go Adds MSSQL Windows-auth routing, but TLS-enabled requests always fail and timed-out proxy handshakes continue running.
packages/gateway-v2/test_connection_failure_kind.go Adds failure classification, but categorizes MSSQL database-access and LDAP authorization failures as refused credentials.
packages/gateway-v2/winrm_handler.go Adds an optional structured failure kind while preserving JSON error handling.
packages/pam/handlers/mssql/proxy.go Exposes the existing authentication handshake for probes without adding context cancellation or deadlines.
packages/gateway-v2/test_connection_mssql_auth_test.go Verifies auth-method routing but does not cover TLS-enabled or stalled-target behavior.

Reviews (1): Last reviewed commit: "feat(gateway): report whether a probe fa..." | Re-trigger Greptile

Comment thread packages/gateway-v2/test_connection_handler.go Outdated
Comment thread packages/gateway-v2/test_connection_handler.go Outdated
Comment thread packages/gateway-v2/test_connection_failure_kind.go Outdated
A target that accepted the connection and withheld its PRELOGIN response
left the verifier blocked on a read after the caller had already timed
out, and since transport failures are retried those goroutines and sockets
accumulated.
The branch set EnableTLS without a TLSConfig, so every SSL-enabled NTLM or
Kerberos check failed against a working server. Comments across the change
are cut back to the few that explain something the code cannot.
Comment thread packages/gateway-v2/test_connection_failure_kind.go Outdated
ssh: handshake failed wraps everything that goes wrong after TCP connect,
including a key-exchange mismatch or a peer hangup, so a host answering
port 22 with a broken handshake was reported as a rejected credential and
took the account off the check schedule. A genuine rejection still matches
the authentication strings nested inside it.
The classifier read Postgres SQLSTATEs, MySQL/MSSQL error numbers, LDAP
result codes, and a list of driver error substrings to decide whether a
credential was refused or the target was never reached. That list had to
grow with every account type and was wrong twice in review, once for cloud
outages and once for SSH handshakes.

The probes already know the answer: they dial, then they authenticate.
Each one now tags its failure with the phase it happened in, so the vendor
codes and the substring lists are gone and a new account type needs no
classification code at all. This is the same shape gateway-retry.ts already
uses upstream, where an established channel decides retryability.
ssh.ServerAuthError is returned by NewServerConn, not by the client, so the
type check added with the phase refactor could never match and every SSH
failure classified as transport. The client wraps a refused password and a
broken handshake in the same ssh: handshake failed text, so the two are only
separable by whether the client got as far as offering a credential, which
the auth callbacks now record.

Adds live_probe_test.go (build tag liveprobe): 36 cases across Postgres,
MySQL, MSSQL, MSSQL over NTLM, Redis, MongoDB, LDAP, SSH, and TCP, run
against real servers.
enroll.go and systemd.go were already unformatted on main and a blanket
gofmt -w reformatted them into this branch.
Both needed a hand-built environment (local containers on fixed ports, a
SQL Server on EC2) that nobody else can reproduce, so they documented a
verification run rather than testing anything on their own. The phase
behaviour they proved is covered by the self-contained tests.
@bernie-g
bernie-g requested a review from x032205 August 28, 2026 02:31
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.

1 participant