Merge pull request #5356 from grafana/dev

v1.13.10
This commit is contained in:
Matias Bordese 2024-12-11 16:31:09 -03:00 committed by GitHub
commit 391cbd03de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 162 additions and 42 deletions

View file

@ -29,7 +29,7 @@ To authorize, use the **Authorization** header:
```shell ```shell
# With shell, you can just pass the correct header with each request # With shell, you can just pass the correct header with each request
curl "api_endpoint_here" --header "Authorization: "api_key_here"" curl "api_endpoint_here" --header "Authorization: <api_key_here>"
``` ```
Grafana OnCall uses API keys to allow access to the API. You can request a new OnCall API key in OnCall -> Settings page. Grafana OnCall uses API keys to allow access to the API. You can request a new OnCall API key in OnCall -> Settings page.
@ -39,6 +39,19 @@ request a different API key.
The endpoint refers to the OnCall Application endpoint and can be found on the OnCall -> Settings page as well. The endpoint refers to the OnCall Application endpoint and can be found on the OnCall -> Settings page as well.
### Authentication using Service Account tokens
It is also possible to use a [service account token](https://grafana.com/docs/grafana/latest/administration/service-accounts/#service-account-tokens)
to authenticate instead of an OnCall access token. In this case you will also need to provide a
header (`X-Grafana-URL`) pointing to your Grafana stack:
```shell
# With shell, you can just pass the correct header with each request
curl "api_endpoint_here" --header "Authorization: <service account token>" --header "X-Grafana-URL: <your stack URL>"
```
Service accounts allow you to set explicit permissions for tokens as well as expire and/or disable them if needed.
## Pagination ## Pagination
List endpoints such as List Integrations or List Alert Groups return multiple objects. List endpoints such as List Integrations or List Alert Groups return multiple objects.

View file

@ -14,6 +14,8 @@ refs:
## List alert groups ## List alert groups
**Required permission**: `grafana-oncall-app.alert-groups:read`
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/" \ curl "{{API_URL}}/api/v1/alert_groups/" \
--request GET \ --request GET \
@ -97,6 +99,8 @@ These available filter parameters should be provided as `GET` arguments:
## Alert group details ## Alert group details
**Required permission**: `grafana-oncall-app.alert-groups:read`
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1" \
--request GET \ --request GET \
@ -109,6 +113,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1" \
## Acknowledge an alert group ## Acknowledge an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/acknowledge" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/acknowledge" \
--request POST \ --request POST \
@ -121,6 +127,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/acknowledge" \
## Unacknowledge an alert group ## Unacknowledge an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unacknowledge" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unacknowledge" \
--request POST \ --request POST \
@ -133,6 +141,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unacknowledge" \
## Resolve an alert group ## Resolve an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/resolve" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/resolve" \
--request POST \ --request POST \
@ -145,6 +155,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/resolve" \
## Unresolve an alert group ## Unresolve an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unresolve" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unresolve" \
--request POST \ --request POST \
@ -157,6 +169,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unresolve" \
## Silence an alert group ## Silence an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/silence" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/silence" \
--request POST \ --request POST \
@ -177,6 +191,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/silence" \
## Unsilence an alert group ## Unsilence an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unsilence" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unsilence" \
--request POST \ --request POST \
@ -189,6 +205,8 @@ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/unsilence" \
## Delete an alert group ## Delete an alert group
**Required permission**: `grafana-oncall-app.alert-groups:write`
```shell ```shell
curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/" \ curl "{{API_URL}}/api/v1/alert_groups/I68T24C13IFW1/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## List Alerts ## List Alerts
**Required permission**: `grafana-oncall-app.alert-groups:read`
```shell ```shell
curl "{{API_URL}}/api/v1/alerts/" \ curl "{{API_URL}}/api/v1/alerts/" \
--request GET \ --request GET \

View file

@ -22,6 +22,8 @@ refs:
# Escalation HTTP API # Escalation HTTP API
**Required permission**: `grafana-oncall-app.alert-groups:direct-paging` (user authentication only)
See [Manual paging integration](ref:manual-paging) for more background on how escalating to a team or user(s) works. See [Manual paging integration](ref:manual-paging) for more background on how escalating to a team or user(s) works.
## Escalate to a set of users ## Escalate to a set of users

View file

@ -14,6 +14,8 @@ refs:
## Create an escalation chain ## Create an escalation chain
**Required permission**: `grafana-oncall-app.escalation-chains:write`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_chains/" \ curl "{{API_URL}}/api/v1/escalation_chains/" \
--request POST \ --request POST \
@ -45,6 +47,8 @@ The above command returns JSON structured in the following way:
## Get an escalation chain ## Get an escalation chain
**Required permission**: `grafana-oncall-app.escalation-chains:read`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_chains/F5JU6KJET33FE/" \ curl "{{API_URL}}/api/v1/escalation_chains/F5JU6KJET33FE/" \
--request GET \ --request GET \
@ -68,6 +72,8 @@ The above command returns JSON structured in the following way:
## List escalation chains ## List escalation chains
**Required permission**: `grafana-oncall-app.escalation-chains:read`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_chains/" \ curl "{{API_URL}}/api/v1/escalation_chains/" \
--request GET \ --request GET \
@ -103,6 +109,8 @@ The above command returns JSON structured in the following way:
## Delete an escalation chain ## Delete an escalation chain
**Required permission**: `grafana-oncall-app.escalation-chains:write`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_chains/F5JU6KJET33FE/" \ curl "{{API_URL}}/api/v1/escalation_chains/F5JU6KJET33FE/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Create an escalation policy ## Create an escalation policy
**Required permission**: `grafana-oncall-app.escalation-chains:write`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_policies/" \ curl "{{API_URL}}/api/v1/escalation_policies/" \
--request POST \ --request POST \
@ -61,6 +63,8 @@ The above command returns JSON structured in the following way:
## Get an escalation policy ## Get an escalation policy
**Required permission**: `grafana-oncall-app.escalation-chains:read`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \ curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \
--request GET \ --request GET \
@ -82,6 +86,8 @@ The above command returns JSON structured in the following way:
## Update an escalation policy ## Update an escalation policy
**Required permission**: `grafana-oncall-app.escalation-chains:write`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \ curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \
--request PUT \ --request PUT \
@ -115,6 +121,8 @@ The above command returns JSON structured in the following way:
## List escalation policies ## List escalation policies
**Required permission**: `grafana-oncall-app.escalation-chains:read`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_policies/" \ curl "{{API_URL}}/api/v1/escalation_policies/" \
--request GET \ --request GET \
@ -163,6 +171,8 @@ The following available filter parameter should be provided as a `GET` argument:
## Delete an escalation policy ## Delete an escalation policy
**Required permission**: `grafana-oncall-app.escalation-chains:write`
```shell ```shell
curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \ curl "{{API_URL}}/api/v1/escalation_policies/E3GA6SJETWWJS/" \
--request DELETE \ --request DELETE \

View file

@ -23,6 +23,8 @@ refs:
## Create an integration ## Create an integration
**Required permission**: `grafana-oncall-app.integrations:write`
```shell ```shell
curl "{{API_URL}}/api/v1/integrations/" \ curl "{{API_URL}}/api/v1/integrations/" \
--request POST \ --request POST \
@ -102,6 +104,8 @@ For example, to learn how to integrate Grafana OnCall with Alertmanager refer to
## Get integration ## Get integration
**Required permission**: `grafana-oncall-app.integrations:read`
```shell ```shell
curl "{{API_URL}}/api/v1/integrations/CFRPV98RPR1U8/" \ curl "{{API_URL}}/api/v1/integrations/CFRPV98RPR1U8/" \
--request GET \ --request GET \
@ -177,6 +181,8 @@ This endpoint retrieves an integration. Integrations are sources of alerts and a
## List integrations ## List integrations
**Required permission**: `grafana-oncall-app.integrations:read`
```shell ```shell
curl "{{API_URL}}/api/v1/integrations/" \ curl "{{API_URL}}/api/v1/integrations/" \
--request GET \ --request GET \
@ -262,6 +268,8 @@ The above command returns JSON structured in the following way:
## Update integration ## Update integration
**Required permission**: `grafana-oncall-app.integrations:write`
```shell ```shell
curl "{{API_URL}}/api/v1/integrations/CFRPV98RPR1U8/" \ curl "{{API_URL}}/api/v1/integrations/CFRPV98RPR1U8/" \
--request PUT \ --request PUT \
@ -339,6 +347,8 @@ The above command returns JSON structured in the following way:
## Delete integration ## Delete integration
**Required permission**: `grafana-oncall-app.integrations:write`
Deleted integrations will stop recording new alerts from monitoring. Integration removal won't trigger removal of Deleted integrations will stop recording new alerts from monitoring. Integration removal won't trigger removal of
related alert groups or alerts. related alert groups or alerts.

View file

@ -14,6 +14,8 @@ refs:
## Create an OnCall shift ## Create an OnCall shift
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/on_call_shifts/" \ curl "{{API_URL}}/api/v1/on_call_shifts/" \
--request POST \ --request POST \
@ -77,6 +79,8 @@ For more information about recurrence rules, refer to [RFC 5545](https://tools.i
## Get OnCall shifts ## Get OnCall shifts
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \ curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \
--request GET \ --request GET \
@ -106,6 +110,8 @@ The above command returns JSON structured in the following way:
## List OnCall shifts ## List OnCall shifts
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/on_call_shifts/" \ curl "{{API_URL}}/api/v1/on_call_shifts/" \
--request GET \ --request GET \
@ -169,6 +175,8 @@ The following available filter parameters should be provided as `GET` arguments:
## Update OnCall shift ## Update OnCall shift
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \ curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \
--request PUT \ --request PUT \
@ -208,6 +216,8 @@ The above command returns JSON structured in the following way:
## Delete OnCall shift ## Delete OnCall shift
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \ curl "{{API_URL}}/api/v1/on_call_shifts/OH3V5FYQEYJ6M/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Get an organization ## Get an organization
**Required permission**: `grafana-oncall-app.other-settings:read`
This endpoint retrieves the organization object. This endpoint retrieves the organization object.
```shell ```shell
@ -41,6 +43,8 @@ The above command returns JSON structured in the following way:
## List Organizations ## List Organizations
**Required permission**: `grafana-oncall-app.other-settings:read`
```shell ```shell
curl "{{API_URL}}/api/v1/organizations/" \ curl "{{API_URL}}/api/v1/organizations/" \
--request GET \ --request GET \

View file

@ -30,6 +30,8 @@ For more details about specific fields of a webhook, refer to [Outgoing webhooks
## List webhooks ## List webhooks
**Required permission**: `grafana-oncall-app.outgoing-webhooks:read`
```shell ```shell
curl "{{API_URL}}/api/v1/webhooks/" \ curl "{{API_URL}}/api/v1/webhooks/" \
--request GET \ --request GET \
@ -75,6 +77,8 @@ The above command returns JSON structured in the following way:
## Get webhook ## Get webhook
**Required permission**: `grafana-oncall-app.outgoing-webhooks:read`
```shell ```shell
curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \ curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \
--request GET \ --request GET \
@ -108,6 +112,8 @@ The above command returns JSON structured in the following way:
## Create webhook ## Create webhook
**Required permission**: `grafana-oncall-app.outgoing-webhooks:write`
```shell ```shell
curl "{{API_URL}}/api/v1/webhooks/" \ curl "{{API_URL}}/api/v1/webhooks/" \
--request POST \ --request POST \
@ -167,6 +173,8 @@ The above command returns JSON structured in the following way:
## Update webhook ## Update webhook
**Required permission**: `grafana-oncall-app.outgoing-webhooks:write`
```shell ```shell
curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \ curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \
--request PUT \ --request PUT \
@ -201,6 +209,8 @@ The above command returns JSON structured in the following way:
## Delete webhook ## Delete webhook
**Required permission**: `grafana-oncall-app.outgoing-webhooks:write`
```shell ```shell
curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \ curl "{{API_URL}}/api/v1/webhooks/{{WEBHOOK_UID}}/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Post a personal notification rule ## Post a personal notification rule
**Required permission**: `grafana-oncall-app.user-settings:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/personal_notification_rules/" \ curl "{{API_URL}}/api/v1/personal_notification_rules/" \
--request POST \ --request POST \
@ -51,6 +53,8 @@ The above command returns JSON structured in the following way:
## Get personal notification rule ## Get personal notification rule
**Required permission**: `grafana-oncall-app.user-settings:read` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/personal_notification_rules/ND9EHN5LN1DUU/" \ curl "{{API_URL}}/api/v1/personal_notification_rules/ND9EHN5LN1DUU/" \
--request GET \ --request GET \
@ -77,6 +81,8 @@ The above command returns JSON structured in the following way:
## List personal notification rules ## List personal notification rules
**Required permission**: `grafana-oncall-app.user-settings:read` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/personal_notification_rules/" \ curl "{{API_URL}}/api/v1/personal_notification_rules/" \
--request GET \ --request GET \
@ -141,6 +147,8 @@ The following available filter parameters should be provided as `GET` arguments:
## Delete a personal notification rule ## Delete a personal notification rule
**Required permission**: `grafana-oncall-app.user-settings:write` (user authentication only)
```shell ```shell
curl "{{API_URL}}/api/v1/personal_notification_rules/NWAL6WFJNWDD8/" \ curl "{{API_URL}}/api/v1/personal_notification_rules/NWAL6WFJNWDD8/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Create a resolution note ## Create a resolution note
**Required permission**: `grafana-oncall-app.alert-groups:write`
```shell ```shell
curl "{{API_URL}}/api/v1/resolution_notes/" \ curl "{{API_URL}}/api/v1/resolution_notes/" \
--request POST \ --request POST \
@ -49,6 +51,8 @@ The above command returns JSON structured in the following way:
## Get a resolution note ## Get a resolution note
**Required permission**: `grafana-oncall-app.alert-groups:read`
```shell ```shell
curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \ curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \
--request GET \ --request GET \
@ -75,6 +79,8 @@ The above command returns JSON structured in the following way:
## List resolution notes ## List resolution notes
**Required permission**: `grafana-oncall-app.alert-groups:read`
```shell ```shell
curl "{{API_URL}}/api/v1/resolution_notes/" \ curl "{{API_URL}}/api/v1/resolution_notes/" \
--request GET \ --request GET \
@ -117,6 +123,8 @@ The following available filter parameter should be provided as a `GET` argument:
## Update a resolution note ## Update a resolution note
**Required permission**: `grafana-oncall-app.alert-groups:write`
```shell ```shell
curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \ curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \
--request PUT \ --request PUT \
@ -146,6 +154,8 @@ The above command returns JSON structured in the following way:
## Delete a resolution note ## Delete a resolution note
**Required permission**: `grafana-oncall-app.alert-groups:write`
```shell ```shell
curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \ curl "{{API_URL}}/api/v1/resolution_notes/M4BTQUS3PRHYQ/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Create a route ## Create a route
**Required permission**: `grafana-oncall-app.integrations:write`
```shell ```shell
curl "{{API_URL}}/api/v1/routes/" \ curl "{{API_URL}}/api/v1/routes/" \
--request POST \ --request POST \
@ -67,6 +69,8 @@ Routes allow you to direct different alerts to different messenger channels and
## Get a route ## Get a route
**Required permission**: `grafana-oncall-app.integrations:read`
```shell ```shell
curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \ curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \
--request GET \ --request GET \
@ -96,6 +100,8 @@ The above command returns JSON structured in the following way:
## List routes ## List routes
**Required permission**: `grafana-oncall-app.integrations:read`
```shell ```shell
curl "{{API_URL}}/api/v1/routes/" \ curl "{{API_URL}}/api/v1/routes/" \
--request GET \ --request GET \
@ -153,6 +159,8 @@ The following available filter parameters should be provided as `GET` arguments:
## Update route ## Update route
**Required permission**: `grafana-oncall-app.integrations:write`
```shell ```shell
curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \ curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \
--request PUT \ --request PUT \
@ -189,6 +197,8 @@ The above command returns JSON structured in the following way:
## Delete a route ## Delete a route
**Required permission**: `grafana-oncall-app.integrations:write`
```shell ```shell
curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \ curl "{{API_URL}}/api/v1/routes/RIYGUJXCPFHXY/" \
--request DELETE \ --request DELETE \

View file

@ -14,6 +14,8 @@ refs:
## Create a schedule ## Create a schedule
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/schedules/" \ curl "{{API_URL}}/api/v1/schedules/" \
--request POST \ --request POST \
@ -65,6 +67,8 @@ The above command returns JSON structured in the following way:
## Get a schedule ## Get a schedule
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \ curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \
--request GET \ --request GET \
@ -96,6 +100,8 @@ The above command returns JSON structured in the following way:
## List schedules ## List schedules
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/schedules/" \ curl "{{API_URL}}/api/v1/schedules/" \
--request GET \ --request GET \
@ -158,6 +164,8 @@ The following available filter parameter should be provided as a `GET` argument:
## Update a schedule ## Update a schedule
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \ curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \
--request PUT \ --request PUT \
@ -196,6 +204,8 @@ The above command returns JSON structured in the following way:
## Delete a schedule ## Delete a schedule
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \ curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \
--request DELETE \ --request DELETE \
@ -209,6 +219,8 @@ curl "{{API_URL}}/api/v1/schedules/SBM7DV7BKFUYU/" \
## Export a schedule's final shifts ## Export a schedule's final shifts
**Required permission**: `grafana-oncall-app.schedules:read`
**HTTP request** **HTTP request**
```shell ```shell

View file

@ -14,6 +14,8 @@ refs:
## Create a shift swap request ## Create a shift swap request
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/" \ curl "{{API_URL}}/api/v1/shift_swaps/" \
--request POST \ --request POST \
@ -87,6 +89,8 @@ The above command returns JSON structured in the following way:
## Get a shift swap request ## Get a shift swap request
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \ curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \
--request GET \ --request GET \
@ -145,6 +149,8 @@ The above command returns JSON structured in the following way:
## List shift swap requests ## List shift swap requests
**Required permission**: `grafana-oncall-app.schedules:read`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/" \ curl "{{API_URL}}/api/v1/shift_swaps/" \
--request GET \ --request GET \
@ -207,6 +213,8 @@ The following available filter parameters may be provided as a `GET` arguments:
## Update a shift swap request ## Update a shift swap request
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \ curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \
--request PUT \ --request PUT \
@ -271,6 +279,8 @@ The above command returns JSON structured in the following way:
## Delete a shift swap request ## Delete a shift swap request
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \ curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \
--request DELETE \ --request DELETE \
@ -284,6 +294,8 @@ curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/" \
## Take a shift swap request ## Take a shift swap request
**Required permission**: `grafana-oncall-app.schedules:write`
```shell ```shell
curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/take" \ curl "{{API_URL}}/api/v1/shift_swaps/SSRG1TDNBMJQ1NC/take" \
--request POST \ --request POST \

View file

@ -14,6 +14,8 @@ refs:
## List Slack Channels ## List Slack Channels
**Required permission**: `grafana-oncall-app.chatops:read`
```shell ```shell
curl "{{API_URL}}/api/v1/slack_channels/" \ curl "{{API_URL}}/api/v1/slack_channels/" \
--request GET \ --request GET \

View file

@ -14,6 +14,8 @@ refs:
## Get a team ## Get a team
**Required permission**: `grafana-oncall-app.user-settings:read`
This endpoint retrieves the team object. This endpoint retrieves the team object.
```shell ```shell
@ -49,6 +51,8 @@ The above command returns JSON structured in the following way:
## List Teams ## List Teams
**Required permission**: `grafana-oncall-app.user-settings:read`
```shell ```shell
curl "{{API_URL}}/api/v1/teams/" \ curl "{{API_URL}}/api/v1/teams/" \
--request GET \ --request GET \

View file

@ -16,6 +16,8 @@ refs:
## List user groups ## List user groups
**Required permission**: `grafana-oncall-app.chatops:read`
```shell ```shell
curl "{{API_URL}}/api/v1/user_groups/" \ curl "{{API_URL}}/api/v1/user_groups/" \
--request GET \ --request GET \

View file

@ -14,6 +14,8 @@ refs:
## Get a user ## Get a user
**Required permission**: `grafana-oncall-app.user-settings:read`
This endpoint retrieves the user object. This endpoint retrieves the user object.
```shell ```shell
@ -62,6 +64,8 @@ Use `{{API_URL}}/api/v1/users/current` to retrieve the current user.
## List Users ## List Users
**Required permission**: `grafana-oncall-app.user-settings:read`
```shell ```shell
curl "{{API_URL}}/api/v1/users/" \ curl "{{API_URL}}/api/v1/users/" \
--request GET \ --request GET \

View file

@ -135,11 +135,9 @@ class BasePluginAuthentication(BaseAuthentication):
user_id = context["UserID"] user_id = context["UserID"]
if context.get("IsServiceAccount", False): if context.get("IsServiceAccount", False):
# no user involved in service account requests
logger.info(f"serviceaccount request - id={user_id}")
service_account_role = context.get("Role", "None") service_account_role = context.get("Role", "None")
if service_account_role.lower() != "admin": # no user involved in service account requests
raise exceptions.AuthenticationFailed("Service account requests must have Admin or Editor role.") logger.info(f"serviceaccount request - id={user_id} - role={service_account_role}")
return None return None
try: try:
@ -361,7 +359,7 @@ class GrafanaServiceAccountAuthentication(BaseAuthentication):
organization = self.get_organization(request, auth) organization = self.get_organization(request, auth)
if not organization: if not organization:
raise exceptions.AuthenticationFailed("Invalid organization.") raise exceptions.AuthenticationFailed("Organization not found.")
if organization.is_moved: if organization.is_moved:
raise OrganizationMovedException(organization) raise OrganizationMovedException(organization)
if organization.deleted_at: if organization.deleted_at:
@ -374,9 +372,10 @@ class GrafanaServiceAccountAuthentication(BaseAuthentication):
if grafana_url: if grafana_url:
organization = Organization.objects.filter(grafana_url=grafana_url).first() organization = Organization.objects.filter(grafana_url=grafana_url).first()
if not organization: if not organization:
success = setup_organization(grafana_url, auth) # trigger a request to sync the organization
if not success: # (ignore response since we can get a 400 if sync was already triggered;
raise exceptions.AuthenticationFailed("Invalid Grafana URL.") # if organization exists, we are good)
setup_organization(grafana_url, auth)
organization = Organization.objects.filter(grafana_url=grafana_url).first() organization = Organization.objects.filter(grafana_url=grafana_url).first()
return organization return organization

View file

@ -93,7 +93,7 @@ def test_grafana_authentication_missing_org():
with pytest.raises(exceptions.AuthenticationFailed) as exc: with pytest.raises(exceptions.AuthenticationFailed) as exc:
GrafanaServiceAccountAuthentication().authenticate(request) GrafanaServiceAccountAuthentication().authenticate(request)
assert exc.value.detail == "Invalid organization." assert exc.value.detail == "Organization not found."
@pytest.mark.django_db @pytest.mark.django_db
@ -112,7 +112,7 @@ def test_grafana_authentication_invalid_grafana_url():
with pytest.raises(exceptions.AuthenticationFailed) as exc: with pytest.raises(exceptions.AuthenticationFailed) as exc:
GrafanaServiceAccountAuthentication().authenticate(request) GrafanaServiceAccountAuthentication().authenticate(request)
assert exc.value.detail == "Invalid Grafana URL." assert exc.value.detail == "Organization not found."
@pytest.mark.django_db @pytest.mark.django_db

View file

@ -6,7 +6,7 @@ from django.utils import timezone
from rest_framework.exceptions import AuthenticationFailed from rest_framework.exceptions import AuthenticationFailed
from rest_framework.test import APIRequestFactory from rest_framework.test import APIRequestFactory
from apps.auth_token.auth import BasePluginAuthentication, PluginAuthentication from apps.auth_token.auth import PluginAuthentication
INSTANCE_CONTEXT = '{"stack_id": 42, "org_id": 24, "grafana_token": "abc"}' INSTANCE_CONTEXT = '{"stack_id": 42, "org_id": 24, "grafana_token": "abc"}'
@ -176,33 +176,3 @@ def test_plugin_authentication_self_hosted_setup_new_user(make_organization, mak
assert ret_user.user_id == 12 assert ret_user.user_id == 12
assert ret_token.organization == organization assert ret_token.organization == organization
assert organization.users.count() == 1 assert organization.users.count() == 1
@pytest.mark.django_db
@pytest.mark.parametrize(
"role,expected_raises", [("Admin", False), ("Editor", True), ("Viewer", True), ("Other", True)]
)
def test_plugin_authentication_service_account(make_organization, role, expected_raises):
# Setting gcom_token_org_last_time_synced to now, so it doesn't try to sync with gcom
organization = make_organization(
stack_id=42, org_id=24, gcom_token="123", api_token="abc", gcom_token_org_last_time_synced=timezone.now()
)
headers = {
"HTTP_AUTHORIZATION": "gcom:123",
"HTTP_X-Instance-Context": INSTANCE_CONTEXT,
"HTTP_X-Grafana-Context": json.dumps({"UserId": 12, "Role": role, "IsServiceAccount": True}),
}
request = APIRequestFactory().get("/", **headers)
if expected_raises:
with pytest.raises(AuthenticationFailed):
BasePluginAuthentication().authenticate(request)
else:
ret_user, ret_token = BasePluginAuthentication().authenticate(request)
assert ret_user is None
assert ret_token.organization == organization
# PluginAuthentication should always raise an exception if the request comes from a service account
with pytest.raises(AuthenticationFailed):
PluginAuthentication().authenticate(request)