andrewmusselman opened a new pull request, #646:
URL: https://github.com/apache/tooling-trusted-releases/pull/646

   # Invalidate PATs when user account is disabled
   
   Fixes #598
   
   ## Problem
   
   When an LDAP account is banned or deleted, the user's Personal Access Tokens 
remain in the database. While the existing LDAP check in `issue_jwt()` prevents 
banned users from exchanging PATs for JWTs, the stale tokens persist for up to 
180 days, violating ASVS 7.4.2.
   
   ## Solution
   
   Three layers of defense, two of which are new:
   
   1. **LDAP check at JWT exchange** (already existed) — `issue_jwt()` rejects 
banned users immediately
   2. **Automated background cleanup** (new) — polls LDAP ~hourly and revokes 
PATs for banned/deleted accounts
   3. **Manual admin page** (new) — allows admins to revoke all PATs for a user 
instantly
   
   ## Changes
   
   ### New files
   - `atr/token_cleanup.py` — background cleanup loop with `cleanup_loop()` and 
`revoke_pats_for_banned_users()`
   - `atr/admin/templates/revoke-user-tokens.html` — admin page template
   - `tests/unit/test_token_cleanup.py` — 7 unit tests covering active 
accounts, banned accounts, deleted accounts, LDAP failures, race conditions, 
and multi-user cleanup
   - `tests/e2e/admin/` — e2e tests for the admin revoke tokens page (page 
rendering, form validation, revocation flow, nav link)
   
   ### Modified files
   - `atr/storage/writers/tokens.py` — adds `FoundationAdmin` class with 
`revoke_all_user_tokens()`
   - `atr/storage/__init__.py` — wires `tokens` into `WriteAsFoundationAdmin`
   - `atr/server.py` — starts/stops the cleanup loop task
   - `atr/admin/__init__.py` — adds `RevokeUserTokensForm`, GET/POST route 
handlers
   - `atr/templates/includes/topnav.html` — adds "Revoke user tokens" nav link 
under Admin
   - `atr/docs/authentication-security.md` — documents the three-layer defense 
and automated cleanup
   - `atr/docs/authorization-security.md` — documents admin bulk revocation and 
automated cleanup access control
   
   ## Design decisions
   
   - **Separate module** rather than adding to `cache.py` — `cache.py` is 
solely about LDAP admin caching; token cleanup is active security enforcement. 
A separate module also avoids circular imports (`cache` → `storage` → `user` → 
`cache`).
   - **Per-UID error handling** in the cleanup loop — one LDAP failure doesn't 
block revocation of other users' tokens.
   - **Poll interval offset** (3617s vs 3631s for admin cache) — avoids 
simultaneous LDAP request spikes.
   - **`revoke_pats_for_banned_users()` is public** — directly callable from 
tests and potentially a future "run now" button.
   - **REVOKE confirmation** on the admin form — prevents accidental bulk 
revocation.
   - **All revocations are audit logged** — both automated (via 
`storage.audit()`) and manual (via `append_to_audit_log()`).
   
   ---
   
   ## Required acknowledgements
   
   * [x] I have read and followed **CONTRIBUTING.md**
   * [x] I have read **DEVELOPMENT.md**
   * [x] I have run the required tests and checks locally
   * [x] All required checks are currently passing
   * [x] This branch is **rebased on the current `main` branch**
   
   ---
   
   ## Rebase confirmation details (optional but encouraged)
   
   ```
   $ git fetch upstream main
   From github.com:apache/tooling-trusted-releases
    * branch              main       -> FETCH_HEAD
   $ git rebase upstream/main
   Current branch invalidate-pats-598 is up to date.
   ```
   
   ---
   
   ## Additional notes
   
   * Tested locally, requires REVOKE, lists all users' PATs below
   
   <img width="1260" height="783" alt="image" 
src="https://github.com/user-attachments/assets/240b2513-8f8b-47fd-ae68-91f4b1bcf48b";
 />
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to