fix: enforce server trust boundaries
This commit is contained in:
@@ -100,6 +100,41 @@ sed '/^case "\$mode" in/,$d' "$root/scripts/verify-workspace-install-docs.sh" >"
|
||||
# shellcheck source=/dev/null
|
||||
source "$verifier_functions"
|
||||
|
||||
adapted_reorder="$negative_root/caddy-adapted-reorder.json"
|
||||
node - "$adapted_reorder" <<'NODE'
|
||||
const fs = require("fs");
|
||||
const publicHeaders = [
|
||||
"X-Thoth-Principal-Issuer", "X-Thoth-Principal-Subject",
|
||||
"X-Thoth-Principal-Display-Name", "X-Thoth-Is-Admin",
|
||||
];
|
||||
const trustedHeaders = [
|
||||
"X-Thoth-Trusted-Principal-Issuer", "X-Thoth-Trusted-Principal-Subject",
|
||||
"X-Thoth-Trusted-Principal-Display-Name", "X-Thoth-Trusted-Is-Admin",
|
||||
];
|
||||
const clear = (name) => ({handler: "headers", request: {delete: [name]}});
|
||||
const auth = {
|
||||
handler: "reverse_proxy", upstreams: [{dial: "auth-gateway:4180"}],
|
||||
handle_response: [{match: {status_code: [2]}, routes: [{handle: trustedHeaders.map((name, index) => ({
|
||||
handler: "headers", request: {set: {[name]: [`{http.reverse_proxy.header.${publicHeaders[index]}}`]}},
|
||||
}))}]}],
|
||||
};
|
||||
const document = {routes: [{handle: [
|
||||
...publicHeaders.map(clear), auth, ...trustedHeaders.map(clear),
|
||||
{handler: "reverse_proxy", upstreams: [{dial: "127.0.0.1:8080"}]},
|
||||
]}]};
|
||||
fs.writeFileSync(process.argv[2], JSON.stringify(document));
|
||||
NODE
|
||||
adapted_output="$negative_root/caddy-adapted-output"
|
||||
set +e
|
||||
verify_caddy_adapted_identity_order "$adapted_reorder" >"$adapted_output" 2>&1
|
||||
adapted_status=$?
|
||||
set -e
|
||||
if [[ $adapted_status -eq 0 ]] || ! grep -Fq "Caddy adapted identity clears must execute before authentication" "$adapted_output"; then
|
||||
echo "Caddy reordered adapted-handler fixture was not rejected correctly" >&2
|
||||
cat "$adapted_output" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
negative_failures=0
|
||||
expect_guide_rejected() {
|
||||
local label="$1" validator="$2" source_guide="$3" relative_path="$4"
|
||||
@@ -175,6 +210,14 @@ switch (mutation) {
|
||||
case "nginx-no-admin-map":
|
||||
changed = original.replace("proxy_set_header X-Thoth-Trusted-Is-Admin $thoth_is_admin;", "proxy_set_header X-Thoth-Trusted-Is-Admin \"\";");
|
||||
break;
|
||||
case "nginx-admin-clear-wrong-scope": {
|
||||
const clear = ' proxy_set_header X-Thoth-Is-Admin "";';
|
||||
const authAt = original.indexOf(clear);
|
||||
changed = original.slice(0, authAt) + original.slice(authAt + clear.length + 1);
|
||||
const frontendAt = changed.indexOf(clear);
|
||||
changed = changed.slice(0, frontendAt) + clear + "\n" + clear + changed.slice(frontendAt + clear.length);
|
||||
break;
|
||||
}
|
||||
case "caddy-no-auth":
|
||||
changed = original.replace("forward_auth auth-gateway:4180 {", "# forward authentication omitted");
|
||||
break;
|
||||
@@ -196,6 +239,13 @@ switch (mutation) {
|
||||
case "caddy-no-admin-map":
|
||||
changed = original.replace("X-Thoth-Is-Admin>X-Thoth-Trusted-Is-Admin", "X-Thoth-Is-Admin");
|
||||
break;
|
||||
case "caddy-clears-after-auth": {
|
||||
const clearPattern = /(?:\t\trequest_header -X-(?:Authenticated-User|Thoth-[^\n]+)\n)+/;
|
||||
const clears = original.match(clearPattern)?.[0] || "";
|
||||
changed = original.replace(clearPattern, "");
|
||||
changed = changed.replace("\n\t\treverse_proxy 127.0.0.1:8080 {", "\n" + clears + "\n\t\treverse_proxy 127.0.0.1:8080 {");
|
||||
break;
|
||||
}
|
||||
case "dirty-source":
|
||||
changed = original.replaceAll("git status --porcelain --untracked-files=all", "git status --short");
|
||||
break;
|
||||
@@ -310,19 +360,23 @@ expect_guide_rejected \
|
||||
expect_guide_rejected \
|
||||
"Nginx issuer inbound claim not cleared" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-issuer-clear \
|
||||
"Nginx proxy does not clear inbound issuer identity"
|
||||
"Nginx auth location does not clear inbound issuer identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx subject auth response not captured" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-subject-capture \
|
||||
"Nginx proxy does not capture authenticated subject identity"
|
||||
"Nginx frontend location does not capture authenticated subject identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx display identity not mapped to private hop" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-display-map \
|
||||
"Nginx proxy does not map authenticated display identity"
|
||||
"Nginx frontend location does not map authenticated display identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx admin identity not mapped to private hop" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-no-admin-map \
|
||||
"Nginx proxy does not map authenticated admin identity"
|
||||
"Nginx frontend location does not map authenticated admin identity"
|
||||
expect_guide_rejected \
|
||||
"Nginx admin clear moved out of auth scope" verify_reverse_proxy_nginx_guide \
|
||||
"$root/docs/install/reverse-proxy-nginx.md" docs/install/reverse-proxy-nginx.md nginx-admin-clear-wrong-scope \
|
||||
"Nginx auth location does not clear inbound admin identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy identity without authentication" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-auth \
|
||||
@@ -351,6 +405,10 @@ expect_guide_rejected \
|
||||
"Caddy admin identity not mapped to private hop" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-no-admin-map \
|
||||
"Caddy proxy does not map authenticated admin identity"
|
||||
expect_guide_rejected \
|
||||
"Caddy identity clears reordered after auth" verify_reverse_proxy_caddy_guide \
|
||||
"$root/docs/install/reverse-proxy-caddy.md" docs/install/reverse-proxy-caddy.md caddy-clears-after-auth \
|
||||
"Caddy identity clears must precede forward_auth"
|
||||
|
||||
expect_guide_rejected \
|
||||
"dirty or untracked source tree" verify_local_guide \
|
||||
|
||||
Reference in New Issue
Block a user