Skip to content

Commit

Permalink
Add option in simple auth manager to disable authentication and allow…
Browse files Browse the repository at this point in the history
… everyone as admin (apache#42355)
  • Loading branch information
vincbeck authored Sep 23, 2024
1 parent ffff0e8 commit 3d2f9c1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 19 deletions.
13 changes: 10 additions & 3 deletions airflow/auth/managers/simple/simple_auth_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -43,7 +44,6 @@
PoolDetails,
VariableDetails,
)
from airflow.auth.managers.simple.user import SimpleAuthManagerUser


class SimpleAuthManagerRole(namedtuple("SimpleAuthManagerRole", "name order"), Enum):
Expand Down Expand Up @@ -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")
Expand All @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions airflow/config_templates/default_webserver_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,6 @@
"role": "admin",
}
]

# Turn this flag on to disable authentication and allow everyone as admin
SIMPLE_AUTH_MANAGER_ALL_ADMINS = False
51 changes: 35 additions & 16 deletions tests/auth/managers/simple/test_simple_auth_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -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")
Expand All @@ -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(
Expand Down

0 comments on commit 3d2f9c1

Please sign in to comment.