fix(postgres): keep the Patroni switchover credential out of curl's argv - #1179
Open
paulocsanz wants to merge 1 commit into
Open
fix(postgres): keep the Patroni switchover credential out of curl's argv#1179paulocsanz wants to merge 1 commit into
paulocsanz wants to merge 1 commit into
Conversation
The switchover authenticates against Patroni's REST API inside the member's container, and since #1171 the credential reached curl as `-u "$PATRONI_REST_USER:$PATRONI_REST_PW"`. Argv is public inside the container: /proc/<pid>/cmdline (ps) shows every process's arguments to every other process in the PID namespace for as long as the request runs, and under the ONE PASSWORD design that argument is the superuser password. Hand curl the credential as a one-line config document on stdin instead (`user = "user:pass"` piped into `curl -K -`), escaped for curl's config parser by a pure-POSIX shell function (`\` and `"` backslashed, newline to `\n`). printf is a builtin of the shells the data images ship (dash, bash), so no process argv carries the secret at any point. Resolution precedence, the bare request for a member with no password, and the error surfacing of Patroni's status and body are unchanged. The sh-shim tests now capture curl's stdin as well as its argv and assert the password is in the document and in no argument; a new test round- trips a password with every character curl's parser treats specially.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
railway postgres ha switchover(src/controllers/patroni.rs) authenticates against Patroni's REST API inside the member's container. Since #1171 the credential reached curl as-u "$PATRONI_REST_USER:$PATRONI_REST_PW". It now reaches curl as a one-line config document on stdin,user = "user:pass"piped intocurl -K -, escaped for curl's config parser by a pure-POSIX shell function (curl_cfg_quote:\and"backslashed, newline to\n).Unchanged: the credential is resolved inside the container from the member's own environment (
PATRONI_RESTAPI_PASSWORD>PATRONI_SUPERUSER_PASSWORD>PGPASSWORD>POSTGRES_PASSWORD; usernamePATRONI_RESTAPI_USERNAME>PATRONI_SUPERUSER_USERNAME>PGUSER>POSTGRES_USER>postgres); a member with no password gets a bare POST (no-K, no document); Patroni's status code and response body surface as the error.Why
HA internal-credential audit (2026-09-08), finding LOW-7 / REPORT-mono-cli Finding 7:
src/controllers/patroni.rs:110on master emitsset -- -u "$PATRONI_REST_USER:$PATRONI_REST_PW", so the password sits in curl's argv for the duration of the request./proc/<pid>/cmdlineis world-readable, so any process in the container's PID namespace (ps) can read the Patroni REST password while a switchover runs, and under the ONE PASSWORD design that is the superuser password. A pipe's stdin is private to its two ends, andprintfis a builtin of the shells the data images ship (dash on the Debian-based postgres image, bash on Oracle Linux), so no process argv carries the secret at any point.How verified
cargo fmt --all --check;cargo test controllers::patroni: 11 passed, on macOS with/bin/shand again withshresolving to dash (CI's ubuntu runner).-uis gone, the document is exactlyuser = "user:pass", the precedence chain and the bare case are unchanged. A new test feeds a password containing",\,$,', space,#, newline and tab and checks the escaped document decodes back to the original under curl's ownunslashquoterules (replicated in the test).-uprelude fail four of five credential tests (document absent, password in argv); only the bare-request test passes.Authorization: Basicheader for the same password in all three shells; the unescaped variant did not.src/controllers/patroni.rs; the repo baseline is untouched.Rollout notes
CLI-only; no image, template or backboard change. Behaviour against enforcing and non-enforcing members is identical apart from where curl reads the credential.
release/patch.