-
Notifications
You must be signed in to change notification settings - Fork 16.8k
action_logging dependency logs invalid requests before route validation can reject them #64641
Description
Apache Airflow version
main
What happened and how to reproduce it?
While helping someone troubleshoot a CI failure on one of their PRs, I think I may have found an issue with how action_logging works in the FastAPI routes. The API is definitely one of my blind spots so I could be entirely mistaken about this, and I passed my notes and thoughts into Cline/Claude to hep consolidate them into something that hopefully makes sense... so apologies for the blatant LLM formatting but I figure it was better than a bullet list of half-formed thoughts and observations.
I'm hoping someone with real API experience can either verify this is an actual issue or close this. (@pierrejeambrun, @bugraoz93 ??)
The action_logging() decorator is registered as a FastAPI Depends() on several routes (variables, connections, pools, etc.). Because FastAPI evaluates dependencies before executing the route function body, the audit log entry is written and committed before the route has a chance to validate the request.
This means that requests which will be rejected (providing team_name when multi_team is disabled was the example that led to this, for example) still produce an audit log entry with session.commit(). This has two consequences:
- Incorrect audit trail — rejected/invalid requests appear in the audit log as if they were attempted actions
- SQLite lock conflicts in tests — the eager
session.commit()in the logging dependency can collide with other sessions that hold write locks (I think this was the root cause of adatabase is lockedtest failure in Feat/check multi team enabled when team name provided api #63994)
Where the problem lives:
airflow-core/src/airflow/api_fastapi/logging/decorators.py— thelog_actioninner function (returned byaction_logging()) creates aLogobject and callssession.commit()unconditionally at the end- All routes that use
dependencies=[..., Depends(action_logging()), ...]are affected
Affected routes (non-exhaustive):
POST /variablesandPATCH /variables/{key}POST /connectionsandPATCH /connections/{connection_id}POST /poolsandPATCH /pools/{pool_name}- (and others — search for
Depends(action_logging()))
Claude's suggested fix (someone with better API background needs to confirm this is a good idea first):
Move request validation checks (like the multi_team check) into their own FastAPI dependency that runs before action_logging(). This way invalid requests are rejected before any audit log entry is created. For example:
# Current (validation happens in route body, AFTER action_logging fires):
@router.post(
"",
dependencies=[Depends(action_logging()), Depends(requires_access_variable("POST"))],
)
def post_variable(post_body: ..., session: SessionDep):
if post_body.team_name is not None and not conf.getboolean("core", "multi_team"):
raise HTTPException(400, "team_name cannot be set when multi_team mode is disabled.")
...
# Proposed (validation runs as a dependency, BEFORE action_logging):
def validate_team_name_allowed(request: Request):
"""Reject requests that include team_name when multi_team is disabled."""
# Only check for methods that accept a body
if request.method in ("POST", "PATCH", "PUT"):
body = await request.json()
if body.get("team_name") is not None and not conf.getboolean("core", "multi_team"):
raise HTTPException(400, "team_name cannot be set when multi_team mode is disabled.")
@router.post(
"",
dependencies=[
Depends(validate_team_name_allowed), # runs first
Depends(action_logging()),
Depends(requires_access_variable("POST")),
],
)
def post_variable(post_body: ..., session: SessionDep):
...Alternatively, the action_logging decorator itself could be made conditional — only commit the log if the route succeeds — but that's a bigger change with wider implications for the audit trail design.
What you think should happen instead?
No response
Operating System
No response
Versions of Apache Airflow Providers
No response
Deployment
None
Deployment details
No response
Anything else?
No response
Are you willing to submit PR?
- Yes I am willing to submit a PR!
Code of Conduct
- I agree to follow this project's Code of Conduct