Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions enterprise_gateway/enterprisegatewayapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@
)
from .services.sessions.sessionmanager import SessionManager

try:
from jupyter_server.auth.authorizer import AllowAllAuthorizer
except ImportError:
AllowAllAuthorizer = object

# Add additional command line aliases
aliases = dict(base_aliases)
aliases.update(
Expand Down Expand Up @@ -219,6 +214,10 @@ def init_webapp(self) -> None:

handlers = self._create_request_handlers()

# Instantiate the configured authorizer class
self.log.info(f"Using authorizer: {self.authorizer_class}")
authorizer = self.authorizer_class(parent=self, log=self.log)

self.web_app = web.Application(
handlers=handlers,
kernel_manager=self.kernel_manager,
Expand Down Expand Up @@ -250,8 +249,8 @@ def init_webapp(self) -> None:
# setting ws_ping_interval value that can allow it to be modified for the purpose of toggling ping mechanism
# for zmq web-sockets or increasing/decreasing web socket ping interval/timeouts.
ws_ping_interval=self.ws_ping_interval * 1000,
# Add a pass-through authorizer for now
authorizer=AllowAllAuthorizer(),
# Use configurable authorizer
authorizer=authorizer,
)

def _build_ssl_options(self) -> Optional[ssl.SSLContext]:
Expand Down
26 changes: 26 additions & 0 deletions enterprise_gateway/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -762,3 +762,29 @@ def _availability_mode_env_default(self):
of `enterprise_gateway.services.sessions.KernelSessionManager`.
""",
)

authorizer_class = Type(
klass="jupyter_server.auth.authorizer.Authorizer",
default_value="jupyter_server.auth.authorizer.AllowAllAuthorizer",
config=True,
help="""
The authorizer class to use for authenticating and authorizing requests.

By default, Enterprise Gateway uses AllowAllAuthorizer which allows all
authenticated requests. You can configure a custom authorizer to implement
authentication and authorization logic.

Example usage:
c.EnterpriseGatewayApp.authorizer_class = 'my_module.MyAuthorizer'

Environment variable: EG_AUTHORIZER_CLASS
""",
)

authorizer_class_env = "EG_AUTHORIZER_CLASS"

@default("authorizer_class")
def _authorizer_class_default(self):
return os.getenv(
self.authorizer_class_env, "jupyter_server.auth.authorizer.AllowAllAuthorizer"
)
50 changes: 50 additions & 0 deletions enterprise_gateway/tests/test_gatewayapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,56 @@ def test_ssl_options_no_config(self):
ssl_options = app._build_ssl_options()
self.assertIsNone(ssl_options)

def test_authorizer_class_default(self):
"""Test that authorizer_class defaults to None when not configured."""
app = EnterpriseGatewayApp()
app.init_configurables()
app.init_webapp()

# By default, should use AllowAllAuthorizer
from jupyter_server.auth.authorizer import AllowAllAuthorizer

authorizer = app.web_app.settings.get("authorizer")
self.assertIsNotNone(authorizer)
self.assertIsInstance(authorizer, AllowAllAuthorizer)

def test_authorizer_class_env_var(self):
"""Test that authorizer_class can be configured via environment variable."""
# Create a custom authorizer for testing
from jupyter_server.auth.authorizer import Authorizer

class CustomTestAuthorizer(Authorizer):
"""Test authorizer for validation"""

def is_authorized(self, handler, user, action, resource):
return True

# Set the environment variable to point to our custom authorizer
# We need to make it importable first
import sys
from types import ModuleType

# Create a test module
test_module = ModuleType("test_auth_module")
test_module.CustomTestAuthorizer = CustomTestAuthorizer
sys.modules["test_auth_module"] = test_module

try:
os.environ["EG_AUTHORIZER_CLASS"] = "test_auth_module.CustomTestAuthorizer"

app = EnterpriseGatewayApp()
app.init_configurables()
app.init_webapp()

# Should use our custom authorizer
authorizer = app.web_app.settings.get("authorizer")
self.assertIsNotNone(authorizer)
self.assertIsInstance(authorizer, CustomTestAuthorizer)
finally:
# Clean up
if "test_auth_module" in sys.modules:
del sys.modules["test_auth_module"]


class TestGatewayAppBase(AsyncHTTPTestCase, ExpectLog):
"""Base class for integration style tests using HTTP/Websockets against an
Expand Down
Loading