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 4890e73  Ensure that the permissions of secret files are correct
4890e73 is described below

commit 4890e73bd157c12f046e89f76bdb2d76dc80c03a
Author: Sean B. Palmer <[email protected]>
AuthorDate: Tue Jan 20 16:08:39 2026 +0000

    Ensure that the permissions of secret files are correct
---
 Makefile                      |  4 +++-
 atr/server.py                 | 29 +++++++++++++++++++++++++++++
 scripts/check-perms           | 15 +++++++++++++++
 scripts/generate-certificates |  3 ++-
 start-atr.sh                  |  3 +++
 5 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index dc2db7f..0269972 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ certs:
 
 certs-local:
        mkdir -p $(STATE_DIR)/hypercorn/secrets
-       cd $(STATE_DIR)/hypercorn/secrets && mkcert localhost.apache.org 
127.0.0.1 ::1
+       cd $(STATE_DIR)/hypercorn/secrets && umask 277 && mkcert 
localhost.apache.org 127.0.0.1 ::1
 
 check:
        git add -A
@@ -108,6 +108,7 @@ run-playwright-slow:
 
 serve:
        @scripts/check-certs
+       @scripts/check-perms
        SSH_HOST=127.0.0.1 uv run --frozen hypercorn --bind $(BIND) \
          --keyfile hypercorn/secrets/localhost.apache.org+2-key.pem \
          --certfile hypercorn/secrets/localhost.apache.org+2.pem \
@@ -115,6 +116,7 @@ serve:
 
 serve-local:
        @scripts/check-certs
+       @scripts/check-perms
        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 hypercorn/secrets/localhost.apache.org+2-key.pem \
diff --git a/atr/server.py b/atr/server.py
index c149b59..b52bcfe 100644
--- a/atr/server.py
+++ b/atr/server.py
@@ -25,6 +25,7 @@ import multiprocessing
 import os
 import pathlib
 import queue
+import stat
 import sys
 import urllib.parse
 from collections.abc import Iterable
@@ -433,6 +434,7 @@ def _create_app(app_config: type[config.AppConfig]) -> 
base.QuartApp:
     _validate_config(app_config, hot_reload)
     _migrate_state(app_config.STATE_DIR, hot_reload)
     _app_dirs_setup(app_config.STATE_DIR, hot_reload)
+    _validate_secrets_permissions(pathlib.Path(app_config.STATE_DIR))
     log.performance_init()
     app = _app_create_base(app_config)
 
@@ -724,6 +726,33 @@ def _validate_config(app_config: type[config.AppConfig], 
hot_reload: bool) -> No
         # sys.exit(1)
 
 
+def _validate_secrets_permissions(state_dir: pathlib.Path) -> None:
+    secrets_dirs = [
+        state_dir / "secrets",
+        state_dir / "hypercorn" / "secrets",
+    ]
+    incorrect_files: list[tuple[pathlib.Path, int, int]] = []
+
+    for secrets_dir in secrets_dirs:
+        if not secrets_dir.exists():
+            continue
+        for path in secrets_dir.rglob("*"):
+            if not path.is_file():
+                continue
+            mode = stat.S_IMODE(path.stat().st_mode)
+            expected = 0o600 if (path.name == "apptoken.txt") else 0o400
+            if mode != expected:
+                incorrect_files.append((path, mode, expected))
+
+    if incorrect_files:
+        print("!!!", file=sys.stderr)
+        print("ERROR: Secrets files have incorrect permissions", 
file=sys.stderr)
+        for path, mode, expected in incorrect_files:
+            print(f"  {path}: {oct(mode)} (expected {oct(expected)})", 
file=sys.stderr)
+        print("!!!", file=sys.stderr)
+        sys.exit(1)
+
+
 if __name__ == "__main__":
     raise RuntimeError("Call hypercorn directly with atr.server:app instead")
 else:
diff --git a/scripts/check-perms b/scripts/check-perms
new file mode 100755
index 0000000..c54a83a
--- /dev/null
+++ b/scripts/check-perms
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -eu
+
+STATE_DIR="${STATE_DIR:-state}"
+
+if [ -d "$STATE_DIR/hypercorn/secrets" ]
+then
+  find "$STATE_DIR/hypercorn/secrets" -type f -exec chmod 400 {} +
+fi
+
+if [ -d "$STATE_DIR/secrets" ]
+then
+  find "$STATE_DIR/secrets" -type f ! -name "apptoken.txt" -exec chmod 400 {} +
+  find "$STATE_DIR/secrets" -type f -name "apptoken.txt" -exec chmod 600 {} +
+fi
diff --git a/scripts/generate-certificates b/scripts/generate-certificates
index bf183f8..bc2b4e9 100755
--- a/scripts/generate-certificates
+++ b/scripts/generate-certificates
@@ -50,7 +50,8 @@ def generate_self_signed_cert() -> None:
         .sign(key, hashes.SHA256())
     )
 
-    # Write out the private key
+    # Write out the private key with 400 permissions
+    os.umask(0o277)
     with open(KEY_PATH, "wb") as f:
         f.write(
             key.private_bytes(
diff --git a/start-atr.sh b/start-atr.sh
index 643742c..f886b1c 100755
--- a/start-atr.sh
+++ b/start-atr.sh
@@ -12,6 +12,9 @@ then
   python3 scripts/generate-certificates
 fi
 
+# Ensure that the permissions of secret files are correct
+STATE_DIR=state scripts/check-perms
+
 mkdir -p /opt/atr/state/hypercorn/logs
 echo "Starting hypercorn on ${BIND}" >> 
/opt/atr/state/hypercorn/logs/hypercorn.log
 exec hypercorn --worker-class uvloop --bind "${BIND}" \


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to