From add6df570f99362eac60f4fdd4848c077d0025b6 Mon Sep 17 00:00:00 2001 From: Joey Orlando Date: Thu, 25 Jan 2024 14:19:28 -0500 Subject: [PATCH] address improperly formatted cloud auth api request headers --- .../mobile_app/tests/test_mobile_app_gateway.py | 3 +-- engine/apps/mobile_app/views.py | 5 +---- engine/common/cloud_auth_api/client.py | 14 +++++++++++--- engine/common/cloud_auth_api/tests/test_client.py | 12 ++++++++---- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/engine/apps/mobile_app/tests/test_mobile_app_gateway.py b/engine/apps/mobile_app/tests/test_mobile_app_gateway.py index 5c259bf1..a860a85a 100644 --- a/engine/apps/mobile_app/tests/test_mobile_app_gateway.py +++ b/engine/apps/mobile_app/tests/test_mobile_app_gateway.py @@ -344,8 +344,7 @@ def test_mobile_app_gateway_properly_generates_an_auth_token( assert auth_token == f"{stack_id}:{MOCK_AUTH_TOKEN}" mock_request_signed_token.assert_called_once_with( - organization_id, - stack_id, + organization, [CloudAuthApiClient.Scopes.INCIDENT_WRITE], { "iat": MOCK_TIMEZONE_NOW, diff --git a/engine/apps/mobile_app/views.py b/engine/apps/mobile_app/views.py index fcd728d7..46da4b5a 100644 --- a/engine/apps/mobile_app/views.py +++ b/engine/apps/mobile_app/views.py @@ -178,10 +178,7 @@ class MobileAppGatewayView(APIView): }[downstream_backend] org = user.organization - stack_id = org.stack_id - token = CloudAuthApiClient().request_signed_token(org.org_id, stack_id, token_scopes, token_claims) - - return f"{stack_id}:{token}" + return f"{org.stack_id}:{CloudAuthApiClient().request_signed_token(org, token_scopes, token_claims)}" @classmethod def _get_downstream_headers( diff --git a/engine/common/cloud_auth_api/client.py b/engine/common/cloud_auth_api/client.py index 21f760cc..193051a8 100644 --- a/engine/common/cloud_auth_api/client.py +++ b/engine/common/cloud_auth_api/client.py @@ -6,6 +6,9 @@ import requests from django.conf import settings from rest_framework import status +if typing.TYPE_CHECKING: + from apps.user_management.models import Organization + class CloudAuthApiException(Exception): """A generic 400 or 500 level exception from the Cloud Auth API""" @@ -35,15 +38,20 @@ class CloudAuthApiClient: self.api_token = settings.GRAFANA_CLOUD_AUTH_API_SYSTEM_TOKEN def request_signed_token( - self, org_id: int, stack_id: int, scopes: typing.List[Scopes], claims: typing.Dict[str, typing.Any] + self, org: "Organization", scopes: typing.List[Scopes], claims: typing.Dict[str, typing.Any] ) -> str: + org_id = org.org_id + stack_id = org.stack_id + headers = { "Authorization": f"Bearer {self.api_token}", - "X-Org-ID": org_id, + # need to cast to str otherwise - requests.exceptions.InvalidHeader: Header part ... from ('X-Org-ID', 5000) + # must be of type str or bytes, not + "X-Org-ID": str(org_id), "X-Realms": [ { "type": "stack", - "identifier": stack_id, + "identifier": str(stack_id), }, ], } diff --git a/engine/common/cloud_auth_api/tests/test_client.py b/engine/common/cloud_auth_api/tests/test_client.py index c52d6eb0..8c0a9bd1 100644 --- a/engine/common/cloud_auth_api/tests/test_client.py +++ b/engine/common/cloud_auth_api/tests/test_client.py @@ -16,13 +16,17 @@ def configure_cloud_auth_api_client(settings): @patch("common.cloud_auth_api.client.requests") +@pytest.mark.django_db @pytest.mark.parametrize("response_status_code", [status.HTTP_200_OK, status.HTTP_401_UNAUTHORIZED]) -def test_request_signed_token(mock_requests, response_status_code): +def test_request_signed_token(mock_requests, make_organization, response_status_code): mock_auth_token = ",mnasdlkjlakjoqwejroiqwejr" mock_response_text = "error message" org_id = 1 stack_id = 5 + + organization = make_organization(stack_id=stack_id, org_id=org_id) + scopes = ["incident:write", "foo:bar"] claims = {"vegetable": "carrot", "fruit": "apple"} @@ -42,7 +46,7 @@ def test_request_signed_token(mock_requests, response_status_code): mock_requests.post.return_value = MockResponse(response_status_code) def _make_request(): - return CloudAuthApiClient().request_signed_token(org_id, stack_id, scopes, claims) + return CloudAuthApiClient().request_signed_token(organization, scopes, claims) url = f"{GRAFANA_CLOUD_AUTH_API_URL}/v1/sign" @@ -61,11 +65,11 @@ def test_request_signed_token(mock_requests, response_status_code): url, headers={ "Authorization": f"Bearer {GRAFANA_CLOUD_AUTH_API_SYSTEM_TOKEN}", - "X-Org-ID": org_id, + "X-Org-ID": str(org_id), "X-Realms": [ { "type": "stack", - "identifier": stack_id, + "identifier": str(stack_id), }, ], },