-
Notifications
You must be signed in to change notification settings - Fork 7
infra-feat: harden edge origin trust #430
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Seranged
wants to merge
1
commit into
development
Choose a base branch
from
feature/eul4-211-deepsecinfra-harden-edge-origin-trust-for-api-protections
base: development
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| const KNOWN_DOPPLER_ENVIRONMENTS = new Set(['dev', 'stg', 'prd']) | ||
|
|
||
| function getDopplerEnvironment(): string | undefined { | ||
| return process.env.DOPPLER_ENVIRONMENT?.trim() || undefined | ||
| } | ||
|
|
||
| export function isProductionRuntime(): boolean { | ||
| const dopplerEnvironment = getDopplerEnvironment() | ||
| if (dopplerEnvironment && KNOWN_DOPPLER_ENVIRONMENTS.has(dopplerEnvironment)) { | ||
| return dopplerEnvironment === 'prd' | ||
| } | ||
|
|
||
| return process.env.NODE_ENV === 'production' | ||
| } | ||
|
|
||
| export function isDevelopmentRuntime(): boolean { | ||
| return getDopplerEnvironment() === 'dev' | ||
| } | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,30 @@ | ||
| import type { H3Event } from 'h3' | ||
| import { randomUUID } from 'node:crypto' | ||
|
|
||
| export const INTERNAL_REQUEST_HEADER = 'x-euler-internal-request' | ||
|
|
||
| const INTERNAL_REQUEST_SECRET = process.env.INTERNAL_FETCH_SECRET?.trim() || randomUUID() | ||
|
|
||
| /** | ||
| * Synthetic headers for server-internal $fetch calls. | ||
| * | ||
| * The rate-limit middleware in production (DOPPLER_ENVIRONMENT=prd) fails | ||
| * closed when `cf-connecting-ip` is absent — a Cloudflare egress invariant | ||
| * that keeps direct-to-origin traffic out. The geo-gate middleware | ||
| * likewise fails closed when `cf-ipcountry` is absent. Internal fetches | ||
| * from warm-cache, vaults-cache, etc. don't go through Cloudflare, so | ||
| * without these headers every internal request would be 403'd or 451'd. | ||
| * | ||
| * `cf-connecting-ip` is a fixed loopback sentinel that downstream | ||
| * middleware also uses to identify internal traffic (see isInternalRequest | ||
| * below) — all server-internal traffic shares one rate-limit bucket, which | ||
| * is fine: warm-cache issues at most ~240 requests per 5-min cycle | ||
| * against a >=600/min-per-endpoint budget. | ||
| * Internal fetches from warm-cache, vaults-cache, etc. don't go through | ||
| * Cloudflare, so they have neither `cf-connecting-ip` nor `cf-ipcountry`. | ||
| * This private header lets downstream middleware recognise those calls and | ||
| * skip checks that only make sense for public edge traffic. | ||
| * | ||
| * SECURITY: this sentinel relies on origin ingress NOT being directly | ||
| * reachable — Cloudflare is the only public entrypoint. If that | ||
| * assumption changes (eg a new ingress is exposed), attackers could | ||
| * spoof these headers to bypass rate limiting AND geo-blocking. Do not | ||
| * add the headers to anything that forwards user input into the | ||
| * downstream URL, and keep origin locked behind Cloudflare. | ||
| * The value is either `INTERNAL_FETCH_SECRET` (for deployments that need a | ||
| * shared internal secret across workers) or a process-local random value. | ||
| * The header name is not secret; the value is. | ||
| */ | ||
| export const INTERNAL_FETCH_HEADERS = { 'cf-connecting-ip': '127.0.0.1' } as const | ||
| export const INTERNAL_FETCH_HEADERS = { | ||
| [INTERNAL_REQUEST_HEADER]: INTERNAL_REQUEST_SECRET, | ||
| } as const | ||
|
|
||
| /** | ||
| * True when the incoming request bears the loopback `cf-connecting-ip` | ||
| * sentinel set by `INTERNAL_FETCH_HEADERS`. Middleware uses this to | ||
| * bypass geo/rate checks for warm-cache → `/api/*` traffic that never | ||
| * traversed Cloudflare. Relies on the same origin-locked-behind-CF | ||
| * security invariant noted above. | ||
| * True when the incoming request bears the private internal header set by | ||
| * `INTERNAL_FETCH_HEADERS`. Middleware uses this to bypass geo/rate checks | ||
| * for warm-cache → `/api/*` traffic that never traversed Cloudflare. | ||
| */ | ||
| export const isInternalRequest = (event: H3Event): boolean => | ||
| event.node.req.headers['cf-connecting-ip'] === '127.0.0.1' | ||
| event.node.req.headers[INTERNAL_REQUEST_HEADER] === INTERNAL_REQUEST_SECRET |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.