-
Notifications
You must be signed in to change notification settings - Fork 11
perf+security+test: deferred audit follow-ups (health growth, first-run token, orchestrator coverage) #100
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4736035
perf(db): bound health_events growth — split retention + weekly VACUUM
GeiserX 42a1e49
test: cover orchestrator/worker_api Docker paths; expect db_vacuum job
GeiserX 1812260
feat(security): setup-token gate for first-run + trusted-proxy client IP
GeiserX efe0ada
fix(db): restore health-retention split + VACUUM lost in rebase; cove…
GeiserX f78c323
fix(security): don't accept first-run setup token via query string (C…
GeiserX 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| """First-run setup-token gate. | ||
|
|
||
| The very first account created on a fresh install becomes the ``owner``. The | ||
| private-network check in :mod:`app.deps` is not enough on its own: behind a | ||
| reverse proxy ``request.client`` is the *proxy* (a loopback/private address), so | ||
| the network check always passes and the first person to reach ``/register`` from | ||
| the public internet could seize the owner account. | ||
|
|
||
| This module adds a proxy-independent second factor: a one-time token generated at | ||
| startup while no users exist, printed to the container logs. Only someone who can | ||
| read the server logs (i.e. already has host access) can complete first-run setup. | ||
| Once the owner account is created the token is cleared and never required again | ||
| (further users are added by an authenticated owner). | ||
|
|
||
| The active token is held in a module global so the synchronous request guard can | ||
| check it without a DB round-trip; it is also persisted in the ``config`` table so | ||
| it survives restarts until consumed. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import hmac | ||
| import secrets | ||
|
|
||
| # The token currently required for first-run registration, or ``None`` when no | ||
| # first-run gate is active (owner already exists, or not yet initialised). | ||
| _active: str | None = None | ||
|
|
||
|
|
||
| def generate() -> str: | ||
| """Return a fresh, URL-safe setup token.""" | ||
| return secrets.token_urlsafe(24) | ||
|
|
||
|
|
||
| def set_active(token: str | None) -> None: | ||
| """Install (or clear, with ``None``) the token required for first-run setup.""" | ||
| global _active | ||
| _active = token or None | ||
|
|
||
|
|
||
| def clear() -> None: | ||
| """Drop the first-run gate — called once the owner account exists.""" | ||
| set_active(None) | ||
|
|
||
|
|
||
| def active() -> str | None: | ||
| """Return the currently required setup token, or ``None`` if none is active.""" | ||
| return _active | ||
|
|
||
|
|
||
| def verify(provided: str | None) -> bool: | ||
| """Check a caller-supplied token against the active one. | ||
|
|
||
| Returns ``True`` when no token is active (nothing to enforce) or when the | ||
| supplied value matches in constant time; ``False`` otherwise. | ||
| """ | ||
| current = _active | ||
| if current is None: | ||
| return True | ||
| if not provided: | ||
| return False | ||
| return hmac.compare_digest(current, provided) |
Oops, something went wrong.
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.