Skip to content

feat(context): retrieve tokens through interactive shell commands - #1531

Open
FelixJacobi wants to merge 2 commits into
hetznercloud:mainfrom
FelixJacobi:feat/credential-helpers
Open

FelixJacobi wants to merge 2 commits into
hetznercloud:mainfrom
FelixJacobi:feat/credential-helpers

Conversation

@FelixJacobi

@FelixJacobi FelixJacobi commented Nov 9, 2026 •

Copy link
Copy Markdown

Contexts currently persist API tokens in cli.toml. This adds an optional per-context token_command so tokens can remain in an external secret store such as Passbolt.

active_context = "production"

[[contexts]]
name = "production"
token_command = "passbolt get resource --id 01234567-89ab-cdef-0123-456789abcdef --field password --raw"

The Passbolt example assumes a version providing those raw-output flags. hcloud accepts any command that prints only its token to stdout, without a credential protocol or response schema.

hcloud context create --token-command '<command>' <name> creates and activates a context without executing the command or storing a token. On Unix the command runs through /bin/sh -c (on Windows, cmd.exe /D /C), inheriting stdin and stderr so interactive passphrase, PIN, and MFA prompts remain available. Only stdout is captured and surrounding whitespace is trimmed.

Tokens are resolved lazily and cached for the client lifecycle. A nonempty HCLOUD_TOKEN takes priority, followed by a nonblank token_command; when no command is configured, the existing stored token is used. Failed commands, empty output, and invalid header characters stop authentication without falling back to a stored token. Configuration inspection, help, and context management do not execute token commands, and resolved tokens never enter configuration output or debug traces.

Includes configuration documentation and regenerated CLI reference documentation. The Git credential protocol, lookup URL, and Python adapter have been removed from this proposal.

Validation:

  • go test ./...
  • go test -race ./internal/state/... ./internal/cmd/context/...
  • Repository-pinned golangci-lint v2.15.0: zero issues
  • CLI build and real pseudo-terminal smoke test: interactive passphrase prompt, inherited stdin/stderr, whitespace trimming, authenticated local API request, debug redaction, no token persistence, context management, and environment override
  • Independent code review: no actionable findings

Only the hcloud side is implemented here; this PR does not modify Passbolt. Live Passbolt integration was not tested.

Implementation and tests were developed with OpenAI Codex assistance.

Support read-only Git credential helpers per context so API tokens can
remain in an external credential store. Resolve tokens lazily, preserve
HCLOUD_TOKEN overrides, and keep retrieved secrets out of config output.

Add a Passbolt adapter example, documentation, and regression coverage.
@FelixJacobi

FelixJacobi commented Nov 9, 2026 •

Copy link
Copy Markdown
Author

After doing some research, I came to the conclusion, that the git credential helper protocol isn't the best choice since it only partly fits the requirements, I would consider something like Process credential provider - AWS SDKs and Tools. A problem is, that there is no proper standard for that.

Replace the Git credential protocol with a per-context token_command.
Capture and trim only stdout while inheriting stdin and stderr so secret
managers can prompt for passphrases and PINs without an adapter.

Keep resolution lazy and cached for the client lifecycle, retain
HCLOUD_TOKEN overrides, and use the stored token when no command is set.
Never persist the resolved token or include it in debug output.

Add parsing, failure, interactive I/O, precedence, and secrecy tests, and
document the new configuration and Passbolt raw-output example.
@FelixJacobi FelixJacobi changed the title feat(context): retrieve tokens through credential helpers feat(context): retrieve tokens through interactive shell commands Nov 9, 2026
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