diff --git a/engine/apps/grafana_plugin/helpers/client.py b/engine/apps/grafana_plugin/helpers/client.py index d9e7faaa..671386b1 100644 --- a/engine/apps/grafana_plugin/helpers/client.py +++ b/engine/apps/grafana_plugin/helpers/client.py @@ -371,11 +371,7 @@ class GcomAPIClient(APIClient): or feature_enabled_via_enable_key_comma_delimited ) - def is_rbac_enabled_for_stack(self, stack_id: str) -> bool: - """ - NOTE: must use an "Admin" GCOM token when calling this method - """ - instance_info = self.get_instance_info(stack_id, True) + def is_rbac_enabled_for_instance(self, instance_info: GCOMInstanceInfo = None) -> bool: if not instance_info: return False return self._feature_toggle_is_enabled(instance_info, "accessControlOnCall") diff --git a/engine/apps/grafana_plugin/tests/test_gcom_api_client.py b/engine/apps/grafana_plugin/tests/test_gcom_api_client.py index a8c3f67d..40d5b836 100644 --- a/engine/apps/grafana_plugin/tests/test_gcom_api_client.py +++ b/engine/apps/grafana_plugin/tests/test_gcom_api_client.py @@ -12,7 +12,7 @@ class TestIsRbacEnabledForStack: TEST_FEATURE_TOGGLE = "helloWorld" @pytest.mark.parametrize( - "gcom_api_response,expected", + "instance_info,expected", [ (None, False), ({}, False), @@ -22,16 +22,9 @@ class TestIsRbacEnabledForStack: ({"config": {"feature_toggles": {"accessControlOnCall": "true"}}}, True), ], ) - @patch("apps.grafana_plugin.helpers.client.GcomAPIClient.api_get") - def test_it_returns_based_on_feature_toggle_value( - self, mocked_gcom_api_client_api_get, gcom_api_response, expected - ): - stack_id = 5 - mocked_gcom_api_client_api_get.return_value = (gcom_api_response, {"status_code": 200}) - + def test_it_returns_based_on_feature_toggle_value(self, instance_info, expected): api_client = GcomAPIClient("someFakeApiToken") - assert api_client.is_rbac_enabled_for_stack(stack_id) == expected - assert mocked_gcom_api_client_api_get.called_once_with(f"instances/{stack_id}?config=true") + assert api_client.is_rbac_enabled_for_instance(instance_info) == expected @pytest.mark.parametrize( "instance_info_feature_toggles,delimiter,expected", diff --git a/engine/apps/user_management/sync.py b/engine/apps/user_management/sync.py index ebbcf6fd..e95245b6 100644 --- a/engine/apps/user_management/sync.py +++ b/engine/apps/user_management/sync.py @@ -13,24 +13,9 @@ logger.setLevel(logging.DEBUG) def sync_organization(organization: Organization) -> None: - grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token) - - # NOTE: checking whether or not RBAC is enabled depends on whether we are dealing with an open-source or cloud - # stack. For Cloud we should make a call to the GCOM API, using an admin API token, and get the list of - # feature_toggles enabled for the stack. For open-source, simply make a HEAD request to the grafana instance's API - # and consider RBAC enabled if the list RBAC permissions endpoint returns 200. We cannot simply rely on the HEAD - # call in cloud because if an instance is not active, the grafana gateway will still return 200 for the - # HEAD request. - if settings.LICENSE == settings.CLOUD_LICENSE_NAME: - gcom_client = GcomAPIClient(settings.GRAFANA_COM_ADMIN_API_TOKEN) - rbac_is_enabled = gcom_client.is_rbac_enabled_for_stack(organization.stack_id) - else: - rbac_is_enabled = grafana_api_client.is_rbac_enabled_for_organization() - - organization.is_rbac_permissions_enabled = rbac_is_enabled - _sync_instance_info(organization) + grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token) _, check_token_call_status = grafana_api_client.check_token() if check_token_call_status["connected"]: organization.api_token_status = Organization.API_TOKEN_STATUS_OK @@ -62,7 +47,7 @@ def sync_organization(organization: Organization) -> None: def _sync_instance_info(organization: Organization) -> None: if organization.gcom_token: gcom_client = GcomAPIClient(organization.gcom_token) - instance_info = gcom_client.get_instance_info(organization.stack_id) + instance_info = gcom_client.get_instance_info(organization.stack_id, include_config_query_param=True) if not instance_info or instance_info["orgId"] != organization.org_id: return @@ -73,7 +58,17 @@ def _sync_instance_info(organization: Organization) -> None: organization.region_slug = instance_info["regionSlug"] organization.grafana_url = instance_info["url"] organization.cluster_slug = instance_info["clusterSlug"] + organization.is_rbac_permissions_enabled = gcom_client.is_rbac_enabled_for_instance(instance_info) organization.gcom_token_org_last_time_synced = timezone.now() + else: + # NOTE: checking whether or not RBAC is enabled depends on whether we are dealing with an open-source or cloud + # stack. For Cloud we should make a call to the GCOM API, using an admin API token, and get the list of + # feature_toggles enabled for the stack. For open-source, simply make a HEAD request to the grafana instance's API + # and consider RBAC enabled if the list RBAC permissions endpoint returns 200. We cannot simply rely on the HEAD + # call in cloud because if an instance is not active, the grafana gateway will still return 200 for the + # HEAD request. + grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token) + organization.is_rbac_permissions_enabled = grafana_api_client.is_rbac_enabled_for_organization() def sync_users_and_teams(client: GrafanaAPIClient, organization: Organization) -> None: diff --git a/engine/apps/user_management/tests/test_sync.py b/engine/apps/user_management/tests/test_sync.py index 86d4881b..76537cef 100644 --- a/engine/apps/user_management/tests/test_sync.py +++ b/engine/apps/user_management/tests/test_sync.py @@ -312,18 +312,36 @@ def test_sync_organization_is_rbac_permissions_enabled_open_source(make_organiza assert organization.is_rbac_permissions_enabled == grafana_api_response -@pytest.mark.parametrize("gcom_api_response", [False, True]) -@patch("apps.user_management.sync.GcomAPIClient") -@override_settings(LICENSE=settings.CLOUD_LICENSE_NAME) -@override_settings(GRAFANA_COM_ADMIN_API_TOKEN="mockedToken") +@patch("apps.user_management.sync.GcomAPIClient.api_get") +@pytest.mark.parametrize( + "instance_info,expected", + [ + ({"config": {"feature_toggles": {}}}, False), + ({"config": {"feature_toggles": {"accessControlOnCall": "false"}}}, False), + ({"config": {"feature_toggles": {"accessControlOnCall": "true"}}}, True), + ], +) @pytest.mark.django_db -def test_sync_organization_is_rbac_permissions_enabled_cloud(mocked_gcom_client, make_organization, gcom_api_response): +def test_sync_organization_is_rbac_permissions_enabled_cloud( + mocked_gcom_client, make_organization, instance_info, expected +): stack_id = 5 - organization = make_organization(stack_id=stack_id) + organization = make_organization(stack_id=stack_id, gcom_token="TEST_GCOM_TOKEN") api_check_token_call_status = {"connected": True} - mocked_gcom_client.return_value.is_rbac_enabled_for_stack.return_value = gcom_api_response + instance_info.update( + { + "orgId": organization.org_id, + "slug": organization.stack_slug, + "orgSlug": organization.org_slug, + "orgName": organization.org_title, + "regionSlug": organization.region_slug, + "url": organization.grafana_url, + "clusterSlug": organization.cluster_slug, + } + ) + mocked_gcom_client.return_value = (instance_info, {"status_code": 200}) api_users_response = ( { @@ -367,10 +385,7 @@ def test_sync_organization_is_rbac_permissions_enabled_cloud(mocked_gcom_client, sync_organization(organization) organization.refresh_from_db() - - assert mocked_gcom_client.return_value.called_once_with("mockedToken") - assert mocked_gcom_client.return_value.is_rbac_enabled_for_stack.called_once_with(stack_id) - assert organization.is_rbac_permissions_enabled == gcom_api_response + assert organization.is_rbac_permissions_enabled == expected @pytest.mark.django_db