Skip to content

Commit

Permalink
Remove deprecations from fab provider (apache#44198)
Browse files Browse the repository at this point in the history
* Remove deprecations from fab provider

* Add CHANGELOG
  • Loading branch information
vincbeck authored Nov 21, 2024
1 parent fbf6116 commit 48eb430
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 156 deletions.
14 changes: 14 additions & 0 deletions providers/src/airflow/providers/fab/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
.....

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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", {})
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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."""
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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()
Expand Down
30 changes: 0 additions & 30 deletions providers/tests/fab/auth_manager/test_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")]}],
Expand Down Expand Up @@ -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
):
Expand Down

0 comments on commit 48eb430

Please sign in to comment.