mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
fix(seed): run psql with -X so psqlrc cannot retarget after the local guard
psql -c no longer implies -X, so ~/.psqlrc or PSQLRC (exportable from .env) ran after the guard and could \connect to another host. Pass -X on both the local and Docker psql paths and assert the control invocation carries it. Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -2323,7 +2323,11 @@ fn admin_seed_refuses_remote_database_before_invoking_psql() {
|
||||
)
|
||||
.expect("copy script without developer .env");
|
||||
let psql = root.join("psql");
|
||||
std::fs::write(&psql, "#!/bin/sh\ntouch \"$SEED_PSQL_WITNESS\"\nexit 1\n").expect("stub psql");
|
||||
std::fs::write(
|
||||
&psql,
|
||||
"#!/bin/sh\nprintf '%s\\n' \"$@\" > \"$SEED_PSQL_WITNESS\"\nexit 1\n",
|
||||
)
|
||||
.expect("stub psql");
|
||||
std::fs::set_permissions(&psql, std::fs::Permissions::from_mode(0o755))
|
||||
.expect("executable stub");
|
||||
let witness = root.join("psql-was-invoked");
|
||||
@@ -2338,15 +2342,16 @@ fn admin_seed_refuses_remote_database_before_invoking_psql() {
|
||||
.env("SEED_PSQL_WITNESS", &witness)
|
||||
.output()
|
||||
.expect("run local seed guard");
|
||||
let invoked = witness.exists();
|
||||
if invoked {
|
||||
let args = std::fs::read_to_string(&witness).ok();
|
||||
if args.is_some() {
|
||||
std::fs::remove_file(&witness).expect("clear witness");
|
||||
}
|
||||
(output, invoked)
|
||||
(output, args)
|
||||
};
|
||||
// Control: a local host with a plain database name reaches psql, so the
|
||||
// refusals below come from the guard rather than an unrunnable fixture.
|
||||
let (_, control_invoked) = run("localhost", "", "", "buzz");
|
||||
// It must also pass -X so a psqlrc cannot \connect after the guard.
|
||||
let (_, control_args) = run("localhost", "", "", "buzz");
|
||||
let cases = [
|
||||
("remote host", "shared-db.example.invalid", "", "", ""),
|
||||
("address override", "localhost", "192.0.2.1", "", ""),
|
||||
@@ -2402,11 +2407,15 @@ fn admin_seed_refuses_remote_database_before_invoking_psql() {
|
||||
),
|
||||
];
|
||||
let results = cases.map(|(name, host, address, service, database)| {
|
||||
let (output, invoked) = run(host, address, service, database);
|
||||
(name, output, invoked)
|
||||
let (output, args) = run(host, address, service, database);
|
||||
(name, output, args.is_some())
|
||||
});
|
||||
std::fs::remove_dir_all(root).expect("remove scratch fixture");
|
||||
assert!(control_invoked, "plain local target did not reach psql");
|
||||
let control_args = control_args.expect("plain local target did not reach psql");
|
||||
assert!(
|
||||
control_args.lines().any(|arg| arg == "-X"),
|
||||
"psql invoked without -X: {control_args:?}"
|
||||
);
|
||||
for (name, output, invoked) in results {
|
||||
assert!(!invoked, "{name} reached psql");
|
||||
assert!(!output.status.success(), "{name} accepted");
|
||||
|
||||
@@ -38,15 +38,16 @@ if [[ ! "${PGDATABASE}" =~ ^[A-Za-z0-9_-]+$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# -X skips psqlrc, which runs after this guard and could \connect elsewhere.
|
||||
if command -v psql >/dev/null 2>&1; then
|
||||
run_psql() {
|
||||
PGPASSWORD="${PGPASSWORD}" psql -h "${PGHOST}" -p "${PGPORT}" \
|
||||
PGPASSWORD="${PGPASSWORD}" psql -X -h "${PGHOST}" -p "${PGPORT}" \
|
||||
-U "${PGUSER}" -d "${PGDATABASE}" "$@"
|
||||
}
|
||||
elif docker exec buzz-postgres psql --version >/dev/null 2>&1; then
|
||||
run_psql() {
|
||||
docker exec -i -e PGPASSWORD="${PGPASSWORD}" buzz-postgres \
|
||||
psql -U "${PGUSER}" -d "${PGDATABASE}" "$@"
|
||||
psql -X -U "${PGUSER}" -d "${PGDATABASE}" "$@"
|
||||
}
|
||||
else
|
||||
echo "error: neither psql nor buzz-postgres docker psql is available" >&2
|
||||
|
||||
Reference in New Issue
Block a user