This is an automated email from the ASF dual-hosted git repository.

vincbeck pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 0ffa24abc6c Clarify that DAG.access_control is only read by the FAB 
auth manager (#71260)
0ffa24abc6c is described below

commit 0ffa24abc6c932d640c56ae40a768d2b9ef44c2b
Author: Stefan Wang <[email protected]>
AuthorDate: Mon Aug 10 07:59:48 2026 -0700

    Clarify that DAG.access_control is only read by the FAB auth manager 
(#71260)
    
    The migration list mapped DAG.access_control to filter_authorized_dag_ids,
    which is a batching helper over is_authorized_dag rather than the place a
    dag-level decision is made, and which the FAB auth manager itself does not
    override. It also read as a relocation, when access_control has no 
successor.
    
    Core has only synced access_control when the auth manager is FAB since 
#48070,
    so under any other auth manager the argument is parsed and serialized but 
never
    consulted. A deployment migrating off FAB silently stops enforcing those 
grants.
---
 .../docs/security/deprecated_permissions.rst         | 20 +++++++++++++++++++-
 task-sdk/src/airflow/sdk/definitions/dag.py          |  7 ++++++-
 task-sdk/tests/task_sdk/definitions/test_dag.py      |  4 +---
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/airflow-core/docs/security/deprecated_permissions.rst 
b/airflow-core/docs/security/deprecated_permissions.rst
index 35334c9c430..00014f12925 100644
--- a/airflow-core/docs/security/deprecated_permissions.rst
+++ b/airflow-core/docs/security/deprecated_permissions.rst
@@ -51,10 +51,28 @@ replacement available from Airflow core:
 
 * ``airflow.security.permissions.ACTION_*`` --> 
``airflow.api_fastapi.auth.managers.base_auth_manager.ResourceMethod``
 * ``airflow.security.permissions.RESOURCE_*`` --> 
``airflow.api_fastapi.auth.managers.models.resource_details``
-* ``DAG.access_control`` --> Dag-level permissions should be handled by the 
chosen Auth Manager's ``filter_authorized_dag_ids`` method.
 
 If you maintain a custom :doc:`/core-concepts/auth-manager/index` which relies 
on the deprecated module, it is
 recommended you refer to the ``SimpleAuthManager``'s `source code 
<https://github.com/apache/airflow/blob/main/airflow-core/src/airflow/api_fastapi/auth/managers/simple/simple_auth_manager.py>`_
 as an example for how you might use the ``ResourceMethod`` and 
``resource_details`` components.
 
 If you rely on custom role definitions based off the deprecated module, you 
should refer to the documentation of the auth manager your system uses.
+
+Migrating ``DAG.access_control``
+--------------------------------
+
+Unlike the components above, ``DAG.access_control`` has no drop-in 
replacement. It was an input to the
+FAB auth manager rather than an authorization mechanism of its own: at parse 
time its contents were
+expanded into that manager's permission tables, and authorization then read 
those tables rather than
+the Dag argument.
+
+.. warning::
+    Airflow only reads ``DAG.access_control`` when the configured auth manager 
is the
+    :doc:`apache-airflow-providers-fab:auth-manager/index`. Under any other 
auth manager the argument is
+    parsed and serialized but never consulted, so it neither grants nor denies 
access. A deployment that
+    moves off the FAB auth manager and leaves ``access_control`` on its Dags 
stops enforcing those grants,
+    and does so without raising an error.
+
+To migrate, move the grants into the policy source your auth manager consults. 
The
+:doc:`/core-concepts/auth-manager/index` guide covers how a custom auth 
manager should express
+Dag-level access.
diff --git a/task-sdk/src/airflow/sdk/definitions/dag.py 
b/task-sdk/src/airflow/sdk/definitions/dag.py
index cadfe697830..633feccb048 100644
--- a/task-sdk/src/airflow/sdk/definitions/dag.py
+++ b/task-sdk/src/airflow/sdk/definitions/dag.py
@@ -392,6 +392,9 @@ class DAG:
         "{'role1': {'can_read'}, 'role2': {'can_read', 'can_edit', 
'can_delete'}}"
         or it can specify the resource name if there is a DAGs Run resource, 
e.g.,
         "{'role1': {'DAG Runs': {'can_create'}}, 'role2': {'DAGs': 
{'can_read', 'can_edit', 'can_delete'}}"
+        Deprecated, and only read when the configured auth manager is the FAB 
auth manager. Under any
+        other auth manager this argument is ignored and grants no access. See
+        
https://airflow.apache.org/docs/apache-airflow/stable/security/deprecated_permissions.html
     :param is_paused_upon_creation: Specifies if the dag is paused when 
created for the first time.
         If the dag exists already, this flag will be ignored. If this optional 
parameter
         is not specified, the global config setting will be used.
@@ -588,7 +591,9 @@ class DAG:
             self.default_args["end_date"] = timezone.convert_to_utc(end_date)
         if self.access_control is not None:
             warnings.warn(
-                "The airflow.security.permissions module is deprecated; please 
see 
https://airflow.apache.org/docs/apache-airflow/stable/security/deprecated_permissions.html";,
+                "DAG.access_control is deprecated and is only read when the 
configured auth manager is the "
+                "FAB auth manager; under any other auth manager it is ignored 
and grants no access. See "
+                
"https://airflow.apache.org/docs/apache-airflow/stable/security/deprecated_permissions.html";,
                 RemovedInAirflow4Warning,
                 stacklevel=2,
             )
diff --git a/task-sdk/tests/task_sdk/definitions/test_dag.py 
b/task-sdk/tests/task_sdk/definitions/test_dag.py
index 9b76816886c..07b8c8186c8 100644
--- a/task-sdk/tests/task_sdk/definitions/test_dag.py
+++ b/task-sdk/tests/task_sdk/definitions/test_dag.py
@@ -185,9 +185,7 @@ class TestDag:
             if len(role_access_control_entry) > 0
             else role_access_control_entry
         )
-        with pytest.warns(
-            RemovedInAirflow4Warning, match=re.escape("The 
airflow.security.permissions module is deprecated")
-        ):
+        with pytest.warns(RemovedInAirflow4Warning, 
match=re.escape("DAG.access_control is deprecated")):
             _ = DAG("should-warn-dag", access_control=access_control, 
schedule=None, start_date=DEFAULT_DATE)
 
     def test_params_not_passed_is_empty_dict(self):

Reply via email to