From 3d2f9c11d15e17fe047845a0b17452aeeb058d66 Mon Sep 17 00:00:00 2001 From: Vincent <97131062+vincbeck@users.noreply.github.com> Date: Mon, 23 Sep 2024 08:06:17 -0700 Subject: [PATCH] Add option in simple auth manager to disable authentication and allow everyone as admin (#42355) --- .../managers/simple/simple_auth_manager.py | 13 +++-- .../default_webserver_config.py | 3 ++ .../simple/test_simple_auth_manager.py | 51 +++++++++++++------ 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/airflow/auth/managers/simple/simple_auth_manager.py b/airflow/auth/managers/simple/simple_auth_manager.py index 1d73341719010..a683aa5472cef 100644 --- a/airflow/auth/managers/simple/simple_auth_manager.py +++ b/airflow/auth/managers/simple/simple_auth_manager.py @@ -28,6 +28,7 @@ from termcolor import colored from airflow.auth.managers.base_auth_manager import BaseAuthManager, ResourceMethod +from airflow.auth.managers.simple.user import SimpleAuthManagerUser from airflow.auth.managers.simple.views.auth import SimpleAuthManagerAuthenticationViews from hatch_build import AIRFLOW_ROOT_PATH @@ -43,7 +44,6 @@ PoolDetails, VariableDetails, ) - from airflow.auth.managers.simple.user import SimpleAuthManagerUser class SimpleAuthManagerRole(namedtuple("SimpleAuthManagerRole", "name order"), Enum): @@ -113,7 +113,9 @@ def init(self) -> None: file.write(json.dumps(self.passwords)) def is_logged_in(self) -> bool: - return "user" in session + return "user" in session or self.appbuilder.get_app.config.get( + "SIMPLE_AUTH_MANAGER_ALL_ADMINS", False + ) def get_url_login(self, **kwargs) -> str: return url_for("SimpleAuthManagerAuthenticationViews.login") @@ -122,7 +124,12 @@ def get_url_logout(self) -> str: return url_for("SimpleAuthManagerAuthenticationViews.logout") def get_user(self) -> SimpleAuthManagerUser | None: - return session["user"] if self.is_logged_in() else None + if not self.is_logged_in(): + return None + if self.appbuilder.get_app.config.get("SIMPLE_AUTH_MANAGER_ALL_ADMINS", False): + return SimpleAuthManagerUser(username="anonymous", role="admin") + else: + return session["user"] def is_authorized_configuration( self, diff --git a/airflow/config_templates/default_webserver_config.py b/airflow/config_templates/default_webserver_config.py index 5ef855ae4ab7d..dda8a25ad9493 100644 --- a/airflow/config_templates/default_webserver_config.py +++ b/airflow/config_templates/default_webserver_config.py @@ -147,3 +147,6 @@ "role": "admin", } ] + +# Turn this flag on to disable authentication and allow everyone as admin +SIMPLE_AUTH_MANAGER_ALL_ADMINS = False diff --git a/tests/auth/managers/simple/test_simple_auth_manager.py b/tests/auth/managers/simple/test_simple_auth_manager.py index 3191069860c6b..a11c79063d042 100644 --- a/tests/auth/managers/simple/test_simple_auth_manager.py +++ b/tests/auth/managers/simple/test_simple_auth_manager.py @@ -72,19 +72,26 @@ def test_init_with_users(self, auth_manager_with_appbuilder): assert len(user_passwords_from_file) == 1 @pytest.mark.db_test - def test_is_logged_in(self, auth_manager, app, test_user): + def test_is_logged_in(self, auth_manager_with_appbuilder, app, test_user): with app.test_request_context(): session["user"] = test_user - result = auth_manager.is_logged_in() + result = auth_manager_with_appbuilder.is_logged_in() assert result @pytest.mark.db_test - def test_is_logged_in_return_false_when_no_user_in_session(self, auth_manager, app, test_user): + def test_is_logged_in_return_false_when_no_user_in_session(self, auth_manager_with_appbuilder, app): with app.test_request_context(): - result = auth_manager.is_logged_in() + result = auth_manager_with_appbuilder.is_logged_in() assert result is False + @pytest.mark.db_test + def test_is_logged_in_with_all_admins(self, auth_manager_with_appbuilder, app): + auth_manager_with_appbuilder.appbuilder.app.config["SIMPLE_AUTH_MANAGER_ALL_ADMINS"] = True + with app.test_request_context(): + result = auth_manager_with_appbuilder.is_logged_in() + assert result + @patch("airflow.auth.managers.simple.simple_auth_manager.url_for") def test_get_url_login(self, mock_url_for, auth_manager): auth_manager.get_url_login() @@ -97,15 +104,27 @@ def test_get_url_logout(self, mock_url_for, auth_manager): @pytest.mark.db_test @patch.object(SimpleAuthManager, "is_logged_in") - def test_get_user(self, mock_is_logged_in, auth_manager, app, test_user): + def test_get_user(self, mock_is_logged_in, auth_manager_with_appbuilder, app, test_user): mock_is_logged_in.return_value = True with app.test_request_context(): session["user"] = test_user - result = auth_manager.get_user() + result = auth_manager_with_appbuilder.get_user() assert result == test_user + @pytest.mark.db_test + @patch.object(SimpleAuthManager, "is_logged_in") + def test_get_user_with_all_admins(self, mock_is_logged_in, auth_manager_with_appbuilder, app): + mock_is_logged_in.return_value = True + + auth_manager_with_appbuilder.appbuilder.app.config["SIMPLE_AUTH_MANAGER_ALL_ADMINS"] = True + with app.test_request_context(): + result = auth_manager_with_appbuilder.get_user() + + assert result.username == "anonymous" + assert result.role == "admin" + @patch.object(SimpleAuthManager, "is_logged_in") def test_get_user_return_none_when_not_logged_in(self, mock_is_logged_in, auth_manager): mock_is_logged_in.return_value = False @@ -138,13 +157,13 @@ def test_get_user_return_none_when_not_logged_in(self, mock_is_logged_in, auth_m ], ) def test_is_authorized_methods( - self, mock_is_logged_in, auth_manager, app, api, is_logged_in, role, method, result + self, mock_is_logged_in, auth_manager_with_appbuilder, app, api, is_logged_in, role, method, result ): mock_is_logged_in.return_value = is_logged_in with app.test_request_context(): session["user"] = SimpleAuthManagerUser(username="test", role=role) - assert getattr(auth_manager, api)(method=method) is result + assert getattr(auth_manager_with_appbuilder, api)(method=method) is result @pytest.mark.db_test @patch.object(SimpleAuthManager, "is_logged_in") @@ -172,13 +191,13 @@ def test_is_authorized_methods( ], ) def test_is_authorized_view_methods( - self, mock_is_logged_in, auth_manager, app, api, kwargs, is_logged_in, role, result + self, mock_is_logged_in, auth_manager_with_appbuilder, app, api, kwargs, is_logged_in, role, result ): mock_is_logged_in.return_value = is_logged_in with app.test_request_context(): session["user"] = SimpleAuthManagerUser(username="test", role=role) - assert getattr(auth_manager, api)(**kwargs) is result + assert getattr(auth_manager_with_appbuilder, api)(**kwargs) is result @pytest.mark.db_test @patch.object(SimpleAuthManager, "is_logged_in") @@ -202,13 +221,13 @@ def test_is_authorized_view_methods( ], ) def test_is_authorized_methods_op_role_required( - self, mock_is_logged_in, auth_manager, app, api, role, method, result + self, mock_is_logged_in, auth_manager_with_appbuilder, app, api, role, method, result ): mock_is_logged_in.return_value = True with app.test_request_context(): session["user"] = SimpleAuthManagerUser(username="test", role=role) - assert getattr(auth_manager, api)(method=method) is result + assert getattr(auth_manager_with_appbuilder, api)(method=method) is result @pytest.mark.db_test @patch.object(SimpleAuthManager, "is_logged_in") @@ -227,13 +246,13 @@ def test_is_authorized_methods_op_role_required( ], ) def test_is_authorized_methods_user_role_required( - self, mock_is_logged_in, auth_manager, app, api, role, method, result + self, mock_is_logged_in, auth_manager_with_appbuilder, app, api, role, method, result ): mock_is_logged_in.return_value = True with app.test_request_context(): session["user"] = SimpleAuthManagerUser(username="test", role=role) - assert getattr(auth_manager, api)(method=method) is result + assert getattr(auth_manager_with_appbuilder, api)(method=method) is result @pytest.mark.db_test @patch.object(SimpleAuthManager, "is_logged_in") @@ -252,13 +271,13 @@ def test_is_authorized_methods_user_role_required( ], ) def test_is_authorized_methods_viewer_role_required_for_get( - self, mock_is_logged_in, auth_manager, app, api, role, method, result + self, mock_is_logged_in, auth_manager_with_appbuilder, app, api, role, method, result ): mock_is_logged_in.return_value = True with app.test_request_context(): session["user"] = SimpleAuthManagerUser(username="test", role=role) - assert getattr(auth_manager, api)(method=method) is result + assert getattr(auth_manager_with_appbuilder, api)(method=method) is result @pytest.mark.db_test @patch(