Skip to content

Allow ESI shared-template caching behind basic auth - #1070

Merged
prk-Jr merged 3 commits into
mainfrom
esi-edge-terminated-auth-main
Aug 28, 2026
Merged

Allow ESI shared-template caching behind basic auth#1070
prk-Jr merged 3 commits into
mainfrom
esi-edge-terminated-auth-main

Conversation

@prk-Jr

@prk-Jr prk-Jr commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Allow ESI shared-template caching when Trusted Server has already validated the request Basic Auth credential at the edge.
  • Preserve the fail-closed bypass for publisher-origin credentials and ambiguous repeated Authorization fields.
  • Carry the server-only authentication decision through all four adapter middleware stacks without modifying the forwarded header.

Changes

File Change
crates/trusted-server-core/src/auth.rs Add the request marker, fail closed on repeated Authorization fields, and add marker lifecycle regressions.
crates/trusted-server-core/src/publisher.rs Exempt exactly one edge-terminated credential from cache bypass and independently reject repeated values.
crates/trusted-server-adapter-fastly/src/middleware.rs Pass the mutable request through Basic Auth middleware.
crates/trusted-server-adapter-axum/src/middleware.rs Pass the mutable request through Basic Auth middleware.
crates/trusted-server-adapter-cloudflare/src/middleware.rs Pass the mutable request through Basic Auth middleware.
crates/trusted-server-adapter-spin/src/middleware.rs Pass the mutable request through Basic Auth middleware.

Test plan

  • cargo test-fastly && cargo test-axum
  • cargo test-cloudflare && cargo test-spin
  • All six target-specific Clippy gates
  • cargo fmt --all -- --check
  • Native core suite: 2,216 tests
  • Regression tests cover pass-through, edge-terminated, and repeated Authorization behavior
  • JS tests
  • JS format
  • Docs format
  • Manual staging validation

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap calls added to production code
  • No println calls added
  • New code has regression tests
  • No secrets or credentials committed

No linked issue for this PR, per request.

@prk-Jr prk-Jr self-assigned this Aug 25, 2026
@ChristianPavilonis ChristianPavilonis changed the title Allow shared templates behind edge-terminated auth Allow ESI shared-template caching behind basic auth Aug 25, 2026
@prk-Jr prk-Jr added this to the 202608 milestone Aug 26, 2026
prk-Jr added a commit that referenced this pull request Aug 26, 2026

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

The edge-auth marker is carried consistently through all four adapters, and the focused cache and authentication tests pass. I found two medium-risk follow-ups around preserving the marker's meaning and documenting the new cache exception. The remaining comments are cleanup nitpicks for the repeated and overly long explanations.

Operator documentation

docs/guide/configuration.md:1612 still says authorization bypasses the template cache unconditionally. It should distinguish pass-through and repeated values, which still bypass, from one edge-validated Basic credential, which may now share a template. Please also document that the credential remains forwarded and that an origin using it must declare Vary: Authorization.

Comment thread crates/trusted-server-core/src/publisher.rs
Comment thread crates/trusted-server-core/src/auth.rs Outdated
Comment thread crates/trusted-server-core/src/publisher.rs Outdated
Comment thread crates/trusted-server-adapter-fastly/src/middleware.rs Outdated

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Allows ESI shared-template caching when Trusted Server itself terminated the request's Basic Auth credential at the edge. The design is sound: the EdgeTerminatedAuthorization marker is unforgeable outside auth.rs (private unit field, cleared on entry, inserted only on the validated path), the publisher gate independently disqualifies repeated Authorization values even when a marker is present, the template-cache key's raw path_and_query is the same raw path the handler regex gated (so every reader of a gated key passed the same first-match handler and credential), and template_fingerprint hashing the complete typed settings means a credential rotation or gate removal rotates every key and orphans gated-era templates. Regression coverage on both sides of the seam is thorough.

1 of the inline comments below carries a one-click GitHub suggestion (use Commit suggestion to apply it as a commit on the PR branch). The remaining comments describe the fix in prose because the change touches lines outside the diff or other files.

Non-blocking

♻️ refactor

  • request_had_authorization no longer means what its name says - see inline at crates/trusted-server-core/src/publisher.rs:4354

🤔 thinking

  • The Vary: Authorization refusal claim is conditional on operator config - see inline at crates/trusted-server-core/src/auth.rs:76-81

⛏ nitpick

  • The handler scoping block is unnecessary and its comment states a borrow constraint that does not exist - see inline at crates/trusted-server-core/src/auth.rs:97-110 (suggestion)

Cross-cutting / body-level findings

  • 🌱 The middleware → router → publisher marker seam is untested end-to-end - auth.rs tests prove the marker is inserted, and the publisher tests inject it with for_test(). The seam between them, extensions surviving ctx.into_request() through each adapter's dispatch path, is exactly the contract the design depends on, and no test exercises it. One adapter dispatch-path test (the fastly app.rs full-dispatch test module or the parity suite already have the scaffolding) asserting that a gated ESI request stores on the cold pass and hits on the warm pass would lock the contract against a future edgezero change that rebuilds the request and drops extensions.

  • 📌 Path-regex basic auth is alias-sensitive, and this PR's premise leans on the gate - pre-existing, not introduced here: handler regexes match the raw path (^/secure does not match /%73ecure/x) while most origins decode, so an unauthenticated request can fetch gated origin content through the proxy under a percent-encoded alias. The shared-template keys also use the raw path, so no stored gated template is readable cross-key and the caching addition itself is safe, but the doc's "every reader able to look up a template has authenticated" premise is only as strong as the gate. Worth a docs note that whole-site staging gates should use an alias-proof pattern (^/), which is the intended use case anyway.

CI Status

  • cargo fmt: PASS (required)
  • cargo test: PASS (required)
  • format-docs: PASS (required)
  • format-typescript: PASS (required)
  • cargo test (axum native): PASS
  • cargo test (cross-adapter parity): PASS
  • cargo test (ts CLI, native): PASS
  • cargo check (cloudflare native + wasm32-unknown-unknown): PASS
  • cargo check/build/test (spin native + wasm32-wasip1): PASS
  • vitest: PASS
  • browser integration tests: PASS
  • integration tests: PASS
  • integration tests (Fastly EC lifecycle): PASS
  • prepare integration artifacts: PASS
  • CodeQL: PASS
  • Analyze (rust): PASS
  • Analyze (actions): PASS
  • Analyze (javascript-typescript): PASS

Comment thread crates/trusted-server-core/src/publisher.rs Outdated
Comment thread crates/trusted-server-core/src/auth.rs
Comment thread crates/trusted-server-core/src/auth.rs Outdated
@prk-Jr

prk-Jr commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the body-level review findings as well:

  • Added a Fastly dispatch-seam regression covering AuthMiddleware → router → publisher cache behavior: cold miss-stored, warm hit, and one origin request.
  • Documented raw-path regex alias sensitivity, including path="^/" for whole-site staging.
  • Clarified Authorization forwarding/cache behavior and prohibited Authorization in template_cache_vary.

Verification completed: Fastly, Axum, Cloudflare, and Spin test suites; integration parity; formatting; and all adapter clippy aliases.

Comment thread crates/trusted-server-core/src/creative_opportunities.rs Dismissed
@prk-Jr
prk-Jr force-pushed the esi-edge-terminated-auth-main branch from 717dccb to 265df48 Compare August 28, 2026 11:20
@prk-Jr
prk-Jr force-pushed the esi-edge-terminated-auth-main branch from 265df48 to 0c47533 Compare August 28, 2026 11:46
@prk-Jr
prk-Jr merged commit b59567b into main Aug 28, 2026
19 checks passed
@prk-Jr
prk-Jr deleted the esi-edge-terminated-auth-main branch August 28, 2026 12:14
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.

4 participants