From ce1aba5f8d561f55383c4a8bf983a75899d1a599 Mon Sep 17 00:00:00 2001 From: Swati Mukund Bagal Date: Wed, 25 Mar 2026 21:19:46 -0500 Subject: [PATCH 1/2] fix: update MaaS tests for subscription binding and fix gateway 500 error Signed-off-by: Swati Mukund Bagal --- .../test_maas_auth_enforcement.py | 49 ++++++++++++++----- .../test_maas_sub_enforcement.py | 48 ++++++++++++++---- .../maas_billing/maas_subscription/utils.py | 6 +++ 3 files changed, 81 insertions(+), 22 deletions(-) diff --git a/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py b/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py index f004951fa..b20be9c00 100644 --- a/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py +++ b/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py @@ -6,9 +6,12 @@ from tests.model_serving.maas_billing.maas_subscription.utils import ( chat_payload_for_url, + create_api_key, poll_expected_status, + revoke_api_key, ) from tests.model_serving.maas_billing.utils import build_maas_headers +from utilities.general import generate_random_name from utilities.plugins.constant import RestHeader LOGGER = structlog.get_logger(name=__name__) @@ -32,21 +35,41 @@ class TestMaaSAuthPolicyEnforcementTinyLlama: def test_authorized_user_gets_200( self, request_session_http: requests.Session, + base_url: str, + ocp_token_for_actor: str, model_url_tinyllama_free: str, - maas_headers_for_actor_api_key: dict[str, str], + maas_subscription_tinyllama_free, ) -> None: - payload = chat_payload_for_url(model_url=model_url_tinyllama_free) - - resp = poll_expected_status( + """ + Verify a free user with a subscription-bound API key can access the free model. + """ + _, body = create_api_key( + base_url=base_url, + ocp_user_token=ocp_token_for_actor, request_session_http=request_session_http, - model_url=model_url_tinyllama_free, - headers=maas_headers_for_actor_api_key, - payload=payload, - expected_statuses={200}, + api_key_name=f"e2e-auth-enforce-{generate_random_name()}", + subscription=maas_subscription_tinyllama_free.name, ) + api_key = body["key"] + key_id = body["id"] - LOGGER.info(f"test_authorized_user_gets_200 -> POST {model_url_tinyllama_free} returned {resp.status_code}") - assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" + try: + resp = poll_expected_status( + request_session_http=request_session_http, + model_url=model_url_tinyllama_free, + headers=build_maas_headers(token=api_key), + payload=chat_payload_for_url(model_url=model_url_tinyllama_free), + expected_statuses={200}, + ) + LOGGER.info(f"test_authorized_user_gets_200 -> POST {model_url_tinyllama_free} returned {resp.status_code}") + assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" + finally: + revoke_api_key( + request_session_http=request_session_http, + base_url=base_url, + key_id=key_id, + ocp_user_token=ocp_token_for_actor, + ) @pytest.mark.smoke def test_no_auth_header_gets_401( @@ -99,10 +122,12 @@ def test_wrong_group_sa_denied_on_premium_model( model_url=model_url_tinyllama_premium, headers=maas_headers_for_wrong_group_sa, payload=payload, - expected_statuses={403}, + expected_statuses={401}, ) LOGGER.info( "test_wrong_group_sa_denied_on_premium_model -> " f"POST {model_url_tinyllama_premium} returned {resp.status_code}" ) - assert resp.status_code == 403, f"Expected 403, got {resp.status_code}: {resp.text[:200]}" + assert resp.status_code == 401, ( + f"Expected 401 (SA token not authenticated as MaaS user), got {resp.status_code}: {resp.text[:200]}" + ) diff --git a/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py b/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py index f50acadd7..0d3fae6fb 100644 --- a/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py +++ b/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py @@ -4,7 +4,13 @@ import requests import structlog -from tests.model_serving.maas_billing.maas_subscription.utils import chat_payload_for_url +from tests.model_serving.maas_billing.maas_subscription.utils import ( + chat_payload_for_url, + create_api_key, + revoke_api_key, +) +from tests.model_serving.maas_billing.utils import build_maas_headers +from utilities.general import generate_random_name LOGGER = structlog.get_logger(name=__name__) @@ -30,19 +36,41 @@ class TestSubscriptionEnforcementTinyLlama: def test_subscribed_user_gets_200( self, request_session_http: requests.Session, + base_url: str, + ocp_token_for_actor: str, model_url_tinyllama_premium: str, - maas_headers_for_actor_api_key: dict[str, str], + maas_subscription_tinyllama_premium, ) -> None: - resp = request_session_http.post( - url=model_url_tinyllama_premium, - headers=maas_headers_for_actor_api_key, - json=chat_payload_for_url(model_url=model_url_tinyllama_premium), - timeout=60, + """ + Verify a premium user with a subscription-bound API key can access the premium model. + """ + _, body = create_api_key( + base_url=base_url, + ocp_user_token=ocp_token_for_actor, + request_session_http=request_session_http, + api_key_name=f"e2e-sub-enforce-{generate_random_name()}", + subscription=maas_subscription_tinyllama_premium.name, ) - LOGGER.info(f"test_subscribed_user_gets_200 -> {resp.status_code}") - assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" + api_key = body["key"] + key_id = body["id"] + + try: + resp = request_session_http.post( + url=model_url_tinyllama_premium, + headers=build_maas_headers(token=api_key), + json=chat_payload_for_url(model_url=model_url_tinyllama_premium), + timeout=60, + ) + LOGGER.info(f"test_subscribed_user_gets_200 -> {resp.status_code}") + assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" + finally: + revoke_api_key( + request_session_http=request_session_http, + base_url=base_url, + key_id=key_id, + ocp_user_token=ocp_token_for_actor, + ) - @pytest.mark.tier1 @pytest.mark.parametrize("ocp_token_for_actor", [{"type": "premium"}], indirect=True) def test_explicit_subscription_header_works( self, diff --git a/tests/model_serving/maas_billing/maas_subscription/utils.py b/tests/model_serving/maas_billing/maas_subscription/utils.py index af118a2bc..80b555960 100644 --- a/tests/model_serving/maas_billing/maas_subscription/utils.py +++ b/tests/model_serving/maas_billing/maas_subscription/utils.py @@ -187,6 +187,7 @@ def create_api_key( request_timeout_seconds: int = 60, expires_in: str | None = None, raise_on_error: bool = True, + subscription: str | None = None, ) -> tuple[Response, dict[str, Any]]: """ Create an API key via MaaS API and return (response, parsed_body). @@ -199,12 +200,17 @@ def create_api_key( When None, no expiresIn field is sent and the key does not expire. raise_on_error: When True (default), raises AssertionError for non-200/201 responses. Set to False when testing error cases (e.g. 400 rejection). + subscription: Optional MaaSSubscription name to bind at mint time. + When provided, the key is bound to this subscription for inference. + When None, the API auto-selects the highest-priority subscription. """ api_keys_url = f"{base_url}/v1/api-keys" payload: dict[str, Any] = {"name": api_key_name} if expires_in is not None: payload["expiresIn"] = expires_in + if subscription is not None: + payload["subscription"] = subscription response = request_session_http.post( url=api_keys_url, From 44f83de28d7dfcdfc54273adcc461fa39efda3e7 Mon Sep 17 00:00:00 2001 From: Swati Mukund Bagal Date: Thu, 26 Mar 2026 15:57:14 -0500 Subject: [PATCH 2/2] address review comment Signed-off-by: Swati Mukund Bagal --- .../maas_subscription/conftest.py | 58 +++++++++++++++++++ .../test_maas_auth_enforcement.py | 39 +++---------- .../test_maas_sub_enforcement.py | 39 +++---------- 3 files changed, 74 insertions(+), 62 deletions(-) diff --git a/tests/model_serving/maas_billing/maas_subscription/conftest.py b/tests/model_serving/maas_billing/maas_subscription/conftest.py index afd9ef51d..00bc0bf6e 100644 --- a/tests/model_serving/maas_billing/maas_subscription/conftest.py +++ b/tests/model_serving/maas_billing/maas_subscription/conftest.py @@ -203,6 +203,64 @@ def maas_headers_for_actor_api_key(maas_api_key_for_actor: str) -> dict[str, str return build_maas_headers(token=maas_api_key_for_actor) +@pytest.fixture(scope="class") +def api_key_bound_to_free_subscription( + request_session_http: requests.Session, + base_url: str, + ocp_token_for_actor: str, + maas_subscription_tinyllama_free: MaaSSubscription, + maas_subscription_controller_enabled_latest: None, + maas_gateway_api: None, + maas_api_gateway_reachable: None, +) -> Generator[str, Any, Any]: + """ + API key bound to the free subscription at mint time. Revoked on teardown. + """ + _, body = create_api_key( + base_url=base_url, + ocp_user_token=ocp_token_for_actor, + request_session_http=request_session_http, + api_key_name=f"e2e-auth-enforce-{generate_random_name()}", + subscription=maas_subscription_tinyllama_free.name, + ) + yield body["key"] + revoke_api_key( + request_session_http=request_session_http, + base_url=base_url, + key_id=body["id"], + ocp_user_token=ocp_token_for_actor, + ) + + +@pytest.fixture(scope="class") +def api_key_bound_to_premium_subscription( + request_session_http: requests.Session, + base_url: str, + ocp_token_for_actor: str, + maas_subscription_tinyllama_premium: MaaSSubscription, + maas_subscription_controller_enabled_latest: None, + maas_gateway_api: None, + maas_api_gateway_reachable: None, +) -> Generator[str, Any, Any]: + """ + API key bound to the premium subscription at mint time. Revoked on teardown. + """ + _, body = create_api_key( + base_url=base_url, + ocp_user_token=ocp_token_for_actor, + request_session_http=request_session_http, + api_key_name=f"e2e-sub-enforce-{generate_random_name()}", + subscription=maas_subscription_tinyllama_premium.name, + ) + yield body["key"] + revoke_api_key( + request_session_http=request_session_http, + base_url=base_url, + key_id=body["id"], + ocp_user_token=ocp_token_for_actor, + ) + + @pytest.fixture(scope="class") def maas_wrong_group_service_account_token( maas_api_server_url: str, diff --git a/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py b/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py index b20be9c00..19b2c956a 100644 --- a/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py +++ b/tests/model_serving/maas_billing/maas_subscription/test_maas_auth_enforcement.py @@ -6,12 +6,9 @@ from tests.model_serving.maas_billing.maas_subscription.utils import ( chat_payload_for_url, - create_api_key, poll_expected_status, - revoke_api_key, ) from tests.model_serving.maas_billing.utils import build_maas_headers -from utilities.general import generate_random_name from utilities.plugins.constant import RestHeader LOGGER = structlog.get_logger(name=__name__) @@ -35,41 +32,21 @@ class TestMaaSAuthPolicyEnforcementTinyLlama: def test_authorized_user_gets_200( self, request_session_http: requests.Session, - base_url: str, - ocp_token_for_actor: str, model_url_tinyllama_free: str, - maas_subscription_tinyllama_free, + api_key_bound_to_free_subscription: str, ) -> None: """ Verify a free user with a subscription-bound API key can access the free model. """ - _, body = create_api_key( - base_url=base_url, - ocp_user_token=ocp_token_for_actor, + resp = poll_expected_status( request_session_http=request_session_http, - api_key_name=f"e2e-auth-enforce-{generate_random_name()}", - subscription=maas_subscription_tinyllama_free.name, + model_url=model_url_tinyllama_free, + headers=build_maas_headers(token=api_key_bound_to_free_subscription), + payload=chat_payload_for_url(model_url=model_url_tinyllama_free), + expected_statuses={200}, ) - api_key = body["key"] - key_id = body["id"] - - try: - resp = poll_expected_status( - request_session_http=request_session_http, - model_url=model_url_tinyllama_free, - headers=build_maas_headers(token=api_key), - payload=chat_payload_for_url(model_url=model_url_tinyllama_free), - expected_statuses={200}, - ) - LOGGER.info(f"test_authorized_user_gets_200 -> POST {model_url_tinyllama_free} returned {resp.status_code}") - assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" - finally: - revoke_api_key( - request_session_http=request_session_http, - base_url=base_url, - key_id=key_id, - ocp_user_token=ocp_token_for_actor, - ) + LOGGER.info(f"test_authorized_user_gets_200 -> POST {model_url_tinyllama_free} returned {resp.status_code}") + assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" @pytest.mark.smoke def test_no_auth_header_gets_401( diff --git a/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py b/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py index 0d3fae6fb..723318cdc 100644 --- a/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py +++ b/tests/model_serving/maas_billing/maas_subscription/test_maas_sub_enforcement.py @@ -6,11 +6,8 @@ from tests.model_serving.maas_billing.maas_subscription.utils import ( chat_payload_for_url, - create_api_key, - revoke_api_key, ) from tests.model_serving.maas_billing.utils import build_maas_headers -from utilities.general import generate_random_name LOGGER = structlog.get_logger(name=__name__) @@ -36,40 +33,20 @@ class TestSubscriptionEnforcementTinyLlama: def test_subscribed_user_gets_200( self, request_session_http: requests.Session, - base_url: str, - ocp_token_for_actor: str, model_url_tinyllama_premium: str, - maas_subscription_tinyllama_premium, + api_key_bound_to_premium_subscription: str, ) -> None: """ Verify a premium user with a subscription-bound API key can access the premium model. """ - _, body = create_api_key( - base_url=base_url, - ocp_user_token=ocp_token_for_actor, - request_session_http=request_session_http, - api_key_name=f"e2e-sub-enforce-{generate_random_name()}", - subscription=maas_subscription_tinyllama_premium.name, + resp = request_session_http.post( + url=model_url_tinyllama_premium, + headers=build_maas_headers(token=api_key_bound_to_premium_subscription), + json=chat_payload_for_url(model_url=model_url_tinyllama_premium), + timeout=60, ) - api_key = body["key"] - key_id = body["id"] - - try: - resp = request_session_http.post( - url=model_url_tinyllama_premium, - headers=build_maas_headers(token=api_key), - json=chat_payload_for_url(model_url=model_url_tinyllama_premium), - timeout=60, - ) - LOGGER.info(f"test_subscribed_user_gets_200 -> {resp.status_code}") - assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" - finally: - revoke_api_key( - request_session_http=request_session_http, - base_url=base_url, - key_id=key_id, - ocp_user_token=ocp_token_for_actor, - ) + LOGGER.info(f"test_subscribed_user_gets_200 -> {resp.status_code}") + assert resp.status_code == 200, f"Expected 200, got {resp.status_code}: {resp.text[:200]}" @pytest.mark.parametrize("ocp_token_for_actor", [{"type": "premium"}], indirect=True) def test_explicit_subscription_header_works(