Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
from contextlib import contextmanager
|
2024-01-30 15:29:16 +08:00
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from typing import Optional
|
2022-06-03 08:09:47 -06:00
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
|
|
|
|
import pytest
|
2023-01-11 12:48:30 +01:00
|
|
|
from django.conf import settings
|
|
|
|
|
from django.test import override_settings
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2023-09-28 11:57:49 +08:00
|
|
|
from apps.alerts.models import AlertReceiveChannel
|
2023-10-19 14:39:08 -03:00
|
|
|
from apps.api.permissions import LegacyAccessControlRole
|
2024-08-02 15:08:45 -03:00
|
|
|
from apps.grafana_plugin.sync_data import SyncData, SyncSettings, SyncUser
|
2024-08-22 14:49:22 -03:00
|
|
|
from apps.user_management.models import Organization, User
|
2024-01-30 15:29:16 +08:00
|
|
|
from apps.user_management.sync import (
|
2024-08-02 15:08:45 -03:00
|
|
|
apply_sync_data,
|
2024-01-30 15:29:16 +08:00
|
|
|
cleanup_organization,
|
2024-07-31 13:12:56 -03:00
|
|
|
get_or_create_user,
|
2024-01-30 15:29:16 +08:00
|
|
|
sync_organization,
|
2024-07-31 13:12:56 -03:00
|
|
|
sync_team_members,
|
|
|
|
|
sync_teams,
|
|
|
|
|
sync_users,
|
2024-01-30 15:29:16 +08:00
|
|
|
)
|
2023-12-05 14:58:05 -05:00
|
|
|
|
|
|
|
|
MOCK_GRAFANA_INCIDENT_BACKEND_URL = "https://grafana-incident.test"
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
@contextmanager
|
2024-07-29 17:28:35 +01:00
|
|
|
def patched_grafana_api_client(organization, is_rbac_enabled_for_organization=(False, False)):
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
GRAFANA_INCIDENT_PLUGIN_BACKEND_URL_KEY = "backendUrl"
|
|
|
|
|
|
|
|
|
|
with patch("apps.user_management.sync.GrafanaAPIClient") as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.GRAFANA_INCIDENT_PLUGIN_BACKEND_URL_KEY = GRAFANA_INCIDENT_PLUGIN_BACKEND_URL_KEY
|
|
|
|
|
|
|
|
|
|
mock_client_instance = mock_grafana_api_client.return_value
|
|
|
|
|
|
|
|
|
|
mock_client_instance.get_users.return_value = [
|
|
|
|
|
{
|
|
|
|
|
"userId": 1,
|
|
|
|
|
"email": "test@test.test",
|
|
|
|
|
"name": "Test",
|
|
|
|
|
"login": "test",
|
|
|
|
|
"role": "admin",
|
|
|
|
|
"avatarUrl": "test.test/test",
|
2024-07-31 17:27:42 -03:00
|
|
|
"permissions": [{"action": "permission:all"}] if is_rbac_enabled_for_organization[0] else [],
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
mock_client_instance.get_teams.return_value = (
|
|
|
|
|
{
|
|
|
|
|
"totalCount": 1,
|
|
|
|
|
"teams": (
|
|
|
|
|
{
|
|
|
|
|
"id": 1,
|
|
|
|
|
"name": "Test",
|
|
|
|
|
"email": "test@test.test",
|
|
|
|
|
"avatarUrl": "test.test/test",
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
mock_client_instance.get_team_members.return_value = (
|
|
|
|
|
[
|
|
|
|
|
{
|
|
|
|
|
"orgId": organization.org_id,
|
|
|
|
|
"teamId": 1,
|
|
|
|
|
"userId": 1,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
None,
|
|
|
|
|
)
|
2024-10-14 10:34:33 -03:00
|
|
|
mock_client_instance.get_grafana_irm_plugin_settings.return_value = (
|
|
|
|
|
{"enabled": False, "jsonData": {}},
|
|
|
|
|
None,
|
|
|
|
|
)
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
mock_client_instance.get_grafana_incident_plugin_settings.return_value = (
|
|
|
|
|
{"enabled": True, "jsonData": {GRAFANA_INCIDENT_PLUGIN_BACKEND_URL_KEY: MOCK_GRAFANA_INCIDENT_BACKEND_URL}},
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
mock_client_instance.get_grafana_labels_plugin_settings.return_value = (
|
|
|
|
|
{"enabled": True, "jsonData": {}},
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
mock_client_instance.check_token.return_value = (None, {"connected": True})
|
|
|
|
|
mock_client_instance.is_rbac_enabled_for_organization.return_value = is_rbac_enabled_for_organization
|
|
|
|
|
|
|
|
|
|
yield mock_grafana_api_client
|
|
|
|
|
|
|
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_sync_users_for_organization(make_organization, make_user_for_organization):
|
2022-11-28 15:52:31 +00:00
|
|
|
organization = make_organization(grafana_url="https://test.test")
|
2022-06-03 08:09:47 -06:00
|
|
|
users = tuple(make_user_for_organization(organization, user_id=user_id) for user_id in (1, 2))
|
|
|
|
|
|
|
|
|
|
api_users = tuple(
|
|
|
|
|
{
|
|
|
|
|
"userId": user_id,
|
|
|
|
|
"email": "test@test.test",
|
|
|
|
|
"name": "Test",
|
|
|
|
|
"login": "test",
|
|
|
|
|
"role": "admin",
|
2022-11-28 15:52:31 +00:00
|
|
|
"avatarUrl": "/test/1234",
|
2022-11-29 09:41:56 +01:00
|
|
|
"permissions": [],
|
2022-06-03 08:09:47 -06:00
|
|
|
}
|
|
|
|
|
for user_id in (2, 3)
|
|
|
|
|
)
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_users.return_value = api_users
|
|
|
|
|
sync_users(mock_grafana_api_client, organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
assert organization.users.count() == 2
|
|
|
|
|
|
|
|
|
|
# check that excess users are deleted
|
|
|
|
|
assert not organization.users.filter(pk=users[0].pk).exists()
|
|
|
|
|
|
|
|
|
|
# check that existing users are updated
|
|
|
|
|
updated_user = organization.users.filter(pk=users[1].pk).first()
|
|
|
|
|
assert updated_user is not None
|
|
|
|
|
assert updated_user.name == api_users[0]["name"]
|
|
|
|
|
assert updated_user.email == api_users[0]["email"]
|
2024-08-15 16:20:55 +02:00
|
|
|
assert updated_user.avatar_full_url(organization) == "https://test.test/test/1234"
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
# check that missing users are created
|
|
|
|
|
created_user = organization.users.filter(user_id=api_users[1]["userId"]).first()
|
|
|
|
|
assert created_user is not None
|
|
|
|
|
assert created_user.user_id == api_users[1]["userId"]
|
|
|
|
|
assert created_user.name == api_users[1]["name"]
|
2024-08-15 16:20:55 +02:00
|
|
|
assert created_user.avatar_full_url(organization) == "https://test.test/test/1234"
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
|
2023-10-19 14:39:08 -03:00
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_sync_users_for_organization_role_none(make_organization, make_user_for_organization):
|
|
|
|
|
organization = make_organization(grafana_url="https://test.test")
|
|
|
|
|
users = tuple(make_user_for_organization(organization, user_id=user_id) for user_id in (1, 2))
|
|
|
|
|
|
|
|
|
|
api_users = tuple(
|
|
|
|
|
{
|
|
|
|
|
"userId": user_id,
|
|
|
|
|
"email": "test@test.test",
|
|
|
|
|
"name": "Test",
|
|
|
|
|
"login": "test",
|
|
|
|
|
"role": "None",
|
|
|
|
|
"avatarUrl": "/test/1234",
|
|
|
|
|
"permissions": [],
|
|
|
|
|
}
|
|
|
|
|
for user_id in (2, 3)
|
|
|
|
|
)
|
|
|
|
|
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_users.return_value = api_users
|
|
|
|
|
sync_users(mock_grafana_api_client, organization)
|
2023-10-19 14:39:08 -03:00
|
|
|
|
|
|
|
|
assert organization.users.count() == 2
|
|
|
|
|
|
|
|
|
|
# check that excess users are deleted
|
|
|
|
|
assert not organization.users.filter(pk=users[0].pk).exists()
|
|
|
|
|
|
|
|
|
|
# check that existing users are updated
|
|
|
|
|
updated_user = organization.users.filter(pk=users[1].pk).first()
|
|
|
|
|
assert updated_user is not None
|
|
|
|
|
assert updated_user.role == LegacyAccessControlRole.NONE
|
|
|
|
|
|
|
|
|
|
# check that missing users are created
|
|
|
|
|
created_user = organization.users.filter(user_id=api_users[1]["userId"]).first()
|
|
|
|
|
assert created_user is not None
|
|
|
|
|
assert created_user.user_id == api_users[1]["userId"]
|
|
|
|
|
assert created_user.role == LegacyAccessControlRole.NONE
|
|
|
|
|
|
|
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
@pytest.mark.django_db
|
2023-11-16 13:54:15 +00:00
|
|
|
def test_sync_teams_for_organization(make_organization, make_team, make_alert_receive_channel):
|
2022-06-03 08:09:47 -06:00
|
|
|
organization = make_organization()
|
2023-11-30 17:18:18 +00:00
|
|
|
teams = tuple(make_team(organization, team_id=team_id) for team_id in (1, 2, 3))
|
2023-11-16 13:54:15 +00:00
|
|
|
direct_paging_integrations = tuple(
|
|
|
|
|
make_alert_receive_channel(organization, integration=AlertReceiveChannel.INTEGRATION_DIRECT_PAGING, team=team)
|
2023-11-30 17:18:18 +00:00
|
|
|
for team in teams[:2]
|
2023-11-16 13:54:15 +00:00
|
|
|
)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
api_teams = tuple(
|
2023-11-30 17:18:18 +00:00
|
|
|
{"id": team_id, "name": "Test", "email": "test@test.test", "avatarUrl": "test.test/test"}
|
|
|
|
|
for team_id in (2, 3, 4)
|
2022-06-03 08:09:47 -06:00
|
|
|
)
|
|
|
|
|
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_teams.return_value = ({"teams": api_teams}, None)
|
|
|
|
|
sync_teams(mock_grafana_api_client, organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2023-11-30 17:18:18 +00:00
|
|
|
assert organization.teams.count() == 3
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2023-11-16 13:54:15 +00:00
|
|
|
# check that excess teams and direct paging integrations are deleted
|
2022-06-03 08:09:47 -06:00
|
|
|
assert not organization.teams.filter(pk=teams[0].pk).exists()
|
2023-11-16 13:54:15 +00:00
|
|
|
assert not organization.alert_receive_channels.filter(pk=direct_paging_integrations[0].pk).exists()
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
# check that existing teams are updated
|
|
|
|
|
updated_team = organization.teams.filter(pk=teams[1].pk).first()
|
|
|
|
|
assert updated_team is not None
|
|
|
|
|
assert updated_team.name == api_teams[0]["name"]
|
|
|
|
|
assert updated_team.email == api_teams[0]["email"]
|
2023-11-16 13:54:15 +00:00
|
|
|
assert organization.alert_receive_channels.filter(pk=direct_paging_integrations[1].pk).exists()
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
# check that missing teams are created
|
2023-11-30 17:18:18 +00:00
|
|
|
created_team = organization.teams.filter(team_id=api_teams[2]["id"]).first()
|
2022-06-03 08:09:47 -06:00
|
|
|
assert created_team is not None
|
2023-11-30 17:18:18 +00:00
|
|
|
assert created_team.team_id == api_teams[2]["id"]
|
|
|
|
|
assert created_team.name == api_teams[2]["name"]
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2025-01-06 10:53:13 -05:00
|
|
|
def _assert_teams_direct_paging_integration_is_configured_properly(integration):
|
|
|
|
|
assert integration.channel_filters.count() == 2
|
|
|
|
|
|
|
|
|
|
for route in integration.channel_filters.all():
|
|
|
|
|
if route.is_default:
|
|
|
|
|
assert route.order == 1
|
|
|
|
|
assert route.filtering_term is None
|
|
|
|
|
else:
|
|
|
|
|
assert route.order == 0
|
|
|
|
|
assert route.filtering_term == "{{ payload.oncall.important }}"
|
|
|
|
|
assert route.filtering_term_type == route.FILTERING_TERM_TYPE_JINJA2
|
|
|
|
|
|
2023-11-30 17:18:18 +00:00
|
|
|
# check that direct paging is created for created team
|
2023-09-28 11:57:49 +08:00
|
|
|
direct_paging_integration = AlertReceiveChannel.objects.get(
|
|
|
|
|
organization=organization,
|
|
|
|
|
integration=AlertReceiveChannel.INTEGRATION_DIRECT_PAGING,
|
|
|
|
|
team=created_team,
|
|
|
|
|
)
|
2025-01-06 10:53:13 -05:00
|
|
|
_assert_teams_direct_paging_integration_is_configured_properly(direct_paging_integration)
|
2023-09-28 11:57:49 +08:00
|
|
|
|
2023-11-30 17:18:18 +00:00
|
|
|
# check that direct paging is created for existing team
|
|
|
|
|
direct_paging_integration = AlertReceiveChannel.objects.get(
|
2025-01-06 10:53:13 -05:00
|
|
|
organization=organization,
|
|
|
|
|
integration=AlertReceiveChannel.INTEGRATION_DIRECT_PAGING,
|
|
|
|
|
team=teams[2],
|
2023-11-30 17:18:18 +00:00
|
|
|
)
|
2025-01-06 10:53:13 -05:00
|
|
|
_assert_teams_direct_paging_integration_is_configured_properly(direct_paging_integration)
|
2023-11-30 17:18:18 +00:00
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_sync_users_for_team(make_organization, make_user_for_organization, make_team):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
team = make_team(organization)
|
|
|
|
|
users = tuple(make_user_for_organization(organization) for _ in range(2))
|
|
|
|
|
|
|
|
|
|
api_members = (
|
|
|
|
|
{
|
|
|
|
|
"orgId": organization.org_id,
|
|
|
|
|
"teamId": team.team_id,
|
|
|
|
|
"userId": users[0].user_id,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_team_members.return_value = (api_members, None)
|
|
|
|
|
sync_team_members(mock_grafana_api_client, organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
assert team.users.count() == 1
|
|
|
|
|
assert team.users.get() == users[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
2024-07-31 13:12:56 -03:00
|
|
|
def test_sync_organization(make_organization):
|
2023-04-14 09:15:57 +02:00
|
|
|
organization = make_organization()
|
2022-06-03 08:09:47 -06:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
with patched_grafana_api_client(organization):
|
2023-04-14 09:15:57 +02:00
|
|
|
sync_organization(organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
# check that users are populated
|
|
|
|
|
assert organization.users.count() == 1
|
|
|
|
|
user = organization.users.get()
|
|
|
|
|
assert user.user_id == 1
|
|
|
|
|
|
|
|
|
|
# check that teams are populated
|
|
|
|
|
assert organization.teams.count() == 1
|
|
|
|
|
team = organization.teams.get()
|
|
|
|
|
assert team.team_id == 1
|
|
|
|
|
|
|
|
|
|
# check that team members are populated
|
|
|
|
|
assert team.users.count() == 1
|
|
|
|
|
assert team.users.get() == user
|
|
|
|
|
|
2023-01-17 13:04:50 +01:00
|
|
|
# check that is_grafana_incident_enabled flag is set
|
|
|
|
|
assert organization.is_grafana_incident_enabled is True
|
2024-01-30 15:29:16 +08:00
|
|
|
assert organization.grafana_incident_backend_url == MOCK_GRAFANA_INCIDENT_BACKEND_URL
|
|
|
|
|
|
|
|
|
|
# check that is_grafana_labels_enabled flag is set
|
|
|
|
|
assert organization.is_grafana_labels_enabled is True
|
2023-01-17 13:04:50 +01:00
|
|
|
|
2023-01-11 12:48:30 +01:00
|
|
|
|
2024-08-22 14:49:22 -03:00
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_sync_organization_invalid_api_token(make_organization):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
|
|
|
|
|
with patch("apps.user_management.sync.GrafanaAPIClient") as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.return_value.check_token.return_value = (None, {"connected": False})
|
|
|
|
|
sync_organization(organization)
|
|
|
|
|
|
|
|
|
|
organization.refresh_from_db()
|
|
|
|
|
organization.api_token_status = Organization.API_TOKEN_STATUS_FAILED
|
|
|
|
|
|
|
|
|
|
|
2024-07-29 17:28:35 +01:00
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
"is_rbac_enabled_for_organization,expected",
|
|
|
|
|
[
|
|
|
|
|
((False, False), False),
|
|
|
|
|
((True, False), True),
|
|
|
|
|
((True, True), False),
|
|
|
|
|
],
|
|
|
|
|
)
|
2023-01-11 12:48:30 +01:00
|
|
|
@override_settings(LICENSE=settings.OPEN_SOURCE_LICENSE_NAME)
|
|
|
|
|
@pytest.mark.django_db
|
2024-07-29 17:28:35 +01:00
|
|
|
def test_sync_organization_is_rbac_permissions_enabled_open_source(
|
|
|
|
|
make_organization, is_rbac_enabled_for_organization, expected
|
|
|
|
|
):
|
|
|
|
|
organization = make_organization(is_rbac_permissions_enabled=False)
|
2023-01-11 12:48:30 +01:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
with patched_grafana_api_client(organization, is_rbac_enabled_for_organization):
|
|
|
|
|
sync_organization(organization)
|
2023-01-11 12:48:30 +01:00
|
|
|
|
|
|
|
|
organization.refresh_from_db()
|
2024-07-29 17:28:35 +01:00
|
|
|
assert organization.is_rbac_permissions_enabled == expected
|
2024-07-31 17:27:42 -03:00
|
|
|
expected_permissions = [{"action": "permission:all"}] if is_rbac_enabled_for_organization[0] else []
|
|
|
|
|
assert organization.users.get().permissions == expected_permissions
|
2023-01-11 12:48:30 +01:00
|
|
|
|
|
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
@pytest.mark.parametrize(
|
2024-05-22 11:27:16 -04:00
|
|
|
"gcom_api_response,grafana_api_response,org_initial_value,org_is_rbac_permissions_enabled_expected_value",
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
[
|
|
|
|
|
# stack is in an inactive state, rely on org's previous state of is_rbac_permissions_enabled
|
2024-07-29 17:28:35 +01:00
|
|
|
(False, (False, False), False, False),
|
|
|
|
|
(False, (False, False), True, True),
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
# stack is active, Grafana API tells us RBAC is not enabled
|
2024-07-29 17:28:35 +01:00
|
|
|
(True, (False, False), True, False),
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
# stack is active, Grafana API tells us RBAC is enabled
|
2024-07-29 17:28:35 +01:00
|
|
|
(True, (True, False), False, True),
|
|
|
|
|
# stack is active, Grafana API returns error
|
|
|
|
|
(True, (False, True), True, True),
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
],
|
|
|
|
|
)
|
Revert "Refactor gcom api calls when syncing org" (#3498)
Reverts grafana/oncall#3489
Reviewing logs, it seems something broke related to [token
auth](https://ops.grafana-ops.net/explore?schemaVersion=1&panes=%7B%22ffS%22:%7B%22datasource%22:%22OP27Xzxnk%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bcluster%3D~%5C%22dev-.%2A%5C%22,%20namespace%3D%5C%22grafana-com%5C%22,%20job%3D%5C%22grafana-com%2Fgrafana-com-api%5C%22%7D%20%7C~%20%5C%22%2Finstances%2F%5Ba-z0-9%5D%2B.config%3Dtrue%5C%22%20%7C%3D%20%5C%22Grafana%20OnCall%5C%22%22,%22editorMode%22:%22code%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22OP27Xzxnk%22%7D%7D%5D,%22range%22:%7B%22from%22:%22now-1h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1).
Reverting for now, will revisit in a later PR.
2023-12-04 15:02:58 -03:00
|
|
|
@patch("apps.user_management.sync.GcomAPIClient")
|
|
|
|
|
@override_settings(LICENSE=settings.CLOUD_LICENSE_NAME)
|
2023-01-11 12:48:30 +01:00
|
|
|
@pytest.mark.django_db
|
2024-01-04 12:34:28 -03:00
|
|
|
def test_sync_organization_is_rbac_permissions_enabled_cloud(
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
mock_gcom_client,
|
|
|
|
|
make_organization,
|
|
|
|
|
gcom_api_response,
|
|
|
|
|
grafana_api_response,
|
|
|
|
|
org_initial_value,
|
|
|
|
|
org_is_rbac_permissions_enabled_expected_value,
|
2024-01-04 12:34:28 -03:00
|
|
|
):
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
stack_id = 5
|
|
|
|
|
organization = make_organization(stack_id=stack_id, is_rbac_permissions_enabled=org_initial_value)
|
|
|
|
|
mock_gcom_client.return_value.is_stack_active.return_value = gcom_api_response
|
2023-01-11 12:48:30 +01:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
assert organization.is_rbac_permissions_enabled == org_initial_value
|
2023-01-24 13:44:07 +08:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
with patched_grafana_api_client(organization, grafana_api_response) as mock_grafana_api_client:
|
|
|
|
|
sync_organization(organization)
|
2023-01-24 13:44:07 +08:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
organization.refresh_from_db()
|
2023-01-24 13:44:07 +08:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
assert organization.is_rbac_permissions_enabled == org_is_rbac_permissions_enabled_expected_value
|
2024-07-31 17:27:42 -03:00
|
|
|
expected_permissions = [{"action": "permission:all"}] if grafana_api_response[0] else []
|
|
|
|
|
assert organization.users.get().permissions == expected_permissions
|
2023-01-11 12:48:30 +01:00
|
|
|
|
2024-05-22 11:27:16 -04:00
|
|
|
mock_gcom_client.return_value.is_stack_active.assert_called_once_with(stack_id)
|
Revert "Refactor gcom api calls when syncing org" (#3498)
Reverts grafana/oncall#3489
Reviewing logs, it seems something broke related to [token
auth](https://ops.grafana-ops.net/explore?schemaVersion=1&panes=%7B%22ffS%22:%7B%22datasource%22:%22OP27Xzxnk%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22expr%22:%22%7Bcluster%3D~%5C%22dev-.%2A%5C%22,%20namespace%3D%5C%22grafana-com%5C%22,%20job%3D%5C%22grafana-com%2Fgrafana-com-api%5C%22%7D%20%7C~%20%5C%22%2Finstances%2F%5Ba-z0-9%5D%2B.config%3Dtrue%5C%22%20%7C%3D%20%5C%22Grafana%20OnCall%5C%22%22,%22editorMode%22:%22code%22,%22queryType%22:%22range%22,%22datasource%22:%7B%22type%22:%22loki%22,%22uid%22:%22OP27Xzxnk%22%7D%7D%5D,%22range%22:%7B%22from%22:%22now-1h%22,%22to%22:%22now%22%7D%7D%7D&orgId=1).
Reverting for now, will revisit in a later PR.
2023-12-04 15:02:58 -03:00
|
|
|
|
2024-05-22 11:27:16 -04:00
|
|
|
if gcom_api_response:
|
|
|
|
|
mock_grafana_api_client.return_value.is_rbac_enabled_for_organization.assert_called_once_with()
|
2022-11-29 09:41:56 +01:00
|
|
|
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_duplicate_user_ids(make_organization, make_user_for_organization):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
|
|
|
|
|
user = make_user_for_organization(organization, user_id=1)
|
2024-07-31 13:12:56 -03:00
|
|
|
api_users = [
|
|
|
|
|
{
|
|
|
|
|
"userId": 2,
|
|
|
|
|
"email": "other@test.test",
|
|
|
|
|
"name": "Other",
|
|
|
|
|
"login": "other",
|
|
|
|
|
"role": "admin",
|
|
|
|
|
"avatarUrl": "other.test/test",
|
|
|
|
|
"permissions": [],
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_users.return_value = api_users
|
|
|
|
|
sync_users(mock_grafana_api_client, organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
user.refresh_from_db()
|
|
|
|
|
|
|
|
|
|
assert user.is_active is None
|
2024-07-31 13:12:56 -03:00
|
|
|
assert organization.users.count() == 1
|
|
|
|
|
assert User.objects.filter_with_deleted(organization=organization).count() == 2
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
api_users = [
|
|
|
|
|
{
|
|
|
|
|
"userId": 1,
|
|
|
|
|
"email": "newtest@test.test",
|
|
|
|
|
"name": "New Test",
|
|
|
|
|
"login": "test",
|
|
|
|
|
"role": "admin",
|
|
|
|
|
"avatarUrl": "test.test/test",
|
2022-11-29 09:41:56 +01:00
|
|
|
"permissions": [],
|
2022-06-03 08:09:47 -06:00
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.get_users.return_value = api_users
|
|
|
|
|
sync_users(mock_grafana_api_client, organization)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
assert organization.users.count() == 1
|
|
|
|
|
assert organization.users.get().email == "newtest@test.test"
|
2024-07-31 13:12:56 -03:00
|
|
|
assert User.objects.filter_with_deleted(organization=organization).count() == 3
|
2022-06-03 08:09:47 -06:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
@pytest.mark.parametrize("is_deleted", [True, False])
|
2024-03-04 12:45:01 -07:00
|
|
|
def test_cleanup_organization_deleted(make_organization, is_deleted):
|
2022-06-03 08:09:47 -06:00
|
|
|
organization = make_organization(gcom_token="TEST_GCOM_TOKEN")
|
|
|
|
|
|
2024-03-04 12:45:01 -07:00
|
|
|
with patch("apps.grafana_plugin.helpers.client.GcomAPIClient.is_stack_deleted", return_value=is_deleted):
|
2022-09-02 14:48:03 -06:00
|
|
|
cleanup_organization(organization.id)
|
2022-06-03 08:09:47 -06:00
|
|
|
|
2023-01-05 12:42:55 +08:00
|
|
|
organization.refresh_from_db()
|
2024-03-04 12:45:01 -07:00
|
|
|
assert (organization.deleted_at is not None) == is_deleted
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_organization_not_deleted(make_organization):
|
|
|
|
|
organization = make_organization(gcom_token="TEST_GCOM_TOKEN")
|
|
|
|
|
|
|
|
|
|
with patch("apps.grafana_plugin.helpers.client.GcomAPIClient.is_stack_deleted") as mock_method:
|
|
|
|
|
exception_message = "Test Exception"
|
|
|
|
|
mock_method.side_effect = Exception(exception_message)
|
|
|
|
|
with pytest.raises(Exception) as e:
|
|
|
|
|
cleanup_organization(organization.id)
|
|
|
|
|
assert str(e.value) == exception_message
|
|
|
|
|
|
|
|
|
|
organization.refresh_from_db()
|
|
|
|
|
assert organization.deleted_at is None
|
2024-01-04 12:34:28 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
@pytest.mark.parametrize("task_lock_acquired", [True, False])
|
|
|
|
|
@patch("apps.user_management.sync.task_lock")
|
|
|
|
|
@patch("apps.user_management.sync.uuid.uuid4", return_value="random")
|
|
|
|
|
def test_sync_organization_lock(
|
|
|
|
|
_mock_uuid4,
|
|
|
|
|
mock_task_lock,
|
|
|
|
|
make_organization,
|
|
|
|
|
task_lock_acquired,
|
|
|
|
|
):
|
2024-01-04 12:34:28 -03:00
|
|
|
organization = make_organization()
|
|
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
lock_cache_key = f"sync-organization-lock-{organization.id}"
|
|
|
|
|
mock_task_lock.return_value.__enter__.return_value = task_lock_acquired
|
|
|
|
|
|
|
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
sync_organization(organization)
|
|
|
|
|
|
|
|
|
|
mock_task_lock.assert_called_once_with(lock_cache_key, "random")
|
2024-01-04 12:34:28 -03:00
|
|
|
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
if task_lock_acquired:
|
2024-07-31 13:12:56 -03:00
|
|
|
# 2 calls: get client to fetch organization data,
|
|
|
|
|
# and then another one to check token in the refactored sync function
|
|
|
|
|
assert mock_grafana_api_client.call_count == 2
|
Refactor how RBAC enabled/disabled status is determined for Grafana Cloud stacks (#4279)
# What this PR does
In cloud we are currently (somewhat) improperly determining whether or
not a Grafana stack had the `accessControlOnCall` feature flag enabled.
At first things worked fine. We would enable this feature toggle via the
Grafana Admin UI, and then the OnCall backend would read this value from
GCOM's `GET /instance/<stack_id>` endpoint (via
`config.feature_toggles`), and everything worked as expected.
There was a recent change made in `grafana/deployment_tools` to set this
feature flag to True for all stacks. However, for some reason, the GCOM
endpoint above doesn't return the `accessControlOnCall` feature toggle
value in `config.feature_toggles` if it is set in this manner (it only
returns the value if it is set via the Grafana Admin UI).
So what we should instead be doing is such instead of asking GCOM for
this feature toggle, infer whether RBAC is enabled on the stack by doing
a `HEAD /api/access-control/users/permissions/search` (this endpoint _is
only_ available on a Grafana stack if `accessControlOnCall` is enabled).
**Few caveats to this ☝️**
1. we first have to make sure that the cloud stack is in an `active`
state (ie. not paused). This is because, no matter if the
`accessControlOnCall` is enabled or not, if the stack is in a `paused`
state it will ALWAYS return `HTTP 200` which can be misleading and lead
to bugs (this feels like a bug on the Grafana API, will follow up with
core grafana team)
2. Once we roll out this change we will effectively **actually** be
enabling RBAC for OnCall for all orgs. The Identity Access team would
prefer a progressive rollout, which is why I decided to introduce the
concept of
[`settings.CLOUD_RBAC_ROLLOUT_PERCENTAGE`](https://github.com/grafana/oncall/pull/4279/files#diff-3383aef931e41e44d95829ad971641eeb98fe001be2f5da92217446d300ea1b3R918)
(see also [`Organization.
should_be_considered_for_rbac_permissioning`](https://github.com/grafana/oncall/pull/4279/files#diff-2ca9917f4f56349be39545ee8abd459be5076295d02ca3a7ec545152fcddccdfR348-R362))
## Which issue(s) this PR closes
Related to https://github.com/grafana/identity-access-team/issues/667
## Checklist
- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
show up in the autogenerated release notes.
2024-05-14 12:30:16 -04:00
|
|
|
else:
|
|
|
|
|
# task lock could not be acquired
|
|
|
|
|
mock_grafana_api_client.assert_not_called()
|
2024-01-30 15:29:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class TestSyncGrafanaLabelsPluginParams:
|
2024-04-02 14:59:03 -04:00
|
|
|
__test__ = False
|
|
|
|
|
|
2024-01-30 15:29:16 +08:00
|
|
|
response: tuple
|
|
|
|
|
expected_result: bool
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
"test_params",
|
|
|
|
|
[
|
|
|
|
|
TestSyncGrafanaLabelsPluginParams(({"enabled": True, "jsonData": {}}, None), True),
|
|
|
|
|
TestSyncGrafanaLabelsPluginParams(({"enabled": True}, None), True),
|
|
|
|
|
TestSyncGrafanaLabelsPluginParams(({"enabled": False}, None), False),
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
def test_sync_grafana_labels_plugin(make_organization, test_params: TestSyncGrafanaLabelsPluginParams):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
organization.is_grafana_labels_enabled = False # by default in tests it's true, so setting to false
|
|
|
|
|
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.return_value.get_grafana_labels_plugin_settings.return_value = test_params.response
|
|
|
|
|
sync_organization(organization)
|
|
|
|
|
organization.refresh_from_db()
|
2024-01-30 15:29:16 +08:00
|
|
|
assert organization.is_grafana_labels_enabled is test_params.expected_result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class TestSyncGrafanaIncidentParams:
|
2024-04-02 14:59:03 -04:00
|
|
|
__test__ = False
|
|
|
|
|
|
2024-01-30 15:29:16 +08:00
|
|
|
response: tuple
|
|
|
|
|
expected_flag: bool
|
|
|
|
|
expected_url: Optional[str]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
@pytest.mark.parametrize(
|
|
|
|
|
"test_params",
|
|
|
|
|
[
|
|
|
|
|
TestSyncGrafanaIncidentParams(
|
|
|
|
|
({"enabled": True, "jsonData": {"backendUrl": MOCK_GRAFANA_INCIDENT_BACKEND_URL}}, None),
|
|
|
|
|
True,
|
|
|
|
|
MOCK_GRAFANA_INCIDENT_BACKEND_URL,
|
|
|
|
|
),
|
|
|
|
|
TestSyncGrafanaIncidentParams(({"enabled": True}, None), True, None),
|
2024-01-31 11:52:20 -07:00
|
|
|
TestSyncGrafanaIncidentParams(({"enabled": True, "jsonData": None}, None), True, None),
|
2024-01-30 15:29:16 +08:00
|
|
|
# missing jsonData (sometimes this is what we get back from the Grafana API)
|
|
|
|
|
TestSyncGrafanaIncidentParams(({"enabled": False}, None), False, None), # plugin is disabled for some reason
|
|
|
|
|
],
|
|
|
|
|
)
|
|
|
|
|
def test_sync_grafana_incident_plugin(make_organization, test_params: TestSyncGrafanaIncidentParams):
|
|
|
|
|
organization = make_organization()
|
2024-07-31 13:12:56 -03:00
|
|
|
with patched_grafana_api_client(organization) as mock_grafana_api_client:
|
|
|
|
|
mock_grafana_api_client.return_value.get_grafana_incident_plugin_settings.return_value = test_params.response
|
|
|
|
|
sync_organization(organization)
|
|
|
|
|
organization.refresh_from_db()
|
2024-01-30 15:29:16 +08:00
|
|
|
assert organization.is_grafana_incident_enabled is test_params.expected_flag
|
2024-07-31 13:12:56 -03:00
|
|
|
assert organization.grafana_incident_backend_url == test_params.expected_url
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_get_or_create_user(make_organization, make_team, make_user_for_organization):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
team = make_team(organization)
|
|
|
|
|
# add an existing_user
|
|
|
|
|
existing_user = make_user_for_organization(organization)
|
|
|
|
|
team.users.add(existing_user)
|
|
|
|
|
|
|
|
|
|
assert organization.users.count() == 1
|
|
|
|
|
assert team.users.count() == 1
|
|
|
|
|
|
|
|
|
|
sync_user = SyncUser(
|
|
|
|
|
id=42,
|
|
|
|
|
email="test@test.com",
|
|
|
|
|
name="Test",
|
|
|
|
|
login="test",
|
|
|
|
|
avatar_url="https://test.com/test",
|
|
|
|
|
role="admin",
|
|
|
|
|
permissions=[],
|
|
|
|
|
teams=None,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# create user
|
|
|
|
|
user = get_or_create_user(organization, sync_user)
|
|
|
|
|
|
|
|
|
|
assert user.user_id == sync_user.id
|
|
|
|
|
assert user.name == sync_user.name
|
|
|
|
|
assert user.email == sync_user.email
|
2024-08-15 16:20:55 +02:00
|
|
|
assert user.avatar_full_url(organization) == sync_user.avatar_url
|
2024-07-31 13:12:56 -03:00
|
|
|
assert organization.users.count() == 2
|
|
|
|
|
assert team.users.count() == 1
|
|
|
|
|
|
|
|
|
|
# update user
|
|
|
|
|
sync_user.teams = [team.team_id]
|
|
|
|
|
user = get_or_create_user(organization, sync_user)
|
|
|
|
|
|
|
|
|
|
assert organization.users.count() == 2
|
|
|
|
|
assert team.users.count() == 2
|
|
|
|
|
assert team.users.filter(pk=user.pk).exists()
|
2024-08-02 15:08:45 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.django_db
|
|
|
|
|
def test_apply_sync_data_none_values(make_organization):
|
|
|
|
|
organization = make_organization()
|
|
|
|
|
sync_data = SyncData(
|
|
|
|
|
users=[
|
|
|
|
|
SyncUser(
|
|
|
|
|
id=42,
|
|
|
|
|
email="foo@bar.com",
|
|
|
|
|
name="Test",
|
|
|
|
|
login="test",
|
|
|
|
|
avatar_url="https://test.com/test",
|
|
|
|
|
role="admin",
|
|
|
|
|
permissions=None,
|
|
|
|
|
teams=None,
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
teams=None,
|
|
|
|
|
team_members=None,
|
|
|
|
|
settings=SyncSettings(
|
|
|
|
|
stack_id=organization.stack_id,
|
|
|
|
|
rbac_enabled=True,
|
|
|
|
|
org_id=organization.org_id,
|
|
|
|
|
incident_enabled=True,
|
|
|
|
|
incident_backend_url="https://test.com",
|
|
|
|
|
labels_enabled=False,
|
|
|
|
|
license=settings.CLOUD_LICENSE_NAME,
|
|
|
|
|
oncall_api_url="https://test.com",
|
|
|
|
|
grafana_token=organization.api_token,
|
|
|
|
|
oncall_token=organization.gcom_token,
|
|
|
|
|
grafana_url=organization.grafana_url,
|
2024-10-11 14:57:59 -04:00
|
|
|
irm_enabled=False,
|
2024-08-02 15:08:45 -03:00
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
with patched_grafana_api_client(organization):
|
|
|
|
|
apply_sync_data(organization, sync_data)
|
|
|
|
|
|
|
|
|
|
# assert created/updated data
|
|
|
|
|
assert organization.users.count() == 1
|
|
|
|
|
user = organization.users.get()
|
|
|
|
|
assert user.user_id == 42
|
|
|
|
|
assert user.name == "Test"
|
|
|
|
|
assert user.permissions == []
|