diff --git a/providers/src/airflow/providers/fab/CHANGELOG.rst b/providers/src/airflow/providers/fab/CHANGELOG.rst index ae427ca3b029f..b878a96c054d8 100644 --- a/providers/src/airflow/providers/fab/CHANGELOG.rst +++ b/providers/src/airflow/providers/fab/CHANGELOG.rst @@ -31,6 +31,20 @@ Breaking changes It is impossible to use ``apache-airflow-providers-fab`` >= 2.0 with Airflow 2.X. If you use Airflow 2.X, please use ``apache-airflow-providers-fab`` 1.X. +.. warning:: + All deprecated classes, parameters and features have been removed from the Fab provider package. + The following breaking changes were introduced: + + * Removed ``is_authorized_dataset`` method from ``FabAuthManager``. Use ``is_authorized_asset`` instead + * Removed ``oauth_whitelists`` property from the security manager override. Use ``oauth_allow_list`` instead + * Removed the authentication type ``AUTH_OID`` + * Removed ``get_readable_dags`` method from the security manager override + * Removed ``get_editable_dags`` method from the security manager override + * Removed ``get_accessible_dags`` method from the security manager override + * Removed ``get_accessible_dag_ids`` method from the security manager override + * Removed ``prefixed_dag_id`` method from the security manager override + * Removed ``init_role`` method from the security manager override + 1.5.1 ..... diff --git a/providers/src/airflow/providers/fab/auth_manager/fab_auth_manager.py b/providers/src/airflow/providers/fab/auth_manager/fab_auth_manager.py index adebe30dd534a..8a91106a64dfc 100644 --- a/providers/src/airflow/providers/fab/auth_manager/fab_auth_manager.py +++ b/providers/src/airflow/providers/fab/auth_manager/fab_auth_manager.py @@ -18,7 +18,6 @@ from __future__ import annotations import argparse -import warnings from functools import cached_property from pathlib import Path from typing import TYPE_CHECKING, Any, Container @@ -47,7 +46,7 @@ GroupCommand, ) from airflow.configuration import conf -from airflow.exceptions import AirflowConfigException, AirflowException, AirflowProviderDeprecationWarning +from airflow.exceptions import AirflowConfigException, AirflowException from airflow.models import DagModel from airflow.providers.fab.auth_manager.cli_commands.definition import ( DB_COMMANDS, @@ -293,16 +292,6 @@ def is_authorized_asset( ) -> bool: return self._is_authorized(method=method, resource_type=RESOURCE_ASSET, user=user) - def is_authorized_dataset( - self, *, method: ResourceMethod, details: AssetDetails | None = None, user: BaseUser | None = None - ) -> bool: - warnings.warn( - "is_authorized_dataset will be renamed as is_authorized_asset in Airflow 3 and will be removed when the minimum Airflow version is set to 3.0 for the fab provider", - AirflowProviderDeprecationWarning, - stacklevel=2, - ) - return self.is_authorized_asset(method=method, user=user) - def is_authorized_pool( self, *, method: ResourceMethod, details: PoolDetails | None = None, user: BaseUser | None = None ) -> bool: diff --git a/providers/src/airflow/providers/fab/auth_manager/security_manager/override.py b/providers/src/airflow/providers/fab/auth_manager/security_manager/override.py index 9c49845b42066..c45d51eaf9062 100644 --- a/providers/src/airflow/providers/fab/auth_manager/security_manager/override.py +++ b/providers/src/airflow/providers/fab/auth_manager/security_manager/override.py @@ -24,13 +24,11 @@ import os import random import uuid -import warnings -from typing import TYPE_CHECKING, Any, Callable, Collection, Container, Iterable, Mapping, Sequence +from typing import TYPE_CHECKING, Any, Callable, Collection, Iterable, Mapping, Sequence import jwt import packaging.version import re2 -from deprecated import deprecated from flask import flash, g, has_request_context, session from flask_appbuilder import const from flask_appbuilder.const import ( @@ -70,13 +68,12 @@ from markupsafe import Markup from sqlalchemy import and_, func, inspect, literal, or_, select from sqlalchemy.exc import MultipleResultsFound -from sqlalchemy.orm import Session, joinedload +from sqlalchemy.orm import joinedload from werkzeug.security import check_password_hash, generate_password_hash from airflow import __version__ as airflow_version -from airflow.auth.managers.utils.fab import get_method_from_fab_action_map from airflow.configuration import conf -from airflow.exceptions import AirflowException, AirflowProviderDeprecationWarning, RemovedInAirflow3Warning +from airflow.exceptions import AirflowException from airflow.models import DagBag, DagModel from airflow.providers.fab.auth_manager.models import ( Action, @@ -109,13 +106,11 @@ ) from airflow.providers.fab.auth_manager.views.user_stats import CustomUserStatsChartView from airflow.security import permissions -from airflow.utils.session import NEW_SESSION, provide_session from airflow.www.extensions.init_auth_manager import get_auth_manager from airflow.www.security_manager import AirflowSecurityManagerV2 from airflow.www.session import AirflowDatabaseSessionInterface if TYPE_CHECKING: - from airflow.auth.managers.base_auth_manager import ResourceMethod from airflow.security.permissions import RESOURCE_ASSET else: from airflow.providers.common.compat.security.permissions import RESOURCE_ASSET @@ -773,14 +768,6 @@ def auth_role_admin(self): """Get the admin role.""" return self.appbuilder.get_app.config["AUTH_ROLE_ADMIN"] - @property - @deprecated( - reason="The 'oauth_whitelists' property is deprecated. Please use 'oauth_allow_list' instead.", - category=AirflowProviderDeprecationWarning, - ) - def oauth_whitelists(self): - return self.oauth_allow_list - def create_builtin_roles(self): """Return FAB builtin roles.""" return self.appbuilder.get_app.config.get("FAB_ROLES", {}) @@ -885,15 +872,6 @@ def _init_auth(self): :meta private: """ app = self.appbuilder.get_app - if self.auth_type == AUTH_OID: - from flask_openid import OpenID - - log.warning( - "AUTH_OID is deprecated and will be removed in version 5. " - "Migrate to other authentication methods." - ) - self.oid = OpenID(app) - if self.auth_type == AUTH_OAUTH: from authlib.integrations.flask_client import OAuth @@ -966,70 +944,6 @@ def create_db(self): log.exception(const.LOGMSG_ERR_SEC_CREATE_DB) exit(1) - def get_readable_dags(self, user) -> Iterable[DagModel]: - """Get the DAGs readable by authenticated user.""" - warnings.warn( - "`get_readable_dags` has been deprecated. Please use `get_auth_manager().get_permitted_dag_ids` " - "instead.", - RemovedInAirflow3Warning, - stacklevel=2, - ) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", RemovedInAirflow3Warning) - return self.get_accessible_dags([permissions.ACTION_CAN_READ], user) - - def get_editable_dags(self, user) -> Iterable[DagModel]: - """Get the DAGs editable by authenticated user.""" - warnings.warn( - "`get_editable_dags` has been deprecated. Please use `get_auth_manager().get_permitted_dag_ids` " - "instead.", - RemovedInAirflow3Warning, - stacklevel=2, - ) - with warnings.catch_warnings(): - warnings.simplefilter("ignore", RemovedInAirflow3Warning) - return self.get_accessible_dags([permissions.ACTION_CAN_EDIT], user) - - @provide_session - def get_accessible_dags( - self, - user_actions: Container[str] | None, - user, - session: Session = NEW_SESSION, - ) -> Iterable[DagModel]: - warnings.warn( - "`get_accessible_dags` has been deprecated. Please use " - "`get_auth_manager().get_permitted_dag_ids` instead.", - RemovedInAirflow3Warning, - stacklevel=3, - ) - - dag_ids = self.get_accessible_dag_ids(user, user_actions, session) - return session.scalars(select(DagModel).where(DagModel.dag_id.in_(dag_ids))) - - @provide_session - def get_accessible_dag_ids( - self, - user, - user_actions: Container[str] | None = None, - session: Session = NEW_SESSION, - ) -> set[str]: - warnings.warn( - "`get_accessible_dag_ids` has been deprecated. Please use " - "`get_auth_manager().get_permitted_dag_ids` instead.", - RemovedInAirflow3Warning, - stacklevel=3, - ) - if not user_actions: - user_actions = [permissions.ACTION_CAN_EDIT, permissions.ACTION_CAN_READ] - method_from_fab_action_map = get_method_from_fab_action_map() - user_methods: Container[ResourceMethod] = [ - method_from_fab_action_map[action] - for action in method_from_fab_action_map - if action in user_actions - ] - return get_auth_manager().get_permitted_dag_ids(user=user, methods=user_methods, session=session) - @staticmethod def get_readable_dag_ids(user=None) -> set[str]: """Get the DAG IDs readable by authenticated user.""" @@ -1088,17 +1002,6 @@ def create_dag_specific_permissions(self) -> None: if dag.access_control is not None: self.sync_perm_for_dag(root_dag_id, dag.access_control) - def prefixed_dag_id(self, dag_id: str) -> str: - """Return the permission name for a DAG id.""" - warnings.warn( - "`prefixed_dag_id` has been deprecated. " - "Please use `airflow.security.permissions.resource_name` instead.", - RemovedInAirflow3Warning, - stacklevel=2, - ) - root_dag_id = self._get_root_dag_id(dag_id) - return self._resource_name(root_dag_id, permissions.RESOURCE_DAG) - def is_dag_resource(self, resource_name: str) -> bool: """Determine if a resource belongs to a DAG or all DAGs.""" if resource_name == permissions.RESOURCE_DAG: @@ -1432,20 +1335,6 @@ def permission_exists_in_one_or_more_roles( def perms_include_action(self, perms, action_name): return any(perm.action and perm.action.name == action_name for perm in perms) - def init_role(self, role_name, perms) -> None: - """ - Initialize the role with actions and related resources. - - :param role_name: - :param perms: - """ - warnings.warn( - "`init_role` has been deprecated. Please use `bulk_sync_roles` instead.", - RemovedInAirflow3Warning, - stacklevel=2, - ) - self.bulk_sync_roles([{"role": role_name, "perms": perms}]) - def bulk_sync_roles(self, roles: Iterable[dict[str, Any]]) -> None: """Sync the provided roles and permissions.""" existing_roles = self._get_all_roles_with_permissions() diff --git a/providers/tests/fab/auth_manager/test_security.py b/providers/tests/fab/auth_manager/test_security.py index 480307cc46d9a..a4e2714ab96d9 100644 --- a/providers/tests/fab/auth_manager/test_security.py +++ b/providers/tests/fab/auth_manager/test_security.py @@ -275,25 +275,6 @@ def _assert_user_does_not_have_dag_perms(dag_id, perms, user=None): return _assert_user_does_not_have_dag_perms -@pytest.mark.parametrize( - "role", - [{"name": "MyRole7", "permissions": [("can_some_other_action", "AnotherBaseView")], "create": False}], - indirect=True, -) -def test_init_role_baseview(app, security_manager, role): - _, params = role - - with pytest.warns( - DeprecationWarning, - match="`init_role` has been deprecated\\. Please use `bulk_sync_roles` instead\\.", - ): - security_manager.init_role(params["name"], params["permissions"]) - - _role = security_manager.find_role(params["name"]) - assert _role is not None - assert len(_role.permissions) == len(params["permissions"]) - - @pytest.mark.parametrize( "role", [{"name": "MyRole3", "permissions": [("can_some_action", "SomeBaseView")]}], @@ -1022,17 +1003,6 @@ def test_get_all_roles_with_permissions(security_manager): assert "Admin" in roles -def test_prefixed_dag_id_is_deprecated(security_manager): - with pytest.warns( - DeprecationWarning, - match=( - "`prefixed_dag_id` has been deprecated. " - "Please use `airflow.security.permissions.resource_name` instead." - ), - ): - security_manager.prefixed_dag_id("hello") - - def test_permissions_work_for_dags_with_dot_in_dagname( app, security_manager, assert_user_has_dag_perms, assert_user_does_not_have_dag_perms, session ):