# What this PR does Allows public OnCall API to use Grafana service accounts for authorization. In cloud requests using a Grafana service account token also needs to provide headers for `X-Grafana-Org-Slug` and `X-Grafana-Instance-Slug` This is **alpha** functionality, it may break or be removed in the future. Going to use this on one endpoint (resolution notes) before we consider the implications across all of public API. ## Which issue(s) this PR fixes ## 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] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not required)
48 lines
2 KiB
Python
48 lines
2 KiB
Python
import typing
|
|
|
|
from apps.auth_token.exceptions import ServiceAccountDoesNotExist
|
|
from apps.grafana_plugin.helpers import GrafanaAPIClient
|
|
from apps.user_management.models import Organization
|
|
|
|
SA_ONCALL_API_NAME = "sa-autogen-OnCall"
|
|
|
|
|
|
def find_service_account(
|
|
organization: Organization, service_account_name=SA_ONCALL_API_NAME
|
|
) -> typing.Optional["GrafanaAPIClient.Types.GrafanaServiceAccount"]:
|
|
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
|
|
response, _ = grafana_api_client.get_service_account(service_account_name)
|
|
if response and "serviceAccounts" in response and response["serviceAccounts"]:
|
|
return response["serviceAccounts"][0]
|
|
return None
|
|
|
|
|
|
def create_service_account(
|
|
organization: Organization, name: str, role: str
|
|
) -> GrafanaAPIClient.Types.GrafanaServiceAccount:
|
|
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
|
|
response, _ = grafana_api_client.create_service_account(name, role)
|
|
return response
|
|
|
|
|
|
def create_service_account_token(
|
|
organization: Organization,
|
|
token_name: str,
|
|
seconds_to_live=int | None,
|
|
service_account_name=SA_ONCALL_API_NAME,
|
|
) -> typing.Optional[str]:
|
|
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=organization.api_token)
|
|
service_account = find_service_account(organization, service_account_name)
|
|
if not service_account:
|
|
raise ServiceAccountDoesNotExist
|
|
|
|
response, _ = grafana_api_client.create_service_account_token(service_account["id"], token_name, seconds_to_live)
|
|
if response:
|
|
return response["key"]
|
|
return None
|
|
|
|
|
|
def get_service_account_token_permissions(organization: Organization, token: str) -> typing.Dict[str, typing.List[str]]:
|
|
grafana_api_client = GrafanaAPIClient(api_url=organization.grafana_url, api_token=token)
|
|
permissions, _ = grafana_api_client.get_service_account_token_permissions()
|
|
return permissions
|