This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
The following commit(s) were added to refs/heads/main by this push:
new ecfb15f Manage the server secret key using ASFQuart
ecfb15f is described below
commit ecfb15fe0c486439666f6324e5baa385ee1362bb
Author: Sean B. Palmer <[email protected]>
AuthorDate: Fri Jan 16 20:24:50 2026 +0000
Manage the server secret key using ASFQuart
---
Makefile | 8 +++----
atr/config.py | 9 ++++++--
atr/server.py | 59 +++++++++++++++++++++++++++++-------------------
docker-compose.yml | 1 -
tests/docker-compose.yml | 2 --
5 files changed, 47 insertions(+), 32 deletions(-)
diff --git a/Makefile b/Makefile
index b251086..bfbc4f8 100644
--- a/Makefile
+++ b/Makefile
@@ -96,8 +96,8 @@ run-alpine:
-v "$$PWD/$(STATE_DIR):/opt/atr/state" \
-v
"$$PWD/$(STATE_DIR)/localhost.apache.org+2-key.pem:/opt/atr/state/key.pem" \
-v
"$$PWD/$(STATE_DIR)/localhost.apache.org+2.pem:/opt/atr/state/cert.pem" \
- -e APP_HOST=localhost.apache.org:8080 -e
SECRET_KEY=insecure-local-key \
- -e ALLOW_TESTS=1 -e SSH_HOST=0.0.0.0 -e BIND=0.0.0.0:8080 \
+ -e APP_HOST=localhost.apache.org:8080 -e ALLOW_TESTS=1 \
+ -e SSH_HOST=0.0.0.0 -e BIND=0.0.0.0:8080 \
tooling-trusted-release
run-playwright:
@@ -112,8 +112,8 @@ serve:
atr.server:app --debug --reload --worker-class uvloop
serve-local:
- APP_HOST=localhost.apache.org:8080 SECRET_KEY=insecure-local-key
DISABLE_CHECK_CACHE=1 \
- ALLOW_TESTS=1 SSH_HOST=127.0.0.1 uv run --frozen hypercorn --bind
$(BIND) \
+ APP_HOST=localhost.apache.org:8080 DISABLE_CHECK_CACHE=1 ALLOW_TESTS=1 \
+ SSH_HOST=127.0.0.1 uv run --frozen hypercorn --bind $(BIND) \
--keyfile localhost.apache.org+2-key.pem --certfile
localhost.apache.org+2.pem \
atr.server:app --debug --reload --worker-class uvloop
diff --git a/atr/config.py b/atr/config.py
index 94f5421..844d80a 100644
--- a/atr/config.py
+++ b/atr/config.py
@@ -63,8 +63,13 @@ class AppConfig:
DEBUG = False
TEMPLATES_AUTO_RELOAD = False
USE_BLOCKBUSTER = False
- JWT_SECRET_KEY = _config_secrets("JWT_SECRET_KEY", STATE_DIR,
default=None, cast=str) or secrets.token_hex(128 // 8)
- SECRET_KEY = _config_secrets("SECRET_KEY", STATE_DIR, default=None,
cast=str) or secrets.token_hex(128 // 8)
+ JWT_SECRET_KEY = _config_secrets("JWT_SECRET_KEY", STATE_DIR,
default=None, cast=str) or secrets.token_hex(256 // 8)
+ # We no longer support SECRET_KEY
+ # We continue to read the value to print a migration warning
+ # We are now relying on apptoken.txt from ASFQuart instead
+ # By default, apptoken.txt is a 256 bit random value
+ # ASFQuart generates it using secrets.token_hex()
+ SECRET_KEY = _config_secrets("SECRET_KEY", STATE_DIR, default=None,
cast=str)
DOWNLOADS_STORAGE_DIR = os.path.join(STATE_DIR, "downloads")
FINISHED_STORAGE_DIR = os.path.join(STATE_DIR, "finished")
UNFINISHED_STORAGE_DIR = os.path.join(STATE_DIR, "unfinished")
diff --git a/atr/server.py b/atr/server.py
index 5859c72..092a557 100644
--- a/atr/server.py
+++ b/atr/server.py
@@ -119,17 +119,18 @@ def _app_create_base(app_config: type[config.AppConfig])
-> base.QuartApp:
return app
-def _app_dirs_setup(app_config: type[config.AppConfig]) -> None:
+def _app_dirs_setup(state_dir_str: str, hot_reload: bool) -> None:
"""Setup application directories."""
- if not os.path.isdir(app_config.STATE_DIR):
- raise RuntimeError(f"State directory not found:
{app_config.STATE_DIR}")
- os.chdir(app_config.STATE_DIR)
- print(f"Working directory changed to: {os.getcwd()}")
+ if not os.path.isdir(state_dir_str):
+ raise RuntimeError(f"State directory not found: {state_dir_str}")
+ os.chdir(state_dir_str)
+ if hot_reload is False:
+ print(f"Working directory changed to: {os.getcwd()}")
directories_to_ensure = [
- pathlib.Path(app_config.STATE_DIR) / "audit",
- pathlib.Path(app_config.STATE_DIR) / "cache",
- pathlib.Path(app_config.STATE_DIR) / "database",
+ pathlib.Path(state_dir_str) / "audit",
+ pathlib.Path(state_dir_str) / "cache",
+ pathlib.Path(state_dir_str) / "database",
util.get_downloads_dir(),
util.get_finished_dir(),
util.get_tmp_dir(),
@@ -411,18 +412,10 @@ def _create_app(app_config: type[config.AppConfig]) ->
base.QuartApp:
if os.sep != "/":
raise RuntimeError('ATR requires a POSIX compatible filesystem where
os.sep is "/"')
config_mode = config.get_mode()
-
- # Custom configuration for the database path is no longer supported
- configured_path = app_config.SQLITE_DB_PATH
- if configured_path != "database/atr.db":
- print("!!!", file=sys.stderr)
- print("ERROR: Custom values of SQLITE_DB_PATH are no longer
supported!", file=sys.stderr)
- print("Please unset SQLITE_DB_PATH to allow the server to start",
file=sys.stderr)
- print("!!!", file=sys.stderr)
- sys.exit(1)
-
- _migrate_state(app_config)
- _app_dirs_setup(app_config)
+ hot_reload = _is_hot_reload()
+ _validate_config(app_config, hot_reload)
+ _migrate_state(app_config.STATE_DIR, hot_reload)
+ _app_dirs_setup(app_config.STATE_DIR, hot_reload)
log.performance_init()
app = _app_create_base(app_config)
@@ -592,9 +585,9 @@ def _migrate_path_by_type(old_path: pathlib.Path, new_path:
pathlib.Path) -> Non
raise RuntimeError(f"Migration path is neither a file nor a directory:
{old_path}")
-def _migrate_state(app_config: type[config.AppConfig]) -> None:
+def _migrate_state(state_dir_str: str, hot_reload: bool) -> None:
# It's okay to use synchronous code in this function and in any functions
that it calls
- state_dir = pathlib.Path(app_config.STATE_DIR)
+ state_dir = pathlib.Path(state_dir_str)
# Are there migrations to apply?
pending_migrations = _pending_migrations(state_dir)
@@ -602,7 +595,7 @@ def _migrate_state(app_config: type[config.AppConfig]) ->
None:
return
# Are we hot reloading?
- if _is_hot_reload():
+ if hot_reload is True:
print("!!!", file=sys.stderr)
print("ERROR: Cannot migrate files during hot reload!",
file=sys.stderr)
print("The following files need to be migrated:", file=sys.stderr)
@@ -694,6 +687,26 @@ def _register_routes(app: base.QuartApp) -> None:
return await template.render("notfound.html", error="404 Not Found",
traceback="", status_code=404), 404
+def _validate_config(app_config: type[config.AppConfig], hot_reload: bool) ->
None:
+ # Custom configuration for the database path is no longer supported
+ configured_path = app_config.SQLITE_DB_PATH
+ if configured_path != "database/atr.db":
+ print("!!!", file=sys.stderr)
+ print("ERROR: Custom values of SQLITE_DB_PATH are no longer
supported!", file=sys.stderr)
+ print("Please unset SQLITE_DB_PATH to allow the server to start",
file=sys.stderr)
+ print("!!!", file=sys.stderr)
+ sys.exit(1)
+
+ # Configuring the SECRET_KEY outside of ASFQuart is no longer supported
+ if (app_config.SECRET_KEY is not None) and (hot_reload is False):
+ print("!!!", file=sys.stderr)
+ print("WARNING: SECRET_KEY is no longer supported", file=sys.stderr)
+ print("Please unset SECRET_KEY", file=sys.stderr)
+ print("We are considering making this mandatory", file=sys.stderr)
+ print("!!!", file=sys.stderr)
+ # sys.exit(1)
+
+
if __name__ == "__main__":
main()
else:
diff --git a/docker-compose.yml b/docker-compose.yml
index 0e4044f..609501e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,7 +7,6 @@ services:
- ALLOW_TESTS=1
- APP_HOST=atr:8080
- BIND=0.0.0.0:8080
- - SECRET_KEY=insecure-test-key
- SSH_HOST=0.0.0.0
- LDAP_BIND_DN=$LDAP_BIND_DN
- LDAP_BIND_PASSWORD=$LDAP_BIND_PASSWORD
diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml
index cd0027c..8a2d400 100644
--- a/tests/docker-compose.yml
+++ b/tests/docker-compose.yml
@@ -7,7 +7,6 @@ services:
- ALLOW_TESTS=1
- APP_HOST=atr:8080
- BIND=0.0.0.0:8080
- - SECRET_KEY=insecure-test-key
- SSH_HOST=0.0.0.0
networks:
- test-network
@@ -26,7 +25,6 @@ services:
- ALLOW_TESTS=1
- APP_HOST=atr-dev:8080
- BIND=0.0.0.0:8080
- - SECRET_KEY=insecure-test-key
- SSH_HOST=0.0.0.0
networks:
- test-network
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]