fix: preserve PostgREST RPC path through DWH proxy
This commit is contained in:
@@ -26,5 +26,5 @@ location /dwh/ {
|
|||||||
# The public ID remains available only to an explicitly sanitized log.
|
# The public ID remains available only to an explicitly sanitized log.
|
||||||
proxy_set_header X-DWH-Key-ID "";
|
proxy_set_header X-DWH-Key-ID "";
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_pass http://127.0.0.1:3001;
|
proxy_pass http://127.0.0.1:3001/;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -382,8 +382,8 @@ Service writes only `RuntimeDirectory=dwh-auth`, reads registry, and has no secr
|
|||||||
- [ ] **Step 5: Add Nginx templates**
|
- [ ] **Step 5: Add Nginx templates**
|
||||||
|
|
||||||
HTTP map/zone rate key contains only remote address plus parsed public ID, never secret; rate is
|
HTTP map/zone rate key contains only remote address plus parsed public ID, never secret; rate is
|
||||||
20/s. Location uses Unix auth, `GET /verify`, no body, clears `X-API-Key` before PostgREST, burst
|
20/s. Location uses Unix auth, `GET /verify`, no body, uses a trailing-slash upstream so public `/dwh/rpc/ping?x` reaches PostgREST as `/rpc/ping?x`, clears `X-API-Key` before PostgREST, burst
|
||||||
100, preserves `/dwh/`, maps auth infrastructure failure to 503.
|
100, keeps the public `/dwh/` authorization boundary while stripping that prefix upstream, maps auth infrastructure failure to 503.
|
||||||
|
|
||||||
- [ ] **Step 6: Prove GREEN**
|
- [ ] **Step 6: Prove GREEN**
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ grep -Fq 'proxy_set_header X-DWH-Key-ID "";' "$location" || die "public key ID i
|
|||||||
[[ $(grep -Fc 'proxy_set_header X-DWH-Key-ID "";' "$location") -eq 1 ]] || die "public key ID must be cleared exactly once"
|
[[ $(grep -Fc 'proxy_set_header X-DWH-Key-ID "";' "$location") -eq 1 ]] || die "public key ID must be cleared exactly once"
|
||||||
grep -Fq 'proxy_pass http://unix:/run/dwh-auth/verify.sock:/verify;' "$location" || die "Unix auth socket is missing"
|
grep -Fq 'proxy_pass http://unix:/run/dwh-auth/verify.sock:/verify;' "$location" || die "Unix auth socket is missing"
|
||||||
grep -Fq 'location /dwh/ {' "$location" || die "DWH prefix location is missing"
|
grep -Fq 'location /dwh/ {' "$location" || die "DWH prefix location is missing"
|
||||||
grep -Fq 'proxy_pass http://127.0.0.1:3001;' "$location" || die "DWH prefix is not preserved"
|
grep -Fq 'proxy_pass http://127.0.0.1:3001/' "$location" || die "DWH prefix is not preserved"
|
||||||
grep -Fq 'limit_req zone=dwh_auth burst=100 nodelay;' "$location" || die "DWH rate limit is missing"
|
grep -Fq 'limit_req zone=dwh_auth burst=100 nodelay;' "$location" || die "DWH rate limit is missing"
|
||||||
grep -Fq 'error_page 500 =503 @dwh_auth_unavailable;' "$location" || die "auth infrastructure failure is not 503"
|
grep -Fq 'error_page 500 =503 @dwh_auth_unavailable;' "$location" || die "auth infrastructure failure is not 503"
|
||||||
grep -Fq 'map $http_x_api_key $dwh_public_key_class' "$http" || die "public rate-key map is missing"
|
grep -Fq 'map $http_x_api_key $dwh_public_key_class' "$http" || die "public rate-key map is missing"
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ check_templates() {
|
|||||||
contains_exactly_once "$dwh_lines" 'proxy_set_header X-API-Key "";' || return 1
|
contains_exactly_once "$dwh_lines" 'proxy_set_header X-API-Key "";' || return 1
|
||||||
contains_exactly_once "$dwh_lines" 'proxy_set_header X-DWH-Key-ID "";' || return 1
|
contains_exactly_once "$dwh_lines" 'proxy_set_header X-DWH-Key-ID "";' || return 1
|
||||||
contains_exactly_once "$dwh_lines" 'proxy_set_header Host $host;' || return 1
|
contains_exactly_once "$dwh_lines" 'proxy_set_header Host $host;' || return 1
|
||||||
contains_exactly_once "$dwh_lines" 'proxy_pass http://127.0.0.1:3001;' || return 1
|
contains_exactly_once "$dwh_lines" 'proxy_pass http://127.0.0.1:3001/;' || return 1
|
||||||
|
|
||||||
contains_exactly_once "$http_lines" 'map $http_x_api_key $dwh_public_key_class {' || return 1
|
contains_exactly_once "$http_lines" 'map $http_x_api_key $dwh_public_key_class {' || return 1
|
||||||
contains_line "$http_lines" 'default opaque;' || return 1
|
contains_line "$http_lines" 'default opaque;' || return 1
|
||||||
@@ -172,7 +172,7 @@ expect_postgrest_regex_bypass_rejected() {
|
|||||||
mkdir -- "$fixture"
|
mkdir -- "$fixture"
|
||||||
cp -- "$http_template" "$fixture/http.conf"
|
cp -- "$http_template" "$fixture/http.conf"
|
||||||
cp -- "$location_template" "$fixture/location.conf"
|
cp -- "$location_template" "$fixture/location.conf"
|
||||||
printf "%s\n" "location ~ ^/dwh/ {" " proxy_pass http://127.0.0.1:3001;" "}" >>"$fixture/location.conf"
|
printf "%s\n" "location ~ ^/dwh/ {" " proxy_pass http://127.0.0.1:3001/;" "}" >>"$fixture/location.conf"
|
||||||
! check_templates "$fixture/http.conf" "$fixture/location.conf"
|
! check_templates "$fixture/http.conf" "$fixture/location.conf"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ expect_postgrest_duplicate_bypass_rejected() {
|
|||||||
mkdir -- "$fixture"
|
mkdir -- "$fixture"
|
||||||
cp -- "$http_template" "$fixture/http.conf"
|
cp -- "$http_template" "$fixture/http.conf"
|
||||||
cp -- "$location_template" "$fixture/location.conf"
|
cp -- "$location_template" "$fixture/location.conf"
|
||||||
printf "%s\n" "location /dwh/ {" " proxy_pass http://127.0.0.1:3001;" "}" >>"$fixture/location.conf"
|
printf "%s\n" "location /dwh/ {" " proxy_pass http://127.0.0.1:3001/;" "}" >>"$fixture/location.conf"
|
||||||
! check_templates "$fixture/http.conf" "$fixture/location.conf"
|
! check_templates "$fixture/http.conf" "$fixture/location.conf"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ probe_body="$temp_root/probe.body"
|
|||||||
expect_status verifier_not_public 404 "$probe_body" 'http://synthetic/_check_dwh_key'
|
expect_status verifier_not_public 404 "$probe_body" 'http://synthetic/_check_dwh_key'
|
||||||
report_pass verifier_not_public
|
report_pass verifier_not_public
|
||||||
|
|
||||||
route_url='http://synthetic/dwh/?keep=exact&second=two'
|
route_url='http://synthetic/dwh/rpc/ping?x=keep&second=two'
|
||||||
expect_status valid_v1 200 "$probe_body" \
|
expect_status valid_v1 200 "$probe_body" \
|
||||||
-H "X-API-Key: $v1_key" \
|
-H "X-API-Key: $v1_key" \
|
||||||
-H 'Cookie: synthetic-session=one' \
|
-H 'Cookie: synthetic-session=one' \
|
||||||
@@ -496,7 +496,7 @@ expect_status valid_v1 200 "$probe_body" \
|
|||||||
[[ $(<"$probe_body") == 'postgrest-marker' ]] || fail_case valid_v1
|
[[ $(<"$probe_body") == 'postgrest-marker' ]] || fail_case valid_v1
|
||||||
report_pass valid_v1
|
report_pass valid_v1
|
||||||
|
|
||||||
expect_status valid_legacy 200 "$probe_body" -H "X-API-Key: $legacy_key" 'http://synthetic/dwh/?legacy=one'
|
expect_status valid_legacy 200 "$probe_body" -H "X-API-Key: $legacy_key" 'http://synthetic/dwh/rpc/ping?legacy=one'
|
||||||
[[ $(<"$probe_body") == 'postgrest-marker' ]] || fail_case valid_legacy
|
[[ $(<"$probe_body") == 'postgrest-marker' ]] || fail_case valid_legacy
|
||||||
report_pass valid_legacy
|
report_pass valid_legacy
|
||||||
|
|
||||||
@@ -554,12 +554,12 @@ assert len(marker) == 2
|
|||||||
assert marker[0] == {
|
assert marker[0] == {
|
||||||
"has_api_key": False,
|
"has_api_key": False,
|
||||||
"has_dwh_key_id": False,
|
"has_dwh_key_id": False,
|
||||||
"path": "/dwh/?keep=exact&second=two",
|
"path": "/rpc/ping?x=keep&second=two",
|
||||||
}
|
}
|
||||||
assert marker[1] == {
|
assert marker[1] == {
|
||||||
"has_api_key": False,
|
"has_api_key": False,
|
||||||
"has_dwh_key_id": False,
|
"has_dwh_key_id": False,
|
||||||
"path": "/dwh/?legacy=one",
|
"path": "/rpc/ping?legacy=one",
|
||||||
}
|
}
|
||||||
PY
|
PY
|
||||||
report_pass header_and_path_isolation
|
report_pass header_and_path_isolation
|
||||||
|
|||||||
Reference in New Issue
Block a user