[0, 0, 0, "* import is invalid because \'Layout,HorizontalGroup,VerticalGroup\' from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
- [ ] It works as expected from a user's perspective.
- [ ] If this is a pre-GA feature, it is behind a feature toggle.
- [ ] The docs are updated, and if this is a [notable improvement](https://grafana.com/docs/writers-toolkit/writing-guide/contribute-release-notes/#how-to-determine-if-content-belongs-in-a-whats-new-document), it's added to our [What's New](https://grafana.com/docs/writers-toolkit/writing-guide/contribute-release-notes/) doc.
- [ ] The docs are updated, and if this is a [notable improvement](https://grafana.com/docs/writers-toolkit/contribute/release-notes/#how-to-determine-if-content-belongs-in-whats-new), it's added to our [What's New](https://grafana.com/docs/writers-toolkit/contribute/release-notes/) doc.
"comment":" please add one or more appropriate labels. Here are some tips:\r\n\r\n- if you are making an issue, TODO, or reminder for yourself or your team, please add one label that best describes the product or feature area. Please also add the issue to your project board. :rocket:\r\n\r\n- if you are making an issue for any other reason (docs typo, you found a bug, etc), please add at least one label that best describes the product or feature that you are discussing (e.g. `area/alerting`, `datasource/loki`, `type/docs`, `type/bug`, etc). [Our issue triage](https://github.com/grafana/grafana/blob/main/ISSUE_TRIAGE.md#3-categorizing-an-issue) doc also provides additional guidance on labeling. :rocket:\r\n\r\n Thank you! :heart:"
"comment":" please add one or more appropriate labels. Here are some tips:\r\n\r\n- if you are making an issue, TODO, or reminder for yourself or your team, please add one label that best describes the product or feature area. Please also add the issue to your project board. :rocket:\r\n\r\n- if you are making an issue for any other reason (docs typo, you found a bug, etc), please add at least one label that best describes the product or feature that you are discussing (e.g. `area/alerting`, `datasource/loki`, `type/docs`, `type/bug`, etc). [Our issue triage](https://github.com/grafana/grafana/blob/main/contribute/ISSUE_TRIAGE.md#3-categorize-an-issue) doc also provides additional guidance on labeling. :rocket:\r\n\r\n Thank you! :heart:"
if :${{ steps.auto_triage.outputs.triage_labels != '' }}
uses:slackapi/slack-github-action@v1.27.0
with:
payload:>
{
"icon_emoji": ":robocto:",
"username": "Auto Triager",
"type": "mrkdwn",
"text": "Auto triager found the following labels: ${{ steps.auto_triage.outputs.triage_labels }} for [issue #${{ github.event.issue.number }}](${{ github.event.issue.html_url }})",
- **Alerting:** Add setting for maximum allowed rule evaluation results [#89468](https://github.com/grafana/grafana/pull/89468), [@alexander-akhmetov](https://github.com/alexander-akhmetov)
- **Alerting:** Add warning in telegram contact point [#89397](https://github.com/grafana/grafana/pull/89397), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Central alert history part4 [#90088](https://github.com/grafana/grafana/pull/90088), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Don't crash the page when trying to filter rules by regex [#89466](https://github.com/grafana/grafana/pull/89466), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Hide edit/view rule buttons according to deleting/creating state [#90375](https://github.com/grafana/grafana/pull/90375), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Implement UI for grafana-managed recording rules [#90360](https://github.com/grafana/grafana/pull/90360), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Improve performance of /api/prometheus for large numbers of alerts. [#89268](https://github.com/grafana/grafana/pull/89268), [@stevesg](https://github.com/stevesg)
- **Alerting:** Include a list of ref_Id and aggregated datasource UIDs to alerts when state reason is NoData [#88819](https://github.com/grafana/grafana/pull/88819), [@wasim-nihal](https://github.com/wasim-nihal)
- **Alerting:** Instrument outbound requests for Loki Historian and Remote Alertmanager with tracing [#89185](https://github.com/grafana/grafana/pull/89185), [@alexweav](https://github.com/alexweav)
- **Alerting:** Limit instances on alert detail view unless in instances tab [#89368](https://github.com/grafana/grafana/pull/89368), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Make alert group editing safer [#88627](https://github.com/grafana/grafana/pull/88627), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Make whitespace more visible on labels [#90223](https://github.com/grafana/grafana/pull/90223), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Remove option to return settings from api/v1/receivers and restrict provisioning action access [#90861](https://github.com/grafana/grafana/pull/90861), [@JacobsonMT](https://github.com/JacobsonMT)
- **Alerting:** Resend resolved notifications for ResolvedRetention duration [#88938](https://github.com/grafana/grafana/pull/88938), [@JacobsonMT](https://github.com/JacobsonMT)
- **Alerting:** Show Insights page only on cloud (when required ds's are available) [#89679](https://github.com/grafana/grafana/pull/89679), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Show repeat interval in timing options meta [#89414](https://github.com/grafana/grafana/pull/89414), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Support median in reduce expressions [#91119](https://github.com/grafana/grafana/pull/91119), [@alexander-akhmetov](https://github.com/alexander-akhmetov)
- **Alerting:** Track central ash interactions [#90330](https://github.com/grafana/grafana/pull/90330), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Update alerting state history API to authorize access using RBAC [#89579](https://github.com/grafana/grafana/pull/89579), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Update warning message for Telegram parse_mode and default to empty value [#89630](https://github.com/grafana/grafana/pull/89630), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Use Runbook URL label everywhere and add validation in the alert rule… [#90523](https://github.com/grafana/grafana/pull/90523), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Use cloud notifier types for metadata on Cloud AMs [#91054](https://github.com/grafana/grafana/pull/91054), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Use stable identifier of a group when export to HCL [#90196](https://github.com/grafana/grafana/pull/90196), [@KyriosGN0](https://github.com/KyriosGN0)
- **Alerting:** Use stable identifier of a group,contact point,mute timing when export to HCL [#90917](https://github.com/grafana/grafana/pull/90917), [@KyriosGN0](https://github.com/KyriosGN0)
- **Alertmanager:** Support limits for silences [#90826](https://github.com/grafana/grafana/pull/90826), [@santihernandezc](https://github.com/santihernandezc)
- **Angular deprecation:** Disable dynamic angular inspector if CheckForPluginUpdates is false [#91194](https://github.com/grafana/grafana/pull/91194), [@xnyo](https://github.com/xnyo)
- **Auth:** Add org to role mappings support to AzureAD/Entra integration [#88861](https://github.com/grafana/grafana/pull/88861), [@mgyongyosi](https://github.com/mgyongyosi)
- **Auth:** Add organization mapping configuration to the UI [#90003](https://github.com/grafana/grafana/pull/90003), [@mgyongyosi](https://github.com/mgyongyosi)
- **Auth:** Add support for escaping colon characters in org_mapping [#89951](https://github.com/grafana/grafana/pull/89951), [@mgyongyosi](https://github.com/mgyongyosi)
- **Azure:** Add new Azure infrastructure dashboards [#88869](https://github.com/grafana/grafana/pull/88869), [@yves-chan](https://github.com/yves-chan)
- **BrowseDashboards:** Update results when starred param changes [#89944](https://github.com/grafana/grafana/pull/89944), [@Clarity-89](https://github.com/Clarity-89)
- **Canvas:** Support template variables in base URL of actions [#91227](https://github.com/grafana/grafana/pull/91227), [@nmarrs](https://github.com/nmarrs)
- **Chore:** Add missing build elements to Dockerfile [#89714](https://github.com/grafana/grafana/pull/89714), [@azilly-de](https://github.com/azilly-de)
- **Chore:** Add unit test for cloudmigration package [#88868](https://github.com/grafana/grafana/pull/88868), [@leandro-deveikis](https://github.com/leandro-deveikis)
- **Chore:** Commit results of bingo get [#90256](https://github.com/grafana/grafana/pull/90256), [@mmandrus](https://github.com/mmandrus)
- **CloudMigrations:** Change onPremToCloudMigrations feature toggle to public preview [#90757](https://github.com/grafana/grafana/pull/90757), [@mmandrus](https://github.com/mmandrus)
- **CloudWatch:** Add errorsource for QueryData [#91085](https://github.com/grafana/grafana/pull/91085), [@iwysiu](https://github.com/iwysiu)
- **CloudWatch:** Update grafana-aws-sdk for updated metrics [#91364](https://github.com/grafana/grafana/pull/91364), [@iwysiu](https://github.com/iwysiu)
- **Cloudwatch:** Clear cached PDC transport when PDC is disabled [#91357](https://github.com/grafana/grafana/pull/91357), [@njvrzm](https://github.com/njvrzm)
- **Cloudwatch:** Metrics Query Builder should clear old query [#88950](https://github.com/grafana/grafana/pull/88950), [@iwysiu](https://github.com/iwysiu)
- **Cloudwatch:** Rename Metric Query to Metric Insights [#89955](https://github.com/grafana/grafana/pull/89955), [@idastambuk](https://github.com/idastambuk)
- **Cloudwatch:** Round up endTime in GetMetricData to next minute [#89341](https://github.com/grafana/grafana/pull/89341), [@idastambuk](https://github.com/idastambuk)
- **Dashboard:** Use preferred timezone on create [#89833](https://github.com/grafana/grafana/pull/89833), [@Clarity-89](https://github.com/Clarity-89)
- **Dynatrace:** Add to list of DS with custom label logic [#90258](https://github.com/grafana/grafana/pull/90258), [@fabrizio-grafana](https://github.com/fabrizio-grafana)
- **Elasticsearch:** Decouple backend from infra/http [#90408](https://github.com/grafana/grafana/pull/90408), [@njvrzm](https://github.com/njvrzm)
- **Elasticsearch:** Decouple backend from infra/log [#90527](https://github.com/grafana/grafana/pull/90527), [@njvrzm](https://github.com/njvrzm)
- **Elasticsearch:** Decouple backend from infra/tracing [#90528](https://github.com/grafana/grafana/pull/90528), [@njvrzm](https://github.com/njvrzm)
- **Explore:** Add setting for default time offset [#90401](https://github.com/grafana/grafana/pull/90401), [@gelicia](https://github.com/gelicia)
- **Feat:** Extending report interaction with static context that can be appended to all interaction events [#88927](https://github.com/grafana/grafana/pull/88927), [@tolzhabayev](https://github.com/tolzhabayev)
- **Grafana:** Enables use of encrypted certificates with password for https [#91418](https://github.com/grafana/grafana/pull/91418), [@leandro-deveikis](https://github.com/leandro-deveikis)
- **IDToken:** Add current user's DisplayName to the ID token [#90992](https://github.com/grafana/grafana/pull/90992), [@colin-stuart](https://github.com/colin-stuart)
- **IDToken:** Add current user's Username and UID to the ID token [#90240](https://github.com/grafana/grafana/pull/90240), [@mgyongyosi](https://github.com/mgyongyosi)
- **Keybinds:** Allow move time range shortcuts (t left / t right) to be chained [#88904](https://github.com/grafana/grafana/pull/88904), [@joshhunt](https://github.com/joshhunt)
- **LibraryPanels:** Use new folder picker when creating a library panel [#89228](https://github.com/grafana/grafana/pull/89228), [@joshhunt](https://github.com/joshhunt)
- **Log:** Added panel support for filtering callbacks [#88980](https://github.com/grafana/grafana/pull/88980), [@matyax](https://github.com/matyax)
- **Logs:** Add log line to content outline when clicking on datalinks [#90207](https://github.com/grafana/grafana/pull/90207), [@gtk-grafana](https://github.com/gtk-grafana)
- **Loki:** Add option to issue forward queries [#91181](https://github.com/grafana/grafana/pull/91181), [@svennergr](https://github.com/svennergr)
- **Loki:** Added support for negative numbers in LogQL [#88719](https://github.com/grafana/grafana/pull/88719), [@matyax](https://github.com/matyax)
- **Loki:** Also replace `step` with vars [#91031](https://github.com/grafana/grafana/pull/91031), [@svennergr](https://github.com/svennergr)
- **Loki:** Remove `instant` query type from Log queries [#90137](https://github.com/grafana/grafana/pull/90137), [@svennergr](https://github.com/svennergr)
- **MSSQL:** Password auth for Azure AD [#89746](https://github.com/grafana/grafana/pull/89746), [@bossinc](https://github.com/bossinc)
- **Metrics:** Add ability to disable classic histogram for HTTP metric [#88315](https://github.com/grafana/grafana/pull/88315), [@hairyhenderson](https://github.com/hairyhenderson)
- **Nav:** Add items to saved [#89908](https://github.com/grafana/grafana/pull/89908), [@Clarity-89](https://github.com/Clarity-89)
- **OpenAPI:** Document the `/api/health` endpoint [#88203](https://github.com/grafana/grafana/pull/88203), [@julienduchesne](https://github.com/julienduchesne)
- **PanelChrome:** Use labelledby for accessible title [#88781](https://github.com/grafana/grafana/pull/88781), [@tskarhed](https://github.com/tskarhed)
- **Plugins:** Add filters by update available [#91526](https://github.com/grafana/grafana/pull/91526), [@oshirohugo](https://github.com/oshirohugo)
- **Plugins:** Add logs to for plugin management actions [#90587](https://github.com/grafana/grafana/pull/90587), [@oshirohugo](https://github.com/oshirohugo)
- **Plugins:** Disable install controls for provisioned plugin in cloud [#90479](https://github.com/grafana/grafana/pull/90479), [@oshirohugo](https://github.com/oshirohugo)
- **Plugins:** Expose functions to plugins for checking RBAC permissions [#89047](https://github.com/grafana/grafana/pull/89047), [@jackw](https://github.com/jackw)
- **Plugins:** Support > 1 levels of plugin dependencies [#90174](https://github.com/grafana/grafana/pull/90174), [@wbrowne](https://github.com/wbrowne)
- **Plugins:** Update CLI check if plugin is already installed [#91213](https://github.com/grafana/grafana/pull/91213), [@wbrowne](https://github.com/wbrowne)
- **Prometheus:** Deprecation message for SigV4 in core Prom [#90250](https://github.com/grafana/grafana/pull/90250), [@bohandley](https://github.com/bohandley)
- **Prometheus:** Reintroduce Azure audience override feature flag [#90339](https://github.com/grafana/grafana/pull/90339), [@aangelisc](https://github.com/aangelisc)
- **RBAC:** Allow plugins to use scoped actions [#90946](https://github.com/grafana/grafana/pull/90946), [@gamab](https://github.com/gamab)
- **RBAC:** Default to plugins.app:access for plugin includes [#90969](https://github.com/grafana/grafana/pull/90969), [@gamab](https://github.com/gamab)
- **Revert:** Calcs: Update diff percent to be a percent [#91563](https://github.com/grafana/grafana/pull/91563), [@Develer](https://github.com/Develer)
- **SAML:** Add button to generate a certificate and private key (Enterprise)
- **SSO:** Make SAML certificate/private key optional (Enterprise)
- **SearchV2:** Support soft deletion [#90217](https://github.com/grafana/grafana/pull/90217), [@ryantxu](https://github.com/ryantxu)
- **Select:** Add orange indicator to selected item [#88695](https://github.com/grafana/grafana/pull/88695), [@tskarhed](https://github.com/tskarhed)
- **Table panel:** Add alt and title text options to image cell type [#89930](https://github.com/grafana/grafana/pull/89930), [@codeincarnate](https://github.com/codeincarnate)
- **Tempo:** Add toggle for streaming [#88685](https://github.com/grafana/grafana/pull/88685), [@fabrizio-grafana](https://github.com/fabrizio-grafana)
- **Tempo:** Remove kind=server from metrics summary [#89419](https://github.com/grafana/grafana/pull/89419), [@joey-grafana](https://github.com/joey-grafana)
- **Tempo:** Run `go get` [#89335](https://github.com/grafana/grafana/pull/89335), [@fabrizio-grafana](https://github.com/fabrizio-grafana)
- **TimeRangePicker:** Use week start [#89765](https://github.com/grafana/grafana/pull/89765), [@Clarity-89](https://github.com/Clarity-89)
- **Tooltip:** Add tooltip support to Histogram [#89196](https://github.com/grafana/grafana/pull/89196), [@adela-almasan](https://github.com/adela-almasan)
- **Trace View:** Add Session for this span button [#89656](https://github.com/grafana/grafana/pull/89656), [@javiruiz01](https://github.com/javiruiz01)
- **Tracing:** Add regex support for span filters [#89885](https://github.com/grafana/grafana/pull/89885), [@ektasorathia](https://github.com/ektasorathia)
- **Transformations:** Add variable support to select groupingToMatrix [#88551](https://github.com/grafana/grafana/pull/88551), [@kazeborja](https://github.com/kazeborja)
- **Transformations:** Move transformation variables to general availability [#89111](https://github.com/grafana/grafana/pull/89111), [@samjewell](https://github.com/samjewell)
- **Transformations:** Promote add field from calc stat function cumulative and window calcs as generally available [#91160](https://github.com/grafana/grafana/pull/91160), [@nmarrs](https://github.com/nmarrs)
- **Transformations:** Promote format string as generally available [#91161](https://github.com/grafana/grafana/pull/91161), [@nmarrs](https://github.com/nmarrs)
- **Transformations:** Promote group to nested table as generally available [#90253](https://github.com/grafana/grafana/pull/90253), [@nmarrs](https://github.com/nmarrs)
- **Users:** Add config option to control how often last_seen is updated [#88721](https://github.com/grafana/grafana/pull/88721), [@parambath92](https://github.com/parambath92)
- **XYChart:** Promote to generally available [#91417](https://github.com/grafana/grafana/pull/91417), [@nmarrs](https://github.com/nmarrs)
### Bug fixes
- **Admin:** Fixes logic for enabled a user [#88117](https://github.com/grafana/grafana/pull/88117), [@gonvee](https://github.com/gonvee)
- **Alerting:** Add validation for path separators in the rule group edit modal [#90887](https://github.com/grafana/grafana/pull/90887), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Allow future relative time [#89405](https://github.com/grafana/grafana/pull/89405), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Disable simplified routing when internal alert manager is disabled [#90648](https://github.com/grafana/grafana/pull/90648), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Do not check evaluation interval for external rulers [#89354](https://github.com/grafana/grafana/pull/89354), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Do not count rule health for totals [#89349](https://github.com/grafana/grafana/pull/89349), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Fix contact point export 500 error and notifications/receivers missing settings [#90342](https://github.com/grafana/grafana/pull/90342), [@JacobsonMT](https://github.com/JacobsonMT)
- **Alerting:** Fix permissions for prometheus rule endpoints [#91409](https://github.com/grafana/grafana/pull/91409), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Fix persisting result fingerprint that is used by recovery threshold [#91224](https://github.com/grafana/grafana/pull/91224), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Fix rule storage to filter by group names using case-sensitive comparison [#88992](https://github.com/grafana/grafana/pull/88992), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Fix saving telegram contact point to Cloud AM config [#89182](https://github.com/grafana/grafana/pull/89182), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Fix setting of existing Telegram Chat ID value [#89287](https://github.com/grafana/grafana/pull/89287), [@tomratcliffe](https://github.com/tomratcliffe)
- **Alerting:** Fix silencing from policy instances [#90417](https://github.com/grafana/grafana/pull/90417), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
- **Alerting:** Fix some status codes returned from provisioning API. [#90117](https://github.com/grafana/grafana/pull/90117), [@stevesg](https://github.com/stevesg)
- **Alerting:** Fix stale values associated with states that have gone to NoData, unify values calculation [#89807](https://github.com/grafana/grafana/pull/89807), [@alexweav](https://github.com/alexweav)
- **Alerting:** Skip fetching alerts for unsaved dashboards [#90061](https://github.com/grafana/grafana/pull/90061), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Skip loading alert rules for dashboards when disabled [#89361](https://github.com/grafana/grafana/pull/89361), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Support `utf8_strict_mode: false` in Mimir [#90092](https://github.com/grafana/grafana/pull/90092), [@gillesdemey](https://github.com/gillesdemey)
- **Alerting:** Time interval Delete API to check for usages in alert rules [#90500](https://github.com/grafana/grafana/pull/90500), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Azure Monitor:** Add validation for namespace field in AdvancedResourcePicker when entering a forward slash [#89288](https://github.com/grafana/grafana/pull/89288), [@adamyeats](https://github.com/adamyeats)
- **AzureMonitor:** Fix out of bounds error when accessing `metricNamespaceArray` and `resourceNameArray` in `buildResourceURI` [#89222](https://github.com/grafana/grafana/pull/89222), [@adamyeats](https://github.com/adamyeats)
- **BrowseDashboards:** Prepend subpath to New Browse Dashboard actions [#89109](https://github.com/grafana/grafana/pull/89109), [@joshhunt](https://github.com/joshhunt)
- **CloudWatch:** Fix labels for raw metric search queries [#88943](https://github.com/grafana/grafana/pull/88943), [@iwysiu](https://github.com/iwysiu)
- **CloudWatch:** Fix raw queries with dimensions set [#90348](https://github.com/grafana/grafana/pull/90348), [@iwysiu](https://github.com/iwysiu)
- **Correlations:** Fix wrong target data source name in the form [#90340](https://github.com/grafana/grafana/pull/90340), [@aocenas](https://github.com/aocenas)
- **DashboardScene:** Fixes lack of re-render when updating field override properties [#88796](https://github.com/grafana/grafana/pull/88796), [@torkelo](https://github.com/torkelo)
- **DataSourcePicker:** Create new data source does not work for subpath [#90536](https://github.com/grafana/grafana/pull/90536), [@ivanortegaalba](https://github.com/ivanortegaalba)
- **Docs:** Add fixed role UUIDs to docs for terraform provisioning [#89457](https://github.com/grafana/grafana/pull/89457), [@Jguer](https://github.com/Jguer)
- **Echo:** Suppress errors from frontend-metrics API call failing [#89379](https://github.com/grafana/grafana/pull/89379), [@joshhunt](https://github.com/joshhunt)
- **Explore Metrics:** Implement grouping with metric prefixes [#89481](https://github.com/grafana/grafana/pull/89481), [@itsmylife](https://github.com/itsmylife)
- **Folders:** Fix folder pagination for cloud instances with many folders [#90008](https://github.com/grafana/grafana/pull/90008), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
- **InfluxDB:** Fix query builder produces invalid SQL query when using wildcard column name [#89032](https://github.com/grafana/grafana/pull/89032), [@wasim-nihal](https://github.com/wasim-nihal)
- **Inspect:** Include only BOM char for excel files [#88994](https://github.com/grafana/grafana/pull/88994), [@ivanortegaalba](https://github.com/ivanortegaalba)
- **Jaeger:** Fix calling of search query with the correct time range [#90320](https://github.com/grafana/grafana/pull/90320), [@EgorKluch](https://github.com/EgorKluch)
- **Metrics:** Fix internal metrics endpoint not accessible from browser if basic auth is enabled [#86904](https://github.com/grafana/grafana/pull/86904), [@wasim-nihal](https://github.com/wasim-nihal)
- **Notifications:** Redact URL from errors [#85687](https://github.com/grafana/grafana/pull/85687), [@alexweav](https://github.com/alexweav)
- **PDF:** Fix layout for page-size panel after row (Enterprise)
- **Panel:** Fix text aliasing bug when panel is loading [#89538](https://github.com/grafana/grafana/pull/89538), [@ashharrison90](https://github.com/ashharrison90)
- **Plugin extensions:** Return react components from `usePluginComponents()` [#89237](https://github.com/grafana/grafana/pull/89237), [@leventebalogh](https://github.com/leventebalogh)
- **Prometheus:** Fix query builder visualization when a query has by() clause for quantile [#88480](https://github.com/grafana/grafana/pull/88480), [@yuri-rs](https://github.com/yuri-rs)
- **QueryEditor:** Break with Scenes because the default query is not empty string [#90583](https://github.com/grafana/grafana/pull/90583), [@ivanortegaalba](https://github.com/ivanortegaalba)
- **RBAC:** Fix seeder failures when inserting duplicated permissions (Enterprise)
- **RBAC:** List only the folders that the user has access to [#88599](https://github.com/grafana/grafana/pull/88599), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
- **Scenes/Dashboards:** Fix issue where changes in panel height weren't saved [#91125](https://github.com/grafana/grafana/pull/91125), [@kaydelaney](https://github.com/kaydelaney)
- **Tempo:** Fix grpc streaming support over pdc-agent [#89883](https://github.com/grafana/grafana/pull/89883), [@taylor-s-dean](https://github.com/taylor-s-dean)
- **Tempo:** Fix query history [#89991](https://github.com/grafana/grafana/pull/89991), [@joey-grafana](https://github.com/joey-grafana)
### Breaking changes
- **Folders:** Allow folder editors and admins to create subfolders without any additional permissions [#91215](https://github.com/grafana/grafana/pull/91215), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
### Plugin development fixes & changes
- **Runtime:** Add provider and access hook for location service [#90759](https://github.com/grafana/grafana/pull/90759), [@aocenas](https://github.com/aocenas)
<!-- 11.2.0 END -->
<!-- 11.1.5 START -->
# 11.1.5 (2024-08-27)
### Bug fixes
- **Alerting:** Fix permissions for prometheus rule endpoints [#91414](https://github.com/grafana/grafana/pull/91414), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Alerting:** Fix persisting result fingerprint that is used by recovery threshold [#91290](https://github.com/grafana/grafana/pull/91290), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Auditing:** Fix a possible crash when audit logger parses responses for failed requests (Enterprise)
- **RBAC:** Fix an issue with server admins not being able to manage users in orgs that they don't belong to [#92273](https://github.com/grafana/grafana/pull/92273), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
- **RBAC:** Fix an issue with server admins not being able to manage users in orgs that they dont belong to (Enterprise)
- **RBAC:** Fix seeder failures when inserting duplicated permissions (Enterprise)
- **Snapshots:** Fix panic when snapshot_remove_expired is true [#91232](https://github.com/grafana/grafana/pull/91232), [@ryantxu](https://github.com/ryantxu)
- **VizTooltip:** Fix positioning at bottom and right edges on mobile [#92137](https://github.com/grafana/grafana/pull/92137), [@leeoniya](https://github.com/leeoniya)
### Plugin development fixes & changes
- **Bugfix:** QueryField typeahead missing background color [#92316](https://github.com/grafana/grafana/pull/92316), [@mckn](https://github.com/mckn)
<!-- 11.1.5 END -->
<!-- 11.0.4 START -->
# 11.0.4 (2024-08-27)
### Bug fixes
- **Alerting:** Fix persisting result fingerprint that is used by recovery threshold [#91328](https://github.com/grafana/grafana/pull/91328), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Auditing:** Fix a possible crash when audit logger parses responses for failed requests (Enterprise)
- **RBAC:** Fix seeder failures when inserting duplicated permissions (Enterprise)
- **Snapshots:** Fix panic when snapshot_remove_expired is true [#91330](https://github.com/grafana/grafana/pull/91330), [@ryantxu](https://github.com/ryantxu)
<!-- 11.0.4 END -->
<!-- 10.4.8 START -->
# 10.4.8 (2024-08-27)
### Bug fixes
- **Alerting:** Fix persisting result fingerprint that is used by recovery threshold [#91331](https://github.com/grafana/grafana/pull/91331), [@yuri-tceretian](https://github.com/yuri-tceretian)
- **Auditing:** Fix a possible crash when audit logger parses responses for failed requests (Enterprise)
- **RBAC:** Fix seeder failures when inserting duplicated permissions (Enterprise)
- **Snapshots:** Fix panic when snapshot_remove_expired is true [#91329](https://github.com/grafana/grafana/pull/91329), [@ryantxu](https://github.com/ryantxu)
# OAuth state max age cookie duration in seconds. Defaults to 600 seconds.
oauth_state_cookie_max_age=600
# Minimum wait time in milliseconds for the server lock retry mechanism.
# The server lock retry mechanism is used to prevent multiple Grafana instances from
# simultaneously refreshing OAuth tokens. This mechanism waits at least this amount
# of time before retrying to acquire the server lock. There are 5 retries in total.
# The wait time between retries is calculated as random(n, n + 500)
oauth_refresh_token_server_lock_min_wait_ms=1000
# limit of api_key seconds to live before expiration
api_key_max_seconds_to_live=-1
@ -1431,6 +1438,9 @@ max_age =
max_annotations_to_keep=
[recording_rules]
# Enable recording rules. You must provide write credentials below.
enabled=false
# Target URL (including write path) for recording rules.
url=
@ -1719,6 +1729,12 @@ install_token =
hide_angular_deprecation=
# Comma separated list of plugin ids for which environment variables should be forwarded. Used only when feature flag pluginsSkipHostEnvVars is enabled.
forward_host_env_vars=
# Comma separated list of plugin ids to install as part of the startup process. Used only when feature flag backgroundPluginInstaller is enabled.
preinstall=
#Controls whether preinstall plugins asynchronously (in the background) or synchronously (blocking). Useful when preinstalled plugins are used with provisioning.
preinstall_async=true
#Disables preinstall feature. It has the same effect as setting preinstall to an empty list.
preinstall_disabled=false
#################################### Grafana Live ##########################################
As such, while both terms are in use (also in our codebase) and are indeed interchangeable, TLS is the preferred term.
That said however, we have at Grafana Labs decided to use both acronyms in combination when referring to this type of
technology, i.e. _TLS/SSL_. This is in order to not confuse those who may not be aware of them being synonymous,
and SSL still being so prevalent in common discourse.
As such, while we use both terms in our codebase and documentation, we generally prefer TLS.
However, we use both acronyms in combination when referring to this type of technology, that is, _TLS/SSL_. We do this because we don't want to confuse readers who may not be aware of them being synonymous, and SSL is still prevalent in common discourse.
When end-to-end testing Grafana plugins, it's recommended to use the [`@grafana/plugin-e2e`](https://www.npmjs.com/package/@grafana/plugin-e2e?activeTab=readme) testing tool. `@grafana/plugin-e2e` extends [`@playwright/test`](https://playwright.dev/) capabilities with relevant fixtures, models, and expect matchers; enabling comprehensive end-to-end testing of Grafana plugins across multiple versions of Grafana. For information on how to get started with Plugin end-to-end testing and Playwright, checkout the [Get started](https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/get-started) guide.
When end-to-end testing Grafana plugins, a best practice is to use the [`@grafana/plugin-e2e`](https://www.npmjs.com/package/@grafana/plugin-e2e?activeTab=readme) testing tool. The `@grafana/plugin-e2e` tool extends [`@playwright/test`](https://playwright.dev/) capabilities with relevant fixtures, models, and expect matchers. Use it to enable comprehensive end-to-end testing of Grafana plugins across multiple versions of Grafana.
## Adding end-to-end tests for a core plugin
> **Note:** To learn more, refer to our documentation on [plugin development](https://grafana.com/developers/plugin-tools/) and [end-to-end plugin testing](https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/get-started).
Playwright end-to-end tests for plugins should be added to the [`e2e/plugin-e2e`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e) directory.
## Add end-to-end tests for a core plugin
1. Add a new directory that has the name as your plugin [`here`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e). This is where your plugin tests will be kept.
You can add Playwright end-to-end tests for plugins to the [`e2e/plugin-e2e`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e) directory.
2. Playwright uses [projects](https://playwright.dev/docs/test-projects) to logically group tests together. All tests in a project share the same configuration.
In the [Playwright config file](https://github.com/grafana/grafana/blob/main/playwright.config.ts), add a new project item. Make sure the `name` and the `testDir` sub directory matches the name of the directory that contains your plugin tests.
Adding `'authenticate'` to the list of dependencies and specifying `'playwright/.auth/admin.json'` as storage state will ensure all tests in your project will start already authenticated as an admin user. If you wish to use a different role for and perhaps test RBAC for some of your tests, please refer to the plugin-e2e [documentation](https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/use-authentication).
1. Add a new directory that has the name as your plugin [`here`](https://github.com/grafana/grafana/tree/main/e2e/plugin-e2e). This is the directory where your plugin tests will be kept.
1. Playwright uses [projects](https://playwright.dev/docs/test-projects) to logically group tests together. All tests in a project share the same configuration.
In the [Playwright config file](https://github.com/grafana/grafana/blob/main/playwright.config.ts), add a new project item. Make sure the `name` and the `testDir` subdirectory match the name of the directory that contains your plugin tests.
Add `'authenticate'` to the list of dependencies and specify `'playwright/.auth/admin.json'` as the storage state to ensure that all tests in your project will start already authenticated as an admin user. If you want to use a different role for and perhaps test RBAC for some of your tests, refer to our [documentation](https://grafana.com/developers/plugin-tools/e2e-test-a-plugin/use-authentication).
```ts
{
@ -24,14 +26,16 @@ Playwright end-to-end tests for plugins should be added to the [`e2e/plugin-e2e`
},
```
3. Update the [CODEOWNERS](https://github.com/grafana/grafana/blob/main/.github/CODEOWNERS/#L315) file so that your team is owner of the tests in the directory you added in step 1.
1. Update the [CODEOWNERS](https://github.com/grafana/grafana/blob/main/.github/CODEOWNERS/#L315) file so that your team is owner of the tests in the directory you added in step 1.
## Commands
- `yarn e2e:playwright`will run all Playwright tests. Optionally, you can provide the `--project mysql` argument to run tests in a certain project.
- `yarn e2e:playwright` runs all Playwright tests. Optionally, you can provide the `--project mysql` argument to run tests in a specific project.
The script above assumes you have Grafana running on `localhost:3000`. You may change this by providing environment variables.
The `yarn e2e:playwright` script assumes you have Grafana running on `localhost:3000`. You may change this with an environment variable:
`HOST=127.0.0.1 PORT=3001 yarn e2e:playwright`
- `yarn e2e:playwright:server` will start a Grafana [development server](https://github.com/grafana/grafana/blob/main/scripts/grafana-server/start-server) on port 3001 and run the Playwright tests. The development server is provisioned with the [devenv](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#add-data-sources) dashboards, data sources and apps.
The `yarn e2e:playwright:server` starts a Grafana [development server](https://github.com/grafana/grafana/blob/main/scripts/grafana-server/start-server) on port 3001 and runs the Playwright tests.
- You can provision the development server with the [devenv](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#add-data-sources) dashboards, data sources, and apps.
Grafana Labs uses a minimal [homegrown solution](../../e2e/utils/index.ts) built on top of [Cypress](https://cypress.io) for its end-to-end (E2E) tests.
@ -6,17 +6,17 @@ Important notes:
- We generally store all element identifiers ([CSS selectors](https://mdn.io/docs/Web/CSS/CSS_Selectors)) within the framework for reuse and maintainability.
- We generally do not use stubs or mocks as to fully simulate a real user.
- Cypress' promises [do not behave as you'd expect](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Mixing-Async-and-Sync-code).
- [Testing core Grafana](e2e-core.md) is different than [testing plugins](e2e-plugins.md) - core Grafana uses Cypress whereas plugins use [Playwright test](https://playwright.dev/).
- Cypress' promises [don't behave as you might expect](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress.html#Mixing-Async-and-Sync-code).
- [Testing core Grafana](e2e-core.md) is different than [testing plugins](e2e-plugins.md)—core Grafana uses Cypress whereas plugins use [Playwright test](https://playwright.dev/).
## Framework structure
Inspired by https://martinfowler.com/bliki/PageObject.html
Our framework structure is inspired by [Martin Fowler's Page Object](https://martinfowler.com/bliki/PageObject.html).
- `Selector`: A unique identifier that is used from the E2E framework to retrieve an element from the Browser
- `Page`: An abstraction for an object that contains one or more `Selectors` with `visit` function to navigate to the page.
- `Component`: An abstraction for an object that contains one or more `Selectors` but without `visit` function
- `Flow`: An abstraction that contains a sequence of actions on one or more `Pages` that can be reused and shared between tests
- **`Selector`**: A unique identifier that is used from the E2E framework to retrieve an element from the browser
- **`Page`**: An abstraction for an object that contains one or more `Selector` identifiers with the `visit` function to go to the page.
- **`Component`**: An abstraction for an object that contains one or more `Selector`identifiers but without the`visit` function
- **`Flow`**: An abstraction that contains a sequence of actions on one or more `Page` abstractions that can be reused and shared between tests
## Basic example
@ -26,13 +26,15 @@ Let's start with a simple [JSX](https://reactjs.org/docs/introducing-jsx.html) e
We _could_ target the field with a CSS selector like `.gf-form-input.login-form-input` but that would be brittle as style changes occur frequently. Furthermore there is nothing that signals to future developers that this input is part of an E2E test. At Grafana, we use `data-testid` attributes as our preferred way of defining selectors. See [Aria-Labels vs data-testid](#aria-labels-vs-data-testid) for more details.
It is possible to target the field with a CSS selector like `.gf-form-input.login-form-input`. However, doing so is a brittle solution because style changes occur frequently.
Furthermore, there is nothing that signals to future developers that this input is part of an E2E test. At Grafana, we use `data-testid` attributes as our preferred way of defining selectors. See [Aria-Labels vs data-testid](#aria-labels-vs-data-testid) for more details.
The next step is to create a `Page` representation in our E2E framework to glue the test with the real implementation using the `pageFactory` function. For that function we can supply a `url` and `selectors` like in the example below:
The next step is to create a `Page` representation in our E2E framework. Doing so glues the test with the real implementation using the `pageFactory` function. For that function we can supply a `url` and selector like in the following example:
```typescript
export const Login = {
@ -43,9 +45,9 @@ export const Login = {
};
```
Note that the selector is prefixed with `data-testid` - this is a signal to the framework to look for the selector in the `data-testid` attribute.
In this example, the selector is prefixed with `data-testid`. The prefix is a signal to the framework to look for the selector in the `data-testid` attribute.
The next step is to add the `Login` page to the `Pages` export within [_\<repo-root>/packages/grafana-e2e-selectors/src/selectors/pages.ts_](../../packages/grafana-e2e-selectors/src/selectors/pages.ts) so that it appears when we type `e2e.pages` in our IDE.
The next step is to add the `Login` page to the `Pages` export within [_\<repo-root>/packages/grafana-e2e-selectors/src/selectors/pages.ts_](../../packages/grafana-e2e-selectors/src/selectors/pages.ts) so that it appears when we type `e2e.pages` in your IDE.
```typescript
export const Pages = {
@ -56,7 +58,9 @@ export const Pages = {
};
```
Now that we have a `Page` called `Login` in our `Pages` const we can use that to add a selector in our html like shown below and now this really signals to future developers that it is part of an E2E test.
Now that we have a page called `Login` in our `Pages` const, use it to add a selector in our HTML as shown in the following example. This page really signals to future developers that it is part of an E2E test.
Example:
```jsx
import { selectors } from '@grafana/e2e-selectors';
@ -66,9 +70,8 @@ import { selectors } from '@grafana/e2e-selectors';
The last step in our example is to use our `Login` page as part of a test.
- The `url` property is used whenever we call the `visit` function and is equivalent to the Cypress' [`cy.visit()`](https://docs.cypress.io/api/commands/visit.html#Syntax).
- Any defined selector can be accessed from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [`cy.get(…)`](https://docs.cypress.io/api/commands/get.html#Syntax).
- Use the `url` property whenever you call the `visit` function. It is equivalent to the [`cy.visit()`](https://docs.cypress.io/api/commands/visit.html#Syntax) in Cypress.
- Access any defined selector from the `Login` page by invoking it. This is equivalent to the result of the Cypress function [`cy.get(…)`](https://docs.cypress.io/api/commands/get.html#Syntax).
```typescript
describe('Login test', () => {
@ -83,7 +86,7 @@ describe('Login test', () => {
## Advanced example
Let's take a look at an example that uses the same `selector` for multiple items in a list for instance. In this example app we have a list of data sources that we want to click on during an E2E test.
Let's take a look at an example that uses the same selector for multiple items in a list for instance. In this example app, there's a list of data sources that we want to click on during an E2E test.
```jsx
<ul>
@ -97,7 +100,7 @@ Let's take a look at an example that uses the same `selector` for multiple items
</ul>
```
Just as before in the basic example we'll start by creating a page abstraction using the `pageFactory` function:
Like in the basic example, start by creating a page abstraction using the `pageFactory` function:
```typescript
export const DataSources = {
@ -106,11 +109,11 @@ export const DataSources = {
};
```
You might have noticed that instead of a simple `string` as the `selector`, we're using a `function` that takes a string parameter as an argument and returns a formatted string using the argument.
You might have noticed that instead of a simple string as the selector, there's a function that takes a string parameter as an argument and returns a formatted string using the argument.
Just as before we need to add the `DataSources` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts`.
Just as before, you need to add the `DataSources` page to the exported const `Pages` in `packages/grafana-e2e-selectors/src/selectors/pages.ts`.
The next step is to use the `dataSources` selector function as in our example below:
The next step is to use the `dataSources` selector function as in the following example:
```jsx
<ul>
@ -126,7 +129,7 @@ The next step is to use the `dataSources` selector function as in our example be
</ul>
```
When this list is rendered with the data sources with names `A`, `B` and `C` ,the resulting HTML would look like:
When this list is rendered with the data sources with names `A`, `B` and `C` ,the resulting HTML looks like this:
```html
<divclass="card-item-name"data-testid="data-testid Data source list item A">A</div>
@ -134,7 +137,7 @@ When this list is rendered with the data sources with names `A`, `B` and `C` ,th
<divclass="card-item-name"data-testid="data-testid Data source list item C">C</div>
```
Now we can write our test. The one thing that differs from the [basic example](#basic-example) above is that we pass in which data source we want to click on as an argument to the selector function:
Now we can write our test. The one thing that differs from the previous [basic example](#basic-example) is that we pass in which data source we want to click as an argument to the selector function:
Our selectors are set up to work with both aria-labels and data-testid attributes. Aria-labels help assistive technologies such as screenreaders identify interactive elements of a page for our users.
Our selectors are set up to work with both `aria-label` attributes and `data-testid` attributes. The `aria-label` attributes help assistive technologies such as screen readers identify interactive elements of a page for our users.
A good example of a time to use an aria-label might be if you have a button with an X to close:
A good example of a time to use an aria-label might be if you have a button with an **X** to close:
```
<buttonaria-label="close">X<button>
```
It might be clear visually that the X closes the modal, but audibly it would not be clear for example.
It might be clear visually that the **X** closes the modal, but audibly it would not be clear, for example.
```
<buttonaria-label="close">Close<button>
@ -165,28 +168,26 @@ It might be clear visually that the X closes the modal, but audibly it would not
The example might read aloud to a user as "Close, Close" or something similar.
However adding aria-labels to elements that are already clearly labeled or not interactive can be confusing and redundant for users with assistive technologies.
However, adding an aria-label to an element that is already clearly labeled or not interactive can be confusing and redundant for users with assistive technologies.
In such cases rather than adding unnecessary aria-labels to components so as to make them selectable for testing, it is preferable to use a data attribute that would not be read aloud with an assistive technology for example:
In such cases, don't add an unnecessary aria-label to a component so as to make them selectable for testing. Instead, use a data attribute that will not be read aloud with an assistive technology. For example:
- [Proposal for removing or replacing Angular dependencies](https://github.com/grafana/grafana/pull/23048)
# Frontend style guide
Grafana Labs follows the [Airbnb React/JSX Style Guide](https://github.com/airbnb/javascript/tree/master/react) in matters pertaining to React. This guide provides highlights of the style rules we follow.
## Basic rules
@ -43,11 +8,13 @@ Generally we follow the Airbnb [React Style Guide](https://github.com/airbnb/jav
- Break large components up into sub-components.
- Use spaces for indentation.
### Naming conventions
## Naming conventions
Follow these guidelines when naming elements of your code.
Use hook useStyles2(getStyles) to memoize the styles generation and try to avoid passing props to the getStyles function and instead compose classes using Emotion CX function.
### Enums
Use PascalCase. For example:
```
// bad
@ -105,9 +79,29 @@ enum ButtonVariant {
}
```
#### Use `camelCase` for:
### Files and directories
##### Functions
Name files according to the primary export:
- When the primary export is a class or React component, use PascalCase.
- When the primary export is a function, use camelCase.
For files that export multiple utility functions, use the name that describes the responsibility of grouped utilities. For example, a file that exports math utilities should be named `math.ts`.
- Use `constants.ts` for files that export constants.
- Use `actions.ts` for files that export Redux actions.
- Use `reducers.ts` for Redux reducers.
- Use `*.test.ts(x)` for test files.
For directory names, use dash-case (sometimes called kebab-case).
Follow these guidelines for naming React components.
#### React callback props and handlers
Name callback props and handlers with an _on_ prefix. For example:
```tsx
// bad
const query_targets = [];
handleChange = () => {
};
render() {
return (
<MyComponentchanged={this.handleChange}/>
);
}
// good
const queryTargets = [];
onChange = () => {
};
render() {
return (
<MyComponentonChange={this.onChange}/>
);
}
```
##### React state and properties
#### React component constructor
Use the following convention when implementing these React components:
```typescript
interface ModalState {
// bad
IsActive: boolean;
// bad
is_active: boolean;
constructor(props) {...}
// good
isActive: boolean;
}
constructor(props: Props) {...}
```
##### Emotion class names
#### React component defaultProps
Use the following convention when implementing these React components:
```typescript
const getStyles = (theme: GrafanaTheme2) => ({
// bad
ElementWrapper: css`...`,
static defaultProps = { ... }
// good
static defaultProps: Partial<Props> = { ... }
```
#### React component definitions
Use the following convention when implementing these React components:
```jsx
// bad
['element-wrapper']: css`...`,
export class YourClass extends PureComponent { ... }
// good
elementWrapper: css({
padding: theme.spacing(1, 2),
background: theme.colors.background.secondary,
}),
});
export class YourClass extends PureComponent<{},{}> { ... }
```
Use hook useStyles2(getStyles) to memoize the styles generation and try to avoid passing props to the getStyles function and instead compose classes using emotion cx function.
Specify function return types explicitly in new code. This improves readability by being able to tell what a function returns just by looking at the signature. It also prevents errors when a function's return type is broader than expected by the author.
> **Note:**We don't have linting for this enabled because of lots of old code that needs to be fixed first.
> **Note:**Linting is not enabled for this issue because there is old code that needs to be fixed first.
- When the primary export is a class or React component, use PascalCase.
- When the primary export is a function, use camelCase.
Use PascalCase. For example:
For files exporting multiple utility functions, use the name that describes the responsibility of grouped utilities. For example, a file exporting math utilities should be named `math.ts`.
Use camelCase.
- Use `constants.ts` for files exporting constants.
- Use `actions.ts` for files exporting Redux actions.
- Use `reducers.ts` Redux reducers.
- Use `*.test.ts(x)` for test files.
```typescript
// bad
const QueryTargets = [];
// bad
const query_targets = [];
- Use kebab case for directory names: lowercase, words delimited by hyphen ( `-` ). For example, `features/new-important-feature/utils.ts`.
// good
const queryTargets = [];
```
### Code organization
## Code organization
Organize your code in a directory that encloses feature code:
- Put Redux state and domain logic code in `state` directory (i.e.`features/my-feature/state/actions.ts`).
- Put React components in `components` directory (i.e.`features/my-feature/components/ButtonPeopleDreamOf.tsx`).
- Put Redux state and domain logic code in the `state` directory (for example,`features/my-feature/state/actions.ts`).
- Put React components in the `components` directory (for example,`features/my-feature/components/ButtonPeopleDreamOf.tsx`).
- Put test files next to the test subject.
- Put containers (pages) in feature root (i.e.`features/my-feature/DashboardPage.tsx`).
- Put API function calls that isn't a redux thunk in an `api.ts` file within the same directory.
- Subcomponents can live in the component folders. Small component do not need their own folder.
- Put containers (pages) in the feature root (for example,`features/my-feature/DashboardPage.tsx`).
- Put API function calls that aren't a Redux thunk in an `api.ts` file within the same directory.
- Subcomponents should live in the component folders. Small components don't need their own folder.
- Component SASS styles should live in the same folder as component code.
For code that needs to be used by external plugin:
For code that needs to be used by an external plugin:
- Put components and types in `@grafana/ui`.
- Put data models and data utilities in `@grafana/data`.
- Put runtime services interfaces in `@grafana/runtime`.
#### Exports
### Exports
- Use named exports for all code you want to export from a file.
- Use declaration exports (i.e.`export const foo = ...`).
- Use declaration exports (that is,`export const foo = ...`).
- Avoid using default exports (for example, `export default foo`).
- Export only the code that is meant to be used outside the module.
### Comments
### Code comments
- Use [TSDoc](https://github.com/microsoft/tsdoc) comments to document your code.
- Use [react-docgen](https://github.com/reactjs/react-docgen) comments (`/** ... */`) for props documentation.
- Use inline comments for comments inside functions, classes etc.
- Use inline comments for comments inside functions, classes, etc.
- Please try to follow the [code comment guidelines](./code-comments.md) when adding comments.
### Linting
## Linting
Linting is performed using [@grafana/eslint-config](https://github.com/grafana/eslint-config-grafana).
## React
Use the following conventions when implementing React components:
## Functional components
### Props
##### Name callback props and handlers with an "on" prefix.
```tsx
// bad
handleChange = () => {
};
render() {
return (
<MyComponentchanged={this.handleChange}/>
);
}
// good
onChange = () => {
};
render() {
return (
<MyComponentonChange={this.onChange}/>
);
}
```
##### React Component definitions
```jsx
// bad
export class YourClass extends PureComponent { ... }
// good
export class YourClass extends PureComponent<{},{}> { ... }
```
##### React Component constructor
```typescript
// bad
constructor(props) {...}
// good
constructor(props: Props) {...}
```
##### React Component defaultProps
```typescript
// bad
static defaultProps = { ... }
// good
static defaultProps: Partial<Props> = { ... }
```
### How to declare functional components
We prefer using function declarations over function expressions when creating a new react functional component.
Use function declarations instead of function expressions when creating a new React functional component. For example:
- [Create React App: Remove React.FC from typescript template](https://github.com/facebook/create-react-app/pull/8177)
- [Kent C. Dodds: How to write a React Component in Typescript](https://kentcdodds.com/blog/how-to-write-a-react-component-in-typescript)
- [Kent C. Dodds: Function forms](https://kentcdodds.com/blog/function-forms)
- [Sam Hendrickx: Why you probably shouldn't use React.FC?](https://medium.com/raccoons-group/why-you-probably-shouldnt-use-react-fc-to-type-your-react-components-37ca1243dd13)
Grafana uses [Redux Toolkit](https://redux-toolkit.js.org/) to handle Redux boilerplate code.
> Some of our Reducers are used by Angular and therefore state is to be considered as mutable for those reducers.
> **Note:** Some of our reducers are used by Angular; therefore, consider state to be mutable for those reducers.
## Test functionality
Here's how to test the functioning of your Redux reducers.
### reducerTester
Fluent API that simplifies the testing of reducers
Use the Fluent API framework to simplify the testing of reducers.
#### Usage
Example of `reducerTester` in use:
```typescript
reducerTester()
.givenReducer(someReducer, initialState)
@ -21,9 +25,9 @@ reducerTester()
#### Complex usage
Sometimes you encounter a `resulting state` that contains properties that are hard to compare, such as `Dates`, but you still want to compare that other props in state are correct.
Sometimes you encounter a _resulting state_ that contains properties that are hard to compare, such as `Dates`, but you still want to evaluate whether other props in state are correct.
Then you can use`thenStatePredicateShouldEqual` function on `reducerTester` that will return the `resulting state` so that you can expect upon individual properties..
In these cases, you can evaluate individual properties by using`thenStatePredicateShouldEqual` function on `reducerTester` that will return the resulting state. For example:
```typescript
reducerTester()
@ -37,10 +41,12 @@ reducerTester()
### thunkTester
Fluent API that simplifies the testing of thunks.
Here's a Fluent API function that simplifies the testing of thunks.
It is possible to infer connected props automatically from `mapStateToProps` and `mapDispatchToProps` using a helper type `ConnectedProps` from Redux. For this to work the `connect` call has to be split into two parts.
It is possible to infer connected props automatically from `mapStateToProps` and `mapDispatchToProps` using a helper type `ConnectedProps` from Redux. For this to work properly, split the `connect` call into two parts like so:
```typescript
import { connect, ConnectedProps } from 'react-redux';
@ -80,4 +86,4 @@ class PanelEditorUnconnected extends PureComponent<Props> {}
For more examples, refer to the [Redux docs](https://react-redux.js.org/using-react-redux/static-typing#inferring-the-connected-props-automatically).
For more examples, refer to the [Redux documentation](https://react-redux.js.org/using-react-redux/static-typing#inferring-the-connected-props-automatically).
[Storybook](https://storybook.js.org/) is a tool which we use to manage our design system and the components which are a part of it. Storybook consists of _stories:_ each story represents a component and a case in which it is used. To show a wide variety of use cases is good both documentation wise and for troubleshooting -- it might be possible to reproduce a bug for an edge case in a story.
[Storybook](https://storybook.js.org/) is a tool which Grafana uses to manage our design system and its components. Storybook consists of _stories_. Each story represents a component and the case in which it is used.
To show a wide variety of use cases is good both documentation wise and for troubleshooting—it might be possible to reproduce a bug for an edge case in a story.
Storybook is:
@ -10,16 +12,22 @@ Storybook is:
## How to create stories
Stories for a component should be placed next to the component file. The Storybook file requires the same name as the component file. For example, a story for `SomeComponent.tsx` will have the file name `SomeComponent.story.tsx`. If a story should be internal, not visible in production, name the file `SomeComponent.story.internal.tsx`.
Stories for a component should be placed next to the component file. The Storybook file requires the same name as the component file. For example, a story for `SomeComponent.tsx` has the file name `SomeComponent.story.tsx`.
If a story should be internal—not visible in production—name the file `SomeComponent.story.internal.tsx`.
### Writing stories
When writing stories, we use the [CSF format](https://storybook.js.org/docs/formats/component-story-format/). For more in-depth information on writing stories, see [Storybook’s documentation on writing stories](https://storybook.js.org/docs/basics/writing-stories/).
When writing stories, we use the [CSF format](https://storybook.js.org/docs/formats/component-story-format/).
> **Note:** For more in-depth information on writing stories, see [Storybook’s documentation](https://storybook.js.org/docs/basics/writing-stories/).
With the CSF format, the default export defines some general information about the stories in the file:
- `title`: Where the component is going to live in the hierarchy
- `decorators`: A list which can contain wrappers or provide context, such as theming
- **`title`**: Where the component is going to live in the hierarchy
- **`decorators`**: A list which can contain wrappers or provide context, such as theming
Example:
```jsx
// In MyComponent.story.tsx
@ -34,18 +42,18 @@ export default {
```
When it comes to writing the actual stories, you continue in the same file with named exports. The exports are turned into the story name.
When it comes to writing the actual stories, you should continue in the same file with named exports. The exports are turned into the story name like so:
```jsx
// Will produce a story name “some story”
export const someStory = () => <MyComponent/>;
```
If you want to write cover cases with different values for props, then using knobs is usually enough. You don’t need to create a new story. This will be covered further down.
If you want to write cover cases with different values for props, then using knobs is usually enough. You don’t need to create a new story. This topic will be covered further down.
### Categorization
We currently have these categories:
We have these categories of components:
- **Docs Overview** - Guidelines and information regarding the design system
- **Forms** - Components commonly used in forms such as different kind of inputs
@ -55,7 +63,7 @@ We currently have these categories:
## Writing MDX documentation
An MDX file is basically a markdown file with the possibility to add jsx. These files are used by Storybook to create a “docs” tab.
An MDX file is a markdown file with the possibility to add JSX. These files are used by Storybook to create a “docs” tab.
### Link the MDX file to a component’s stories
@ -83,7 +91,7 @@ export default {
### MDX file structure
There are some things that the MDX file should contain:
The MDX file should contain the following items:
- When and why the component should be used
- Best practices - dos and don’ts for the component
@ -101,7 +109,9 @@ import { MyComponent } from './MyComponent';
### MDX file without a relationship to a component
An MDX file can exist by itself without any connection to a story. This can be good for writing things such as a general guidelines page. Two things are required for this to work:
An MDX file can exist by itself without any connection to a story. This can be good for writing things such as a general guidelines page.
Two conditions must be met for this to work:
- The file needs to be named `*.story.mdx`
- A `Meta` tag must exist that says where in the hierarchy the component lives. It can look like this:
@ -115,7 +125,7 @@ An MDX file can exist by itself without any connection to a story. This can be g
```
You can add parameters to the Meta tag. This example shows how to hide the tools:
You can add parameters to the `Meta` tag. This example shows how to hide the tools:
@ -128,11 +138,11 @@ You can add parameters to the Meta tag. This example shows how to hide the tools
## Documenting component properties
A quick way to get an overview of what a component does is by looking at its properties. That's why it is important that we document these in a good way.
A quick way to get an overview of what a component does is by looking at its properties. That's why it is important that you document these in a good way.
### Comments
When writing the props interface for a component, it is possible to add a comment to that specific property, which will end up in the Props table in the MDX file. The comments are generated by [react-docgen](https://github.com/reactjs/react-docgen) and are formatted by writing `/** */`.
When writing the props interface for a component, it's possible to add a comment to that specific property. When you do so, the comment will appear in the Props table in the MDX file. The comments are generated by [react-docgen](https://github.com/reactjs/react-docgen) and are formatted by writing `/** */`.
```jsx
interface MyProps {
@ -143,25 +153,28 @@ interface MyProps {
### Controls
The [controls addon](https://storybook.js.org/docs/react/essentials/controls) provides a way to interact with a component's properties dynamically and requires much less code than knobs. We're deprecating knobs in favor of using controls.
The [controls addon](https://storybook.js.org/docs/react/essentials/controls) provides a way to interact with a component's properties dynamically. It also requires much less code than knobs.
Knobs are deprecated in favor of using controls.
#### Migrating a story from Knobs to Controls
As a test, we migrated the [button story](https://github.com/grafana/grafana/blob/main/packages/grafana-ui/src/components/Button/Button.story.tsx). Here's the guide on how to migrate a story to controls.
As a test, we migrated the [button story](https://github.com/grafana/grafana/blob/main/packages/grafana-ui/src/components/Button/Button.story.tsx).
Here's the guide on how to migrate a story to controls.
1. Remove the `@storybook/addon-knobs` dependency.
2. Import the Story type from `@storybook/react`
2. Import the `Story` type from `@storybook/react`
`import { Story } from @storybook/react`
3. Import the props interface from the component you're working on (these must be exported in the component).
3. Import the props interface from the component you're working on (these must be exported in the component):
`import { Props } from './Component'`
4. Add the Story type to all stories in the file, then replace the props sent to the component
and remove any knobs.
4. Add the `Story` type to all stories in the file, then replace the props sent to the component and remove any knobs:
Before
Before:
```tsx
export const Simple = () => {
@ -172,7 +185,7 @@ As a test, we migrated the [button story](https://github.com/grafana/grafana/blo
@ -180,7 +193,7 @@ As a test, we migrated the [button story](https://github.com/grafana/grafana/blo
};
```
5. Add default props (or args in Storybook language).
5. Add default props (or `args` in Storybook language):
```tsx
Simple.args = {
@ -189,8 +202,7 @@ As a test, we migrated the [button story](https://github.com/grafana/grafana/blo
};
```
6. If the component has advanced props type (ie. other than string, number, boolean), you need to
specify these in an `argTypes`. This is done in the default export of the story.
6. If the component has advanced props type (that is, other than string, number, or Boolean), you need to specify these in an `argTypes`. Do this in the default export of the story:
```tsx
export default {
@ -204,6 +216,6 @@ As a test, we migrated the [button story](https://github.com/grafana/grafana/blo
## Best practices
- When creating a new component or writing documentation for an existing one, always cover the basic use case it was intended for with a code example.
- When creating a new component or writing documentation for an existing one, add a code example. The example should always cover the basic use case it was intended for.
- Use stories and knobs to create edge cases. If you are trying to solve a bug, try to reproduce it with a story.
- Do not create stories in the MDX, always create them in the `*.story.tsx` file.
- Do not create stories in the MDX. Instead, create them in the `*.story.tsx` file.
[Emotion](https://emotion.sh/docs/introduction) is our default-to-be approach to styling React components. It provides a way for styles to be a consequence of properties and state of a component.
[Emotion](https://emotion.sh/docs/introduction) is Grafana's default-to-be approach to styling React components. It provides a way for styles to be a consequence of properties and state of a component.
## Usage
@ -8,9 +8,9 @@ For styling components, use [Emotion's `css` function](https://emotion.sh/docs/e
### Basic styling
To access the theme in your styles, use the `useStyles` hook. It provides basic memoization and access to the theme object.
To access the Emotion theme in your styles, use the `useStyles` hook. This hook provides basic memoization and access to the theme object.
> Please remember to put `getStyles` function at the end of the file!
> **Note:**Please remember to put `getStyles` function at the end of the file!
In more complex cases, especially when you need to style multiple DOM elements in one component, or when using styles that depend on properties and/or state you
can have your getStyles function return an object with many class names and use [Emotion's `cx` function](https://emotion.sh/docs/@emotion/css#cx) to compose them.
In more complex cases, you can have the `getStyles` function return an object with many class names and use [Emotion's `cx` function](https://emotion.sh/docs/@emotion/css#cx) to compose them.
Let's say you need to style a component that has a different background depending on the `isActive` property :
This feature can be especially useful in certain use cases:
- when you need to style multiple DOM elements in one component
- when using styles that depend on properties
- when using styles that depend on state
Let's say you need to style a component that has a different background depending on the `isActive` property. For example:
The goal of this document is to address the most frequently asked "How to" questions related to unit testing.
## Best practices
## Some recommended practices for testing
- Default to the `*ByRole` queries when testing components as it encourages testing with accessibility concerns in mind. It's also possible to use `*ByLabelText` queries. However, the `*ByRole` queries are [more robust](https://testing-library.com/docs/queries/bylabeltext/#name) and are generally recommended over the former.
- Default to the `*ByRole` queries when testing components because it encourages testing with accessibility concerns in mind.
- Alternatively, you could use `*ByLabelText` queries for testing components. However, we recommend the `*ByRole` queries because they are [more robust](https://testing-library.com/docs/queries/bylabeltext/#name).
## Testing User Interactions
@ -13,7 +14,7 @@ We use the [user-event](https://testing-library.com/docs/user-event/intro) libra
There are two important considerations when working with `userEvent`:
1. All methods in `userEvent` are asynchronous, and thus require the use of `await` when called.
2. Directly calling methods from `userEvent` may not be supported in future versions. As such, it's necessary to first call `userEvent.setup()` prior to the tests. This method returns a `userEvent` instance, complete with all its methods. This setup process can be simplified using a utility function:
1. Directly calling methods from `userEvent` may not be supported in future versions. As such, it's necessary to first call `userEvent.setup()` prior to the tests. This method returns a `userEvent` instance, complete with all its methods. This setup process can be simplified using a utility function:
```tsx
import { render, screen } from '@testing-library/react';
There are a few utilities that can be useful for debugging tests:
- [screen.debug()](https://testing-library.com/docs/queries/about/#screendebug) - This function prints a human-readable representation of the document's DOM tree when called without arguments, or the DOM tree of specific node(s) when provided with arguments. It is internally using `console.log` to log the output to terminal.
- [Testing Playground](https://testing-playground.com/) - An interactive sandbox that allows testing which queries work with specific HTML elements.
- [logRoles](https://testing-library.com/docs/dom-testing-library/api-debugging/#prettydom) - A utility function that prints out all the implicit ARIA roles for a given DOM tree.
- [screen.debug()](https://testing-library.com/docs/queries/about/#screendebug) - This function prints a human-readable representation of the document's DOM tree when called without arguments, or the DOM tree of specific node or nodes when provided with arguments. It is internally using `console.log` to log the output to terminal.
- [Testing Playground](https://testing-playground.com/) - An interactive sandbox that allows testing of which queries work with specific HTML elements.
- [prettyDOM logRoles](https://testing-library.com/docs/dom-testing-library/api-debugging/#prettydom) - A utility function that prints out all the implicit ARIA roles for a given DOM tree.
## Testing Select Components
## Testing select components
Here, the [OrgRolePicker](https://github.com/grafana/grafana/blob/38863844e7ac72c7756038a1097f89632f9985ff/public/app/features/admin/OrgRolePicker.tsx) component is used as an example. This component essentially serves as a wrapper for the `Select` component, complete with its own set of options.
The recommended way to query `Select` components is by using a label. Add a `label` element and provide the `htmlFor` prop with a matching `inputId`. Alternatively, `aria-label`can be specified on the `Select`.
It is a recommended practice to query `Select` components by using a label. Add a `label` element and provide the `htmlFor` prop with a matching `inputId`. Alternatively, you can specify `aria-label` on the `Select` statement.
At times, it might be necessary to verify that the `Select` component is displaying the correct options. In such instances, the best solution is to click the `Select` component and match the desired option using the `*ByText` query.
The recommended approach for mocking the `window` object is to use Jest spies. Jest's spy functions provide a built-in mechanism for restoring mocks. This feature eliminates the need to manually save a reference to the `window` object.
The recommended approach for mocking the `window` object is to use [Jest spies](https://jestjs.io/docs/jest-object). Jest's spy functions provide a built-in mechanism for restoring mocks. This feature eliminates the need to manually save a reference to the `window` object.
```tsx
let windowSpy: jest.SpyInstance;
@ -156,7 +157,7 @@ it('should test with window', function () {
### Mocking getBackendSrv()
The `getBackendSrv()` function is used to make HTTP requests to the Grafana backend. It is possible to mock this function using the `jest.mock` method.
Use the `getBackendSrv()` function to make HTTP requests to the Grafana backend. It is possible to mock this function using the `jest.mock` method.
The `AsyncSelect` component is used to asynchronously load options. As such, it often relies on the `getBackendSrv` for loading the options.
Use the `AsyncSelect` component to asynchronously load options. This component often relies on the `getBackendSrv` for loading the options.
Here's how the test would look like for this [OrgPicker](https://github.com/grafana/grafana/blob/38863844e7ac72c7756038a1097f89632f9985ff/public/app/core/components/Select/OrgPicker.tsx) component, which uses `AsyncSelect` under the hood.
Here's what the test looks like for this [OrgPicker](https://github.com/grafana/grafana/blob/38863844e7ac72c7756038a1097f89632f9985ff/public/app/core/components/Select/OrgPicker.tsx) component, which uses `AsyncSelect` under the hood:
```tsx
import { screen, render } from '@testing-library/react';
@ -19,6 +19,7 @@ Team LBAC is available in private preview on Grafana Cloud for Loki created with
To be able to use Team LBAC rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
- Be sure that you are running Grafana Enterprise.
- Be sure that you have the permission setup to create a loki tenant in Grafana Cloud
- Be sure that you have admin data source permissions for Grafana.
@ -18,6 +18,9 @@ Team LBAC is available on Cloud for data sources created with basic authenticati
## Before you begin
To be able to use Team LBAC rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
- Be sure that you are running Grafana Enterprise.
- Be sure that you have admin data source permissions for Grafana.
If you're logged in to Grafana Cloud when you add a plugin, log out and then log back in again to use the new plugin.
### Install plugins using the Grafana Helm chart
With the Grafana Helm chart, add the plugins you want to install as a list using the `plugins` field in the your values file. For more information about the configuration, refer to [the Helm chart configuration reference](https://github.com/grafana/helm-charts/tree/main/charts/grafana#configuration).
The following YAML snippet installs v1.9.0 of the Grafana OnCall App plugin and the Redis data source plugin.
You must incorporate this snippet within your Helm values file.
Follow the instructions on the **Install** tab. You can either install the plugin with a Grafana CLI command or by downloading and uncompressing a zip file into the Grafana plugins directory. We recommend using Grafana CLI in most instances. The zip option is available if your Grafana server doesn't have access to the internet.
In previous versions of Grafana, you could only use the API for provisioning data sources and dashboards. But that required the service to be running before you started creating dashboards and you also needed to set up credentials for the HTTP API. In v5.0 we decided to improve this experience by adding a new active provisioning system that uses config files. This will make GitOps more natural as data sources and dashboards can be defined via files that can be version controlled. We hope to extend this system to later add support for users and orgs as well.
Grafana has an active provisioning system that uses configuration files.
This makes GitOps more natural since data sources and dashboards can be defined using files that can be version controlled.
## Config File
## Configuration file
See [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}) for more information on what you can configure in `grafana.ini`.
Refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}) for more information on what you can configure in `grafana.ini`.
### Config File Locations
### Configuration file locations
- Default configuration from `$WORKING_DIR/conf/defaults.ini`
- Custom configuration from `$WORKING_DIR/conf/custom.ini`
- The custom configuration file path can be overridden using the `--config` parameter
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
If you have installed Grafana using the `deb` or `rpm`
packages, then your configuration file is located at
`/etc/grafana/grafana.ini`. This path is specified in the Grafana
init.d script using `--config` file parameter.
{{% /admonition %}}
`init.d` script using the`--config` file parameter.
{{</admonition>}}
### Using Environment Variables
### Environment variables
It is possible to use environment variable interpolation in all 3 provisioning configuration types. Allowed syntax
is either `$ENV_VAR_NAME` or `${ENV_VAR_NAME}` and can be used only for values not for keys or bigger parts
of the configurations. It is not available in the dashboard's definition files just the dashboard provisioning
You can use environment variable interpolation in all three provisioning configuration types.
The allowed syntax is either `$ENV_VAR_NAME` or `${ENV_VAR_NAME}`, and it can be used only for values, not for keys or larger parts
of the configurations.
It's not available in the dashboard's definition files, just the dashboard provisioning
configuration.
Example:
```yaml
@ -51,13 +54,13 @@ datasources:
password: $PASSWORD
```
If you have a literal `$` in your value and want to avoid interpolation, `$$` can be used.
<hr/>
You can use `$$` if you have a literal `$` in your value and want to avoid interpolation.
## Configuration Management Tools
## Configuration management tools
Currently we do not provide any scripts/manifests for configuring Grafana. Rather than spending time learning and creating scripts/manifests for each tool, we think our time is better spent making Grafana easier to provision. Therefore, we heavily rely on the expertise of the community.
Currently, we don't provide any scripts or manifests for configuring Grafana.
Rather than spending time learning and creating scripts or manifests for each tool, we think our time is better spent making Grafana easier to provision.
Therefore, we heavily rely on the expertise of the community.
@ -70,12 +73,8 @@ Currently we do not provide any scripts/manifests for configuring Grafana. Rathe
## Data sources
{{% admonition type="note" %}}
Available in Grafana v5.0 and higher.
{{% /admonition %}}
You can manage data sources in Grafana by adding YAML configuration files in the [`provisioning/data sources`]({{< relref "../../setup-grafana/configure-grafana#provisioning" >}}) directory.
Each config file can contain a list of `datasources` to add or update during startup.
Each configuration file can contain a list of `datasources` to add or update during startup.
If the data source already exists, Grafana reconfigures it to match the provisioned configuration file.
The configuration file can also list data sources to automatically delete, called `deleteDatasources`.
@ -85,17 +84,17 @@ You can configure Grafana to automatically delete provisioned data sources when
To do so, add `prune: true` to the root of your provisioning file.
With this configuration, Grafana also removes the provisioned data sources if you remove the provisioning file entirely.
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
The `prune` parameter is available in Grafana v11.1 and higher.
{{% /admonition %}}
{{</admonition>}}
### Running multiple Grafana instances
If you run multiple instances of Grafana, add a version number to each data source in the configuration and increase it when you update the configuration.
Grafana updates only data sources with the same or lower version number than specified in the config.
Grafana updates only data sources with the same or lower version number than specified in the configuration.
This prevents old configurations from overwriting newer ones if you have different versions of the `datasource.yaml` file that don't define version numbers, and then restart instances at the same time.
### Example data source config file
### Example data source configuration file
This example provisions a [Graphite data source]({{< relref "../../datasources/graphite" >}}):
@ -179,16 +178,16 @@ datasources:
For provisioning examples of specific data sources, refer to that [data source's documentation]({{< relref "../../datasources" >}}).
#### JSON Data
#### JSON data
Since not all data sources have the same configuration settings, we include only the most common ones as fields.
Not all data sources have the same configuration settings. Only the most common fields are included in examples.
To provision the rest of a data source's settings, include them as a JSON blob in the `jsonData` field.
Common settings in the [built-in core data sources]({{< relref "../../datasources#built-in-core-data-sources" >}}) include:
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
Data sources tagged with _HTTP\*_ communicate using the HTTP protocol, which includes all core data source plugins except MySQL, PostgreSQL, and MSSQL.
@ -249,11 +248,14 @@ For examples of specific data sources' JSON data, refer to that [data source's d
#### Secure JSON Data
Secure JSON data is a map of settings that will be encrypted with [secret key]({{< relref "../../setup-grafana/configure-grafana#secret_key" >}}) from the Grafana config. The purpose of this is only to hide content from the users of the application. This should be used for storing TLS Cert and password that Grafana will append to the request on the server side. All of these settings are optional.
Secure JSON data is a map of settings that are encrypted with a [secret key]({{< relref "../../setup-grafana/configure-grafana#secret_key" >}}) from the Grafana configuration.
The encryption hides content from the users of the application.
This should be used for storing the TLS Cert and password that Grafana appends to the request on the server side.
All of these settings are optional.
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
The _HTTP\*_ tag denotes data sources that communicate using the HTTP protocol, including all core data source plugins except MySQL, PostgreSQL, and MS SQL.
@ -270,7 +272,7 @@ The _HTTP\*_ tag denotes data sources that communicate using the HTTP protocol,
#### Custom HTTP headers for data sources
Data sources managed with provisioning can be configured to add HTTP headers to all requests.
The header name is configured in the `jsonData` field and the header value is configured in `secureJsonData`.
Configure the header name in the `jsonData` field and the header value in `secureJsonData`.
```yaml
apiVersion: 1
@ -287,16 +289,14 @@ datasources:
## Plugins
{{% admonition type="note" %}}
Available in Grafana v7.1 and higher.
{{% /admonition %}}
You can manage plugin applications in Grafana by adding one or more YAML config files in the [`provisioning/plugins`]({{< relref "../../setup-grafana/configure-grafana#provisioning" >}}) directory. Each config file can contain a list of `apps` that will be updated during start up. Grafana updates each app to match the configuration file.
You can manage plugin applications in Grafana by adding one or more YAML configuration files in the [`provisioning/plugins`]({{< relref "../../setup-grafana/configure-grafana#provisioning" >}}) directory.
Each configuration file can contain a list of `apps` that update during start up.
Grafana updates each app to match the configuration file.
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
This feature enables you to provision plugin configurations, not the plugins themselves.
The plugins must already be installed on the Grafana instance.
{{% /admonition %}}
{{</admonition>}}
### Example plugin configuration file
@ -324,9 +324,10 @@ apps:
## Dashboards
You can manage dashboards in Grafana by adding one or more YAML config files in the [`provisioning/dashboards`]({{< relref "../../setup-grafana/configure-grafana#dashboards" >}}) directory. Each config file can contain a list of `dashboards providers` that load dashboards into Grafana from the local filesystem.
You can manage dashboards in Grafana by adding one or more YAML configuration files in the [`provisioning/dashboards`]({{< relref "../../setup-grafana/configure-grafana#dashboards" >}}) directory.
Each configuration file can contain a list of `dashboards providers` that load dashboards into Grafana from the local filesystem.
The dashboard provider config file looks somewhat like this:
The dashboard provider configuration file looks somewhat like this:
```yaml
apiVersion: 1
@ -355,40 +356,47 @@ providers:
foldersFromFilesStructure: true
```
When Grafana starts, it will update/insert all dashboards available in the configured path. Then later on poll that path every **updateIntervalSeconds** and look for updated json files and update/insert those into the database.
When Grafana starts, it updates and inserts all dashboards available in the configured path.
Then later on, Grafana polls that path every **updateIntervalSeconds**, looks for updated JSON files, and updates and inserts those into the database.
> **Note:** Dashboards are provisioned to the root level if the `folder` option is missing or empty.
#### Making changes to a provisioned dashboard
It's possible to make changes to a provisioned dashboard in the Grafana UI. However, it is not possible to automatically save the changes back to the provisioning source.
If `allowUiUpdates` is set to `true` and you make changes to a provisioned dashboard, you can `Save` the dashboard then changes will be persisted to the Grafana database.
While you can change a provisioned dashboard in the Grafana UI, those changes can't be saved back to the provisioning source.
If `allowUiUpdates` is set to `true` and you make changes to a provisioned dashboard, you can `Save` the dashboard, then changes persist to the Grafana database.
> **Note:**
> If a provisioned dashboard is saved from the UI and then later updated from the source, the dashboard stored in the database will always be overwritten. The `version` property in the JSON file will not affect this, even if it is lower than the existing dashboard.
>
> If a provisioned dashboard is saved from the UI and the source is removed, the dashboard stored in the database will be deleted unless the configuration option `disableDeletion` is set to true.
{{<admonitiontype="note">}}
If a provisioned dashboard is saved from the UI and then later updated from the source, the dashboard stored in the database will always be overwritten. The `version` property in the JSON file won't affect this, even if it's lower than the version of the existing dashboard.
If a provisioned dashboard is saved from the UI and the source is removed, the dashboard stored in the database is deleted unless the configuration option `disableDeletion` is set to `true`.
{{</admonition>}}
If `allowUiUpdates` is configured to `false`, you are not able to make changes to a provisioned dashboard. When you click `Save`, Grafana brings up a _Cannot save provisioned dashboard_ dialog. The screenshot below illustrates this behavior.
Grafana offers options to export the JSON definition of a dashboard. Either `Copy JSON to Clipboard` or `Save JSON to file` can help you synchronize your dashboard changes back to the provisioning source.
Note: The JSON definition in the input field when using `Copy JSON to Clipboard` or `Save JSON to file` will have the `id` field automatically removed to aid the provisioning workflow.
{{<admonitiontype="note">}}
The JSON definition in the input field when using `Copy JSON to Clipboard` or `Save JSON to file` has the `id` field automatically removed to aid the provisioning workflow.
If the dashboard in the JSON file contains an [UID]({{< relref "../../dashboards/build-dashboards/view-dashboard-json-model" >}}), Grafana forces insert/update on that UID. This allows you to migrate dashboards between Grafana instances and provisioning Grafana from configuration without breaking the URLs given because the new dashboard URL uses the UID as identifier.
When Grafana starts, it updates/inserts all dashboards available in the configured folders. If you modify the file, then the dashboard is also updated.
By default, Grafana deletes dashboards in the database if the file is removed. You can disable this behavior using the `disableDeletion` setting.
If the dashboard in the JSON file contains an [UID]({{< relref "../../dashboards/build-dashboards/view-dashboard-json-model" >}}), Grafana forces insert/update on that UID.
This allows you to migrate dashboards between Grafana instances and provisioning Grafana from configuration without breaking the URLs given because the new dashboard URL uses the UID as identifier.
When Grafana starts, it updates and inserts all dashboards available in the configured folders.
If you modify the file, then the dashboard is also updated.
By default, Grafana deletes dashboards in the database if the file is removed.
You can disable this behavior using the `disableDeletion` setting.
{{% admonition type="note" %}}
{{<admonitiontype="note">}}
Provisioning allows you to overwrite existing dashboards
which leads to problems if you reuse settings that are supposed to be unique.
Be careful not to reuse the same `title` multiple times within a folder
or `uid` within the same installation as this will cause weird behaviors.
{{% /admonition %}}
or `uid` within the same installation as this causes weird behaviors.
{{</admonition>}}
### Provision folders structure from filesystem to Grafana
@ -406,7 +414,7 @@ For example, to replicate these dashboards structure from the filesystem to Graf
└── /resources_dashboard.json
```
you need to specify just this short provision configuration file.
You need to specify just this short provision configuration file.
```yaml
apiVersion: 1
@ -420,32 +428,24 @@ providers:
foldersFromFilesStructure: true
```
`server` and `application`will become new folders in Grafana menu.
In this example, `server` and `application` become new folders in the Grafana menu.
{{% admonition type="note" %}}
`folder` and `folderUid` options should be empty or missing to make `foldersFromFilesStructure` work.
{{% /admonition %}}
{{<admonitiontype="note">}}
The `folder` and `folderUid` options should be empty or missing to make `foldersFromFilesStructure` work.
{{% admonition type="note" %}}
To provision dashboards to the root level, store them in the root of your `path`.
{{% /admonition %}}
{{<admonitiontype="note">}}
This feature doesn't currently allow you to create nested folder structures, that is, where you have folders within folders.
You can't create nested folders structures, where you have folders within folders.
{{</admonition>}}
## Alerting
For information on provisioning Grafana Alerting, refer to [Provision Grafana Alerting resources]({{< relref "../../alerting/set-up/provision-alerting-resources/" >}}).
### Supported Settings
### Supported settings
The following sections detail the supported settings and secure settings for each alert notification type. Secure settings are stored encrypted in the database and you add them to `secure_settings` in the YAML file instead of `settings`.
{{% admonition type="note" %}}
Secure settings is supported since Grafana v7.2.
{{% /admonition %}}
#### Alert notification `pushover`
| Name | Secure setting |
@ -504,6 +504,18 @@ Secure settings is supported since Grafana v7.2.
Available in [Grafana Enterprise]({{< relref "../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
RBAC provides a standardized way of granting, changing, and revoking access when it comes to viewing and modifying Grafana resources, such as dashboards, reports, and administrative settings.
@ -43,7 +123,7 @@ RBAC roles contain multiple permissions, each of which has an action and a scope
- **Action:**`datasources:read`
- **Scope:**`datasources:*`
For information on the RBAC API refer to [RBAC API](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/developers/http_api/access_control/#rbac-api).
For information on the RBAC API refer to [RBAC API](ref:api-rbac).
### Basic roles
@ -77,8 +157,8 @@ You can use RBAC to modify the permissions associated with any basic role, which
Note that any modification to any of these basic role is not propagated to the other basic roles.
For example, if you modify Viewer basic role and grant additional permission, Editors or Admins won't have that additional grant.
For more information about the permissions associated with each basic role, refer to [Basic role definitions]({{< relref "./rbac-fixed-basic-role-definitions/#basic-role-assignments" >}}).
To interact with the API and view or modify basic roles permissions, refer to [the table]({{< relref "./manage-rbac-roles/#basic-role-uid-mapping" >}}) that maps basic role names to the associated UID.
For more information about the permissions associated with each basic role, refer to [Basic role definitions](ref:rbac-role-definitions-basic-role-assignments).
To interact with the API and view or modify basic roles permissions, refer to [the table](ref:rbac-basic-role-uid-mapping) that maps basic role names to the associated UID.
{{% admonition type="note" %}}
You cannot use a service account to modify basic roles via the RBAC API. To update basic roles, you must be a Grafana administrator and use basic authentication with the request.
@ -86,31 +166,31 @@ You cannot use a service account to modify basic roles via the RBAC API. To upda
### Fixed roles
Grafana Enterprise includes the ability for you to assign discrete fixed roles to users, teams, and service accounts. This gives you fine-grained control over user permissions than you would have with basic roles alone. These roles are called "fixed" because you cannot change or delete fixed roles. You can also create _custom_ roles of your own; see more information in the [custom roles section]({{< relref "#custom-roles" >}}) below.
Grafana Enterprise includes the ability for you to assign discrete fixed roles to users, teams, and service accounts. This gives you fine-grained control over user permissions than you would have with basic roles alone. These roles are called "fixed" because you cannot change or delete fixed roles. You can also create _custom_ roles of your own; see more information in the [custom roles section](#custom-roles) below.
Assign fixed roles when the basic roles do not meet your permission requirements. For example, you might want a user with the basic viewer role to also edit dashboards. Or, you might want anyone with the editor role to also add and manage users. Fixed roles provide users more granular access to create, view, and update the following Grafana resources:
To learn more about the permissions you can grant for each resource, refer to [RBAC role definitions]({{< relref "./rbac-fixed-basic-role-definitions/" >}}).
To learn more about the permissions you can grant for each resource, refer to [RBAC role definitions](ref:rbac-role-definitions).
### Custom roles
@ -126,11 +206,11 @@ Consider creating a custom role when fixed roles do not meet your permissions re
You can use either of the following methods to create, assign, and manage custom roles:
- Grafana provisioning: You can use a YAML file to configure roles. For more information about using provisioning to create custom roles, refer to [Manage RBAC roles]({{< relref "./manage-rbac-roles/" >}}). For more information about using provisioning to assign RBAC roles to users or teams, refer to [Assign RBAC roles]({{< relref "./assign-rbac-roles/" >}}).
- RBAC API: As an alternative, you can use the Grafana HTTP API to create and manage roles. For more information about the HTTP API, refer to [RBAC API]({{< relref "../../../developers/http_api/access_control/" >}}).
- Grafana provisioning: You can use a YAML file to configure roles. For more information about using provisioning to create custom roles, refer to [Manage RBAC roles](ref:rbac-manage-rbac-roles). For more information about using provisioning to assign RBAC roles to users or teams, refer to [Assign RBAC roles](ref:rbac-assign-rbac-roles).
- RBAC API: As an alternative, you can use the Grafana HTTP API to create and manage roles. For more information about the HTTP API, refer to [RBAC API](ref:api-rbac).
### Limitation
If you have created a folder with the name `General` or `general`, you cannot manage its permissions with RBAC.
If you set [folder permissions]({{< relref "../../user-management/manage-dashboard-permissions/#grant-dashboard-folder-permissions" >}}) for a folder named `General` or `general`, the system disregards the folder when RBAC is enabled.
If you set [folder permissions](ref:folder-permissions) for a folder named `General` or `general`, the system disregards the folder when RBAC is enabled.
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
In this topic you'll learn how to use the role picker, provisioning, and the HTTP API to assign fixed and custom roles to users and teams.
@ -34,10 +60,10 @@ In both cases, the assignment applies only to the user, team or service account
**Before you begin:**
- [Plan your RBAC rollout strategy]({{< relref "./plan-rbac-rollout-strategy/" >}}).
- [Plan your RBAC rollout strategy](ref:plan-rbac-rollout-strategy).
- Identify the fixed roles that you want to assign to the user, team or service account.
For more information about available fixed roles, refer to [RBAC role definitions]({{< relref "./rbac-fixed-basic-role-definitions/" >}}).
For more information about available fixed roles, refer to [RBAC role definitions](ref:rbac-role-definitions).
- Ensure that your own user account has the correct permissions:
- If you are assigning permissions to a user, team or service account within an organization, you must have organization administrator or server administrator permissions.
@ -52,7 +78,7 @@ In both cases, the assignment applies only to the user, team or service account
1. Sign in to Grafana.
2. Switch to the organization that contains the user, team or service account.
For more information about switching organizations, refer to [Switch organizations]({{< relref "../../../user-management/user-preferences/_index.md#switch-organizations" >}}).
For more information about switching organizations, refer to [Switch organizations](/docs/grafana/<GRAFANA_VERSION>/administration/user-management/user-preferences/#switch-organizations).
3. In the left-side menu, click **Administration**, **Users and access**, and then **Users**, **Teams**, or **Service accounts**.
4. In the **Role** column, select the fixed role that you want to assign to the user, team, or service account.
@ -73,8 +99,8 @@ Instead of using the Grafana role picker, you can use file-based provisioning to
**Before you begin:**
- Refer to [Role provisioning]({{< relref "./rbac-grafana-provisioning/" >}})
- Ensure that the team to which you are adding the fixed role exists. For more information about creating teams, refer to [Manage teams]({{< relref "../../../team-management/" >}})
- Refer to [Role provisioning](ref:rbac-grafana-provisioning)
- Ensure that the team to which you are adding the fixed role exists. For more information about creating teams, refer to [Manage teams](/docs/grafana/<GRAFANA_VERSION>/administration/team-management/)
**To assign a role to a team:**
@ -83,12 +109,12 @@ Instead of using the Grafana role picker, you can use file-based provisioning to
1. Refer to the following table to add attributes and values.
| `roles` | Enter the custom role or custom roles you want to create/update. |
| `roles > name` | Enter the name of the custom role. |
| `roles > version` | Enter the custom role version number. Role assignments are independent of the role version number. |
| `roles > global` | Enter `true`. You can specify the `orgId` otherwise. |
| `roles > permissions` | Enter the permissions `action` and `scope` values. For more information about permissions actions and scopes, refer to [RBAC permissions, actions, and scopes]({{< relref "./custom-role-actions-scopes/" >}}) |
| `roles > permissions` | Enter the permissions `action` and `scope` values. For more information about permissions actions and scopes, refer to [RBAC permissions, actions, and scopes](ref:custom-role-actions-scopes) |
| `teams` | Enter the team or teams to which you are adding the custom role. |
| `teams > orgId` | Because teams belong to organizations, you must add the `orgId` value. |
| `teams > name` | Enter the name of the team. |
@ -96,11 +122,11 @@ Instead of using the Grafana role picker, you can use file-based provisioning to
| `teams > roles > name` | Enter the name of the role. |
| `teams > roles > global` | Enter `true`, or specify `orgId` of the role you want to assign to the team. Fixed roles are global. |
For more information about managing custom roles, refer to [Create custom roles using provisioning]({{< relref "./manage-rbac-roles/#create-custom-roles-using-provisioning" >}}).
For more information about managing custom roles, refer to [Create custom roles using provisioning](ref:manage-rbac-roles-create-custom-roles-using-provisioning).
1. Reload the provisioning configuration file.
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations]({{< relref "../../../../developers/http_api/admin/#reload-provisioning-configurations" >}}).
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations](/docs/grafana/<GRAFANA_VERSION>/developers/http_api/admin/#reload-provisioning-configurations).
The following example creates the `custom:users:writer` role and assigns it to the `user writers` and `user admins` teams along with the `fixed:users:writer` role:
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
The table below describes all RBAC configuration options. Like any other Grafana configuration, you can apply these options as [environment variables]({{< relref "../../../../setup-grafana/configure-grafana/#configure-with-environment-variables" >}}).
The table below describes all RBAC configuration options. Like any other Grafana configuration, you can apply these options as [environment variables](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#override-configuration-with-environment-variables).
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
{{<admonitiontype="note">}}
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
{{</admonition>}}
A permission is comprised of an action and a scope. When creating a custom role, consider the actions the user can perform and the resource(s) on which they can perform those actions.
A permission is comprised of an action and a scope. When creating a custom role, consider the actions the user can perform and the resources on which they can perform those actions.
To learn more about the Grafana resources to which you can apply RBAC, refer to [Resources with RBAC permissions]({{< relref "../#fixed-roles" >}}).
To learn more about the Grafana resources to which you can apply RBAC, refer to [Resources with RBAC permissions](ref:rbac-fixed-roles).
- **Action:** An action describes what tasks a user can perform on a resource.
- **Scope:** A scope describes where an action can be performed, such as reading a specific user profile. In this example, a permission is associated with the scope `users:<userId>` to the relevant role.
@ -29,222 +40,223 @@ To learn more about the Grafana resources to which you can apply RBAC, refer to
The following list contains role-based access control actions.
| `alert.instances.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alerts and silences in data sources that support alerting. |
| `alert.instances.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage alerts and silences in data sources that support alerting. |
| `alert.instances:create` | n/a | Create silences in the current organization. |
| `alert.instances:read` | n/a | Read alerts and silences in the current organization. |
| `alert.instances:write` | n/a | Update and expire silences in the current organization. |
| `alert.notifications.external:read` | `datasources:*`<br>`datasources:uid:*` | Read templates, contact points, notification policies, and mute timings in data sources that support alerting. |
| `alert.notifications.external:write` | `datasources:*`<br>`datasources:uid:*` | Manage templates, contact points, notification policies, and mute timings in data sources that support alerting. |
| `alert.notifications:write` | n/a | Manage templates, contact points, notification policies, and mute timings in the current organization. |
| `alert.notifications:read` | n/a | Read all templates, contact points, notification policies, and mute timings in the current organization. |
| `alert.rules.external:read` | `datasources:*`<br>`datasources:uid:*` | Read alert rules in data sources that support alerting (Prometheus, Mimir, and Loki) |
| `alert.rules.external:write` | `datasources:*`<br>`datasources:uid:*` | Create, update, and delete alert rules in data sources that support alerting (Mimir and Loki). |
| `alert.rules:create` | `folders:*`<br>`folders:uid:*` | Create Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:delete` | `folders:*`<br>`folders:uid:*` | Delete Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:read` | `folders:*`<br>`folders:uid:*` | Read Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:write` | `folders:*`<br>`folders:uid:*` | Update Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.silences:create` | `folders:*`<br>`folders:uid:*` | Create rule-specific silences in a folder and its subfolders. |
| `alert.silences:read` | `folders:*`<br>`folders:uid:*` | Read all general silences and rule-specific silences in a folder and its subfolders. |
| `alert.silences:write` | `folders:*`<br>`folders:uid:*` | Update and expire rule-specific silences in a folder and its subfolders. |
| `alert.provisioning:read` | n/a | Read all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
| `alert.provisioning.secrets:read` | n/a | Same as `alert.provisioning:read` plus ability to export resources with decrypted secrets. |
| `alert.provisioning:write` | n/a | Update all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
| `alert.provisioning.provenance:write` | n/a | Set provisioning status for alerting resources. Cannot be used alone. Requires user to have permissions to access resources |
| `apikeys:read` | `apikeys:*`<br>`apikeys:id:*` | Read API keys. |
| `apikeys:delete` | `apikeys:*`<br>`apikeys:id:*` | Delete API keys. |
| `dashboards:create` | `folders:*`<br>`folders:uid:*` | Create dashboards in one or more folders and their subfolders. |
| `dashboards:delete` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Delete one or more dashboards. |
| `dashboards.insights:read` | n/a | Read dashboard insights data and see presence indicators. |
| `dashboards.permissions:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read permissions for one or more dashboards. |
| `dashboards.permissions:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update permissions for one or more dashboards. |
| `dashboards:read` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Read one or more dashboards. |
| `dashboards:write` | `dashboards:*`<br>`dashboards:uid:*`<br>`folders:*`<br>`folders:uid:*` | Update one or more dashboards. |
| `dashboards.public:write` | `dashboards:*`<br>`dashboards:uid:*` | Write public dashboard configuration. |
| `folders.permissions:read` | `folders:*`<br>`folders:uid:*` | Read permissions for one or more folders and their subfolders. |
| `folders.permissions:write` | `folders:*`<br>`folders:uid:*` | Update permissions for one or more folders and their subfolders. |
| `folders:create` | n/a | Create folders in the root level. If granted together with `folders:write`, also allows creating subfolders under all folders that the user can update. |
| `folders:delete` | `folders:*`<br>`folders:uid:*` | Delete one or more folders and their subfolders. |
| `folders:read` | `folders:*`<br>`folders:uid:*` | Read one or more folders and their subfolders. |
| `folders:write` | `folders:*`<br>`folders:uid:*` | Update one or more folders and their subfolders. If granted together with `folders:create` permission, also allows creating subfolders under these folders. |
| `ldap.config:reload` | n/a | Reload the LDAP configuration. |
| `ldap.status:read` | n/a | Verify the availability of the LDAP server or servers. |
| `ldap.user:read` | n/a | Read users via LDAP. |
| `ldap.user:sync` | n/a | Sync users via LDAP. |
| `library.panels:create` | `folders:*`<br>`folders:uid:*` | Create a library panel in one or more folders and their subfolders. |
| `library.panels:read` | `folders:*`<br>`folders:uid:*`<br>`library.panels:*`<br>`library.panels:uid:*` | Read one or more library panels. |
| `library.panels:write` | `folders:*`<br>`folders:uid:*`<br>`library.panels:*`<br>`library.panels:uid:*` | Update one or more library panels. |
| `library.panels:delete` | `folders:*`<br>`folders:uid:*`<br>`library.panels:*`<br>`library.panels:uid:*` | Delete one or more library panels. |
| `licensing.reports:read` | n/a | Get custom permission reports. |
| `licensing:delete` | n/a | Delete the license token. |
| `orgs:delete` | n/a | Delete one or more organizations. |
| `orgs:read` | n/a | Read one or more organizations. |
| `orgs:write` | n/a | Update one or more organizations. |
| `plugins.app:access` | `plugins:*`<br>`plugins:id:*` | Access one or more application plugins (still enforcing the organization role) |
| `plugins:install` | n/a | Install and uninstall plugins. |
| `plugins:write` | `plugins:*`<br>`plugins:id:*` | Edit settings for one or more plugins. |
| `provisioning:reload` | `provisioners:*` | Reload provisioning files. To find the exact scope for specific provisioner, see [Scope definitions]({{< relref "#scope-definitions" >}}). |
| `serviceaccounts:write` | `serviceaccounts:*` | Create Grafana service accounts. |
| `serviceaccounts:create` | n/a | Update Grafana service accounts. |
| `serviceaccounts:delete` | `serviceaccounts:*`<br>`serviceaccounts:id:*` | Delete Grafana service accounts. |
| `serviceaccounts:read` | `serviceaccounts:*`<br>`serviceaccounts:id:*` | Read Grafana service accounts. |
| `serviceaccounts.permissions:write` | `serviceaccounts:*`<br>`serviceaccounts:id:*` | Update Grafana service account permissions to control who can do what with the service account. |
| `serviceaccounts.permissions:read` | `serviceaccounts:*`<br>`serviceaccounts:id:*` | Read Grafana service account permissions to see who can do what with the service account. |
| `settings:write` | `settings:*`<br>`settings:auth.saml:*`<br>`settings:auth.saml:enabled` (property level) | Update any Grafana configuration settings that can be [updated at runtime]({{< relref "../../../../setup-grafana/configure-grafana/settings-updates-at-runtime" >}}). |
| `support.bundles:create` | n/a | Create support bundles. |
| `support.bundles:delete` | n/a | Delete support bundles. |
| `support.bundles:read` | n/a | List and download support bundles. |
| `status:accesscontrol` | `services:accesscontrol` | Get access-control enabled status. |
| `teams.permissions:read` | `teams:*`<br>`teams:id:*` | Read members and Team Sync setup for teams. |
| `teams.permissions:write` | `teams:*`<br>`teams:id:*` | Add, remove and update members and manage Team Sync setup for teams. |
| `teams.roles:add` | `permissions:type:delegate` | Assign a role to a team. |
| `teams.roles:read` | `teams:*`<br>`teams:id:*` | List roles assigned directly to a team. |
| `teams.roles:remove` | `permissions:type:delegate` | Unassign a role from a team. |
| `teams:create` | n/a | Create teams. |
| `teams:delete` | `teams:*`<br>`teams:id:*` | Delete one or more teams. |
| `teams:read` | `teams:*`<br>`teams:id:*` | Read one or more teams and team preferences. To list teams through the UI one of the following permissions is required in addition to `teams:read`: `teams:write`, `teams.permissions:read` or `teams.permissions:write`. |
| `teams:write` | `teams:*`<br>`teams:id:*` | Update one or more teams and team preferences. |
| `users.authtoken:read` | `global.users:*`<br>`global.users:id:*` | List authentication tokens that are assigned to a user. |
| `users.authtoken:write` | `global.users:*`<br>`global.users:id:*` | Update authentication tokens that are assigned to a user. |
| `users.password:write` | `global.users:*`<br>`global.users:id:*` | Update a user’s password. |
| `users.permissions:read` | `users:*` | List permissions of a user. |
| `alert.instances.external:read` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Read alerts and silences in data sources that support alerting. |
| `alert.instances.external:write` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Manage alerts and silences in data sources that support alerting. |
| `alert.instances:create` | None | Create silences in the current organization. |
| `alert.instances:read` | None | Read alerts and silences in the current organization. |
| `alert.instances:write` | None | Update and expire silences in the current organization. |
| `alert.notifications.external:read` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Read templates, contact points, notification policies, and mute timings in data sources that support alerting. |
| `alert.notifications.external:write` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Manage templates, contact points, notification policies, and mute timings in data sources that support alerting. |
| `alert.notifications:write` | None | Manage templates, contact points, notification policies, and mute timings in the current organization. |
| `alert.notifications:read` | None | Read all templates, contact points, notification policies, and mute timings in the current organization. |
| `alert.rules.external:read` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Read alert rules in data sources that support alerting (Prometheus, Mimir, and Loki) |
| `alert.rules.external:write` | <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Create, update, and delete alert rules in data sources that support alerting (Mimir and Loki). |
| `alert.rules:create` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Create Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:delete` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Delete Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:read` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.rules:write` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update Grafana alert rules in a folder and its subfolders. Combine this permission with `folders:read` in a scope that includes the folder and `datasources:query` in the scope of data sources the user can query. |
| `alert.silences:create` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Create rule-specific silences in a folder and its subfolders. |
| `alert.silences:read` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read all general silences and rule-specific silences in a folder and its subfolders. |
| `alert.silences:write` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update and expire rule-specific silences in a folder and its subfolders. |
| `alert.provisioning:read` | None | Read all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
| `alert.provisioning.secrets:read` | None | Same as `alert.provisioning:read` plus ability to export resources with decrypted secrets. |
| `alert.provisioning:write` | None | Update all Grafana alert rules, notification policies, etc via provisioning API. Permissions to folders and datasource are not required. |
| `alert.provisioning.provenance:write` | None | Set provisioning status for alerting resources. Cannot be used alone. Requires user to have permissions to access resources |
| `apikeys:read` | <ul><li>`apikeys:*`</li><li>`apikeys:id:*`</li></ul> | Read API keys. |
| `apikeys:delete` | <ul><li>`apikeys:*`</li><li>`apikeys:id:*`</li></ul> | Delete API keys. |
| `dashboards:create` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Create dashboards in one or more folders and their subfolders. |
| `dashboards:delete` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Delete one or more dashboards. |
| `dashboards.insights:read` | None | Read dashboard insights data and see presence indicators. |
| `dashboards.permissions:read` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read permissions for one or more dashboards. |
| `dashboards.permissions:write` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update permissions for one or more dashboards. |
| `dashboards:read` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read one or more dashboards. |
| `dashboards:write` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update one or more dashboards. |
| `dashboards.public:write` | <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li></ul> | Write public dashboard configuration. |
| `folders.permissions:read` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read permissions for one or more folders and their subfolders. |
| `folders.permissions:write` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update permissions for one or more folders and their subfolders. |
| `folders:create` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li><li>`folders:uid:general`</li></ul> | Create folders or subfolders. If granted with scope `folders:uid:general`, it allows to create root level folders. Otherwise, it allows creating subfolders under the specified folders. |
| `folders:delete` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Delete one or more folders and their subfolders. |
| `folders:read` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Read one or more folders and their subfolders. |
| `folders:write` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Update one or more folders and their subfolders. |
| `ldap.config:reload` | None | Reload the LDAP configuration. |
| `ldap.status:read` | None | Verify the availability of the LDAP server or servers. |
| `ldap.user:read` | None | Read users via LDAP. |
| `ldap.user:sync` | None | Sync users via LDAP. |
| `library.panels:create` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Create a library panel in one or more folders and their subfolders. |
| `library.panels:read` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li><li>`library.panels:*`</li><li>`library.panels:uid:*`</li></ul> | Read one or more library panels. |
| `library.panels:write` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li><li>`library.panels:*`</li><li>`library.panels:uid:*`</li></ul> | Update one or more library panels. |
| `library.panels:delete` | <ul><li>`folders:*`</li><li>`folders:uid:*`</li><li>`library.panels:*`</li><li>`library.panels:uid:*`</li></ul> | Delete one or more library panels. |
| `licensing.reports:read` | None | Get custom permission reports. |
| `licensing:delete` | None | Delete the license token. |
| `licensing:write` | None | Update the license token. |
| `org.users:write` | <ul><li>`users:*`</li><li>`users:id:*`</li></ul> | Update the organization role (`None`, `Viewer`, `Editor`, or `Admin`) of a user. |
| `org.users:add` | <ul><li>`users:*`</li><li>`users:id:*`</li></ul> | Add a user to an organization or invite a new user to an organization. |
| `org.users:read` | <ul><li>`users:*`</li><li>`users:id:*`</li></ul> | Get user profiles within an organization. |
| `org.users:remove` | <ul><li>`users:*`</li><li>`users:id:*`</li></ul> | Remove a user from an organization. |
| `orgs:create` | None | Create an organization. |
| `orgs:delete` | None | Delete one or more organizations. |
| `orgs:read` | None | Read one or more organizations. |
| `orgs:write` | None | Update one or more organizations. |
| `plugins.app:access` | <ul><li>`plugins:*`</li><li>`plugins:id:*`</li></ul> | Access one or more application plugins (still enforcing the organization role) |
| `plugins:install` | None | Install and uninstall plugins. |
| `plugins:write` | <ul><li>`plugins:*`</li><li>`plugins:id:*`</li></ul> | Edit settings for one or more plugins. |
| `provisioning:reload` | `provisioners:*` | Reload provisioning files. To find the exact scope for specific provisioner, refer to [Scope definitions](#scope-definitions). |
| `serviceaccounts:write` | <ul><li>`serviceaccounts:*`</li><ul> | Create Grafana service accounts. |
| `serviceaccounts:create` | None | Update Grafana service accounts. |
| `serviceaccounts:delete` | <ul><li>`serviceaccounts:*`</li><li>`serviceaccounts:id:*`</li></ul> | Delete Grafana service accounts. |
| `serviceaccounts:read` | <ul><li>`serviceaccounts:*`</li><li>`serviceaccounts:id:*`</li></ul> | Read Grafana service accounts. |
| `serviceaccounts.permissions:write` | <ul><li>`serviceaccounts:*`</li><li>`serviceaccounts:id:*`</li></ul> | Update Grafana service account permissions to control who can do what with the service account. |
| `serviceaccounts.permissions:read` | <ul><li>`serviceaccounts:*`</li><li>`serviceaccounts:id:*`</li></ul> | Read Grafana service account permissions to see who can do what with the service account. |
| `settings:write` | <ul><li>`settings:*`</li><li>`settings:auth.saml:*`</li><li>`settings:auth.saml:enabled`</li></ul> (property level) | Update any Grafana configuration settings that can be [updated at runtime](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/settings-updates-at-runtime/). |
| `support.bundles:create` | None | Create support bundles. |
| `support.bundles:delete` | None | Delete support bundles. |
| `support.bundles:read` | None | List and download support bundles. |
| `status:accesscontrol` | <ul><li>`services:accesscontrol`</li><ul> | Get access-control enabled status. |
| `teams.permissions:read` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Read members and Team Sync setup for teams. |
| `teams.permissions:write` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Add, remove and update members and manage Team Sync setup for teams. |
| `teams.roles:add` | <ul><li>`permissions:type:delegate`</li><ul> | Assign a role to a team. |
| `teams.roles:read` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | List roles assigned directly to a team. |
| `teams.roles:remove` | <ul><li>`permissions:type:delegate`</li><ul> | Unassign a role from a team. |
| `teams:create` | None | Create teams. |
| `teams:delete` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Delete one or more teams. |
| `teams:read` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Read one or more teams and team preferences. To list teams through the UI one of the following permissions is required in addition to `teams:read`: `teams:write`, `teams.permissions:read` or `teams.permissions:write`. |
| `teams:write` | <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Update one or more teams and team preferences. |
| `users.authtoken:read` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | List authentication tokens that are assigned to a user. |
| `users.authtoken:write` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Update authentication tokens that are assigned to a user. |
| `users.password:write` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Update a user’s password. |
| `users.permissions:read` | <ul><li>`users:*`</li><ul> | List permissions of a user. |
| `users.quotas:read` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | List a user’s quotas. |
| `users.quotas:write` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Update a user’s quotas. |
| `users.roles:add` | <ul><li>`permissions:type:delegate`</li><ul> | Assign a role to a user or a service account. |
| `users.roles:read` | <ul><li>`users:*`</li><ul> | List roles assigned directly to a user or a service account. |
| `users.roles:remove` | <ul><li>`permissions:type:delegate`</li><ul> | Unassign a role from a user or a service account. |
| `users:create` | None | Create a user. |
| `users:delete` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Delete a user. |
| `users:disable` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Disable a user. |
| `users:enable` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Enable a user. |
| `users:logout` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Sign out a user. |
| `users:read` | <ul><li>`global.users:*`</li><ul> | Read or search user profiles. |
| `users:write` | <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Update a user’s profile. |
{ .no-spacing-list }
<!-- prettier-ignore-end -->
### Grafana OnCall action definitions (beta)
> **Note:** Available from Grafana 9.4 in early access.
> **Note:** This feature is behind the `accessControlOnCall` feature toggle.
> You can enable feature toggles through configuration file or environment variables. See configuration [docs]({{< relref "../../../../setup-grafana/configure-grafana/#feature_toggles" >}}) for details.
The following list contains role-based access control actions used by Grafana OnCall application plugin.
| `annotations:*`<br>`annotations:type:*` | Restrict an action to a set of annotations. For example, `annotations:*` matches any annotation, `annotations:type:dashboard` matches annotations associated with dashboards and `annotations:type:organization` matches organization annotations. |
| `apikeys:*`<br>`apikeys:id:*` | Restrict an action to a set of API keys. For example, `apikeys:*` matches any API key, `apikey:id:1` matches the API key whose id is `1`. |
| `dashboards:*`<br>`dashboards:uid:*` | Restrict an action to a set of dashboards. For example, `dashboards:*` matches any dashboard, and `dashboards:uid:1` matches the dashboard whose UID is `1`. |
| `datasources:*`<br>`datasources:uid:*` | Restrict an action to a set of data sources. For example, `datasources:*` matches any data source, and `datasources:uid:1` matches the data source whose UID is `1`. |
| `folders:*`<br>`folders:uid:*` | Restrict an action to a set of folders. For example, `folders:*` matches any folder, and `folders:uid:1` matches the folder whose UID is `1`. Note that permissions granted to a folder cascade down to subfolders located under it |
| `global.users:*`<br>`global.users:id:*` | Restrict an action to a set of global users. For example, `global.users:*` matches any user and `global.users:id:1` matches the user whose ID is `1`. |
| `library.panels:*`<br>`library.panels:uid:*` | Restrict an action to a set of library panels. For example, `library.panels:*` matches any library panel, and `library.panel:uid:1` matches the library panel whose UID is `1`. |
| `orgs:*`<br>`orgs:id:*` | Restrict an action to a set of organizations. For example, `orgs:*` matches any organization and `orgs:id:1` matches the organization whose ID is `1`. |
| `permissions:type:delegate` | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. |
| `permissions:type:escalate` | The scope is required to trigger the reset of basic roles permissions. It indicates that users might acquire additional permissions they did not previously have. |
| `plugins:*`<br>`plugins:id:*` | Restrict an action to a set of plugins. For example, `plugins:id:grafana-oncall-app` matches Grafana OnCall plugin, and `plugins:*` matches all plugins. |
| `provisioners:*` | Restrict an action to a set of provisioners. For example, `provisioners:*` matches any provisioner, and `provisioners:accesscontrol` matches the role-based access control [provisioner]({{< relref "./rbac-grafana-provisioning/" >}}). |
| `reports:*`<br>`reports:id:*` | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:id:1` matches the report whose ID is `1`. |
| `roles:*`<br>`roles:uid:*` | Restrict an action to a set of roles. For example, `roles:*` matches any role and `roles:uid:randomuid` matches only the role whose UID is `randomuid`. |
| `services:accesscontrol` | Restrict an action to target only the role-based access control service. You can use this in conjunction with the `status:accesscontrol` actions. |
| `serviceaccounts:*`<br>`serviceaccounts:id:*` | Restrict an action to a set of service account from an organization. For example, `serviceaccounts:*` matches any service account and `serviceaccount:id:1` matches the service account whose ID is `1`. |
| `settings:*` | Restrict an action to a subset of settings. For example, `settings:*` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. |
| `teams:*`<br>`teams:id:*` | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. |
| `users:*`<br>`users:id:*` | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. |
| `n/a` | `n/a` means not applicable. If an action has `n/a` specified for the scope, then the action does not require a scope. For example, the `teams:create` action does not require a scope and allows users to create teams. |
| <ul><li>`annotations:*`</li><li>`annotations:type:*`</li></ul> | Restrict an action to a set of annotations. For example, `annotations:*` matches any annotation, `annotations:type:dashboard` matches annotations associated with dashboards and `annotations:type:organization` matches organization annotations. |
| <ul><li>`apikeys:*`</li><li>`apikeys:id:*`</li></ul> | Restrict an action to a set of API keys. For example, `apikeys:*` matches any API key, `apikey:id:1` matches the API key whose id is `1`. |
| <ul><li>`dashboards:*`</li><li>`dashboards:uid:*`</li></ul> | Restrict an action to a set of dashboards. For example, `dashboards:*` matches any dashboard, and `dashboards:uid:1` matches the dashboard whose UID is `1`. |
| <ul><li>`datasources:*`</li><li>`datasources:uid:*`</li></ul> | Restrict an action to a set of data sources. For example, `datasources:*` matches any data source, and `datasources:uid:1` matches the data source whose UID is `1`. |
| <ul><li>`folders:*`</li><li>`folders:uid:*`</li></ul> | Restrict an action to a set of folders. For example, `folders:*` matches any folder, and `folders:uid:1` matches the folder whose UID is `1`. Note that permissions granted to a folder cascade down to subfolders located under it. |
| <ul><li>`global.users:*`</li><li>`global.users:id:*`</li></ul> | Restrict an action to a set of global users. For example, `global.users:*` matches any user and `global.users:id:1` matches the user whose ID is `1`. |
| <ul><li>`library.panels:*`</li><li>`library.panels:uid:*`</li></ul> | Restrict an action to a set of library panels. For example, `library.panels:*` matches any library panel, and `library.panel:uid:1` matches the library panel whose UID is `1`. |
| <ul><li>`orgs:*`</li><li>`orgs:id:*`</li></ul> | Restrict an action to a set of organizations. For example, `orgs:*` matches any organization and `orgs:id:1` matches the organization whose ID is `1`. |
| <ul><li>`permissions:type:delegate`</li><ul> | The scope is only applicable for roles associated with the Access Control itself and indicates that you can delegate your permissions only, or a subset of it, by creating a new role or making an assignment. |
| <ul><li>`permissions:type:escalate`</li><ul> | The scope is required to trigger the reset of basic roles permissions. It indicates that users might acquire additional permissions they did not previously have. |
| <ul><li>`plugins:*`</li><li>`plugins:id:*`</li></ul> | Restrict an action to a set of plugins. For example, `plugins:id:grafana-oncall-app` matches Grafana OnCall plugin, and `plugins:*` matches all plugins. |
| <ul><li>`provisioners:*`</li><ul> | Restrict an action to a set of provisioners. For example, `provisioners:*` matches any provisioner, and `provisioners:accesscontrol` matches the role-based access control [provisioner](ref:rbac-grafana-provisioning). |
| <ul><li>`reports:*`</li><li>`reports:id:*`</li></ul> | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:id:1` matches the report whose ID is `1`. |
| <ul><li>`roles:*`</li><li>`roles:uid:*`</li></ul> | Restrict an action to a set of roles. For example, `roles:*` matches any role and `roles:uid:randomuid` matches only the role whose UID is `randomuid`. |
| <ul><li>`services:accesscontrol`</li><ul> | Restrict an action to target only the role-based access control service. You can use this in conjunction with the `status:accesscontrol` actions. |
| <ul><li>`serviceaccounts:*`</li><li>`serviceaccounts:id:*`</li></ul> | Restrict an action to a set of service account from an organization. For example, `serviceaccounts:*` matches any service account and `serviceaccount:id:1` matches the service account whose ID is `1`. |
| <ul><li>`settings:*`</li><ul> | Restrict an action to a subset of settings. For example, `settings:*` matches all settings, `settings:auth.saml:*` matches all SAML settings, and `settings:auth.saml:enabled` matches the enable property on the SAML settings. |
| <ul><li>`teams:*`</li><li>`teams:id:*`</li></ul> | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. |
| <ul><li>`users:*`</li><li>`users:id:*`</li></ul> | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. |
| <ul><li>None</li><ul> | If an action has "None" specified for the scope, then the action doesn't require a scope. For example, the `teams:create` action doesn't require a scope and allows users to create teams. |
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
{{<table-of-contents>}}
@ -28,7 +82,7 @@ The following example includes the base64 username:password Basic Authorization.
## List permissions associated with roles
Use a `GET` command to see the actions and scopes associated with a role. For more information about seeing a list of permissions for each role, refer to [Get a role]({{< relref "../../../../developers/http_api/access_control/#get-a-role" >}}).
Use a `GET` command to see the actions and scopes associated with a role. For more information about seeing a list of permissions for each role, refer to [Get a role](ref:api-rbac-get-a-role).
To see the permissions associated with basic roles, refer to the following basic role UIDs:
@ -87,7 +141,7 @@ curl --location --request GET '<grafana_url>/api/access-control/roles/qQui_LCMk'
}
```
Refer to the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#get-a-role" >}}) for more details.
Refer to the [RBAC HTTP API](ref:api-rbac-get-a-role) for more details.
## Create custom roles
@ -97,26 +151,26 @@ Create a custom role when basic roles and fixed roles do not meet your permissio
**Before you begin:**
- [Plan your RBAC rollout strategy]({{< relref "./plan-rbac-rollout-strategy/" >}}).
- Determine which permissions you want to add to the custom role. To see a list of actions and scope, refer to [RBAC permissions, actions, and scopes]({{< relref "./custom-role-actions-scopes/" >}}).
- [Enable role provisioning]({{< relref "./rbac-grafana-provisioning/" >}}).
- [Plan your RBAC rollout strategy](ref:plan-rbac-rollout-strategy).
- Determine which permissions you want to add to the custom role. To see a list of actions and scope, refer to [RBAC permissions, actions, and scopes](ref:custom-role-actions-scopes).
- [Enable role provisioning](ref:rbac-grafana-provisioning).
- Ensure that you have permissions to create a custom role.
- By default, the Grafana Admin role has permission to create custom roles.
- A Grafana Admin can delegate the custom role privilege to another user by creating a custom role with the relevant permissions and adding the `permissions:type:delegate` scope.
### Create custom roles using provisioning
[File-based provisioning]({{< relref "./rbac-grafana-provisioning" >}}) is one method you can use to create custom roles.
[File-based provisioning](ref:rbac-grafana-provisioning) is one method you can use to create custom roles.
1. Open the YAML configuration file and locate the `roles` section.
1. Refer to the following table to add attributes and values.
| `name` | A human-friendly identifier for the role that helps administrators understand the purpose of a role. `name` is required and cannot be longer than 190 characters. We recommend that you use ASCII characters. Role names must be unique within an organization. |
| `uid` | A unique identifier associated with the role. The UID enables you to change or delete the role. You can either generate a UID yourself, or let Grafana generate one for you. You cannot use the same UID within the same Grafana instance. |
| `orgId` | Identifies the organization to which the role belongs. The [default org ID]({{< relref "../../../../setup-grafana/configure-grafana/#auto_assign_org_id" >}}) is used if you do not specify `orgId`. |
| `orgId` | Identifies the organization to which the role belongs. The [default org ID](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#auto_assign_org_id) is used if you do not specify `orgId`. |
| `global` | Global roles are not associated with any specific organization, which means that you can reuse them across all organizations. This setting overrides `orgId`. |
| `displayName` | Human-friendly text that is displayed in the UI. Role display name cannot be longer than 190 ASCII-based characters. For fixed roles, the display name is shown as specified. If you do not set a display name the display name replaces `':'` (a colon) with `' '` (a space). |
| `description` | Human-friendly text that describes the permissions a role provides. |
@ -126,11 +180,11 @@ Create a custom role when basic roles and fixed roles do not meet your permissio
| `state` | State of the role. Defaults to `present`, but if set to `absent` the role will be removed. |
| `force` | Can be used in addition to state `absent`, to force the removal of a role and all its assignments. |
| `from` | An optional list of roles from which you want to copy permissions. |
| `permissions` | Provides users access to Grafana resources. For a list of permissions, refer to [RBAC permissions actions and scopes]({{< relref "./rbac-fixed-basic-role-definitions/" >}}). If you do not know which permissions to assign, you can create and assign roles without any permissions as a placeholder. Using the `from` attribute, you can specify additional permissions or permissions to remove by adding a `state` to your permission list. |
| `permissions` | Provides users access to Grafana resources. For a list of permissions, refer to [RBAC permissions actions and scopes](ref:rbac-role-definitions). If you do not know which permissions to assign, you can create and assign roles without any permissions as a placeholder. Using the `from` attribute, you can specify additional permissions or permissions to remove by adding a `state` to your permission list. |
1. Reload the provisioning configuration file.
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations]({{< relref "../../../../developers/http_api/admin/#reload-provisioning-configurations" >}}).
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations](/docs/grafana/<GRAFANA_VERSION>/developers/http_api/admin/#reload-provisioning-configurations).
The following example creates a local role:
@ -199,7 +253,7 @@ roles:
### Create custom roles using the HTTP API
The following examples show you how to create a custom role using the Grafana HTTP API. For more information about the HTTP API, refer to [Create a new custom role]({{< relref "../../../../developers/http_api/access_control/#create-a-new-custom-role" >}}).
The following examples show you how to create a custom role using the Grafana HTTP API. For more information about the HTTP API, refer to [Create a new custom role](ref:api-rbac-create-a-new-custom-role).
{{% admonition type="note" %}}
You cannot create a custom role with permissions that you do not have. For example, if you only have `users:create` permissions, then you cannot create a role that includes other permissions.
@ -250,7 +304,7 @@ curl --location --request POST '<grafana_url>/api/access-control/roles/' \
}
```
Refer to the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#create-a-new-custom-role" >}}) for more details.
Refer to the [RBAC HTTP API](ref:api-rbac-create-a-new-custom-role) for more details.
## Update basic role permissions
@ -258,7 +312,7 @@ If the default basic role definitions do not meet your requirements, you can cha
**Before you begin:**
- Determine the permissions you want to add or remove from a basic role. For more information about the permissions associated with basic roles, refer to [RBAC role definitions]({{< relref "./rbac-fixed-basic-role-definitions/#basic-role-assignments" >}}).
- Determine the permissions you want to add or remove from a basic role. For more information about the permissions associated with basic roles, refer to [RBAC role definitions](ref:rbac-fixed-basic-role-definitions-basic-role-assignments).
{{% admonition type="note" %}}
You cannot modify the `No Basic Role` permissions.
@ -281,7 +335,7 @@ You cannot modify the `No Basic Role` permissions.
1. Reload the provisioning configuration file.
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations]({{< relref "../../../../developers/http_api/admin/#reload-provisioning-configurations" >}}).
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations](/docs/grafana/<GRAFANA_VERSION>/developers/http_api/admin/#reload-provisioning-configurations).
The following example modifies the `Grafana Admin` basic role permissions.
@ -322,7 +376,7 @@ You can add multiple `fixed`, `basic` or `custom` roles to the `from` section. T
Make sure to **increment** the role version for the changes to be accounted for.
{{% /admonition %}}
You can also change basic roles' permissions using the API. Refer to the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#update-a-role" >}}) for more details.
You can also change basic roles' permissions using the API. Refer to the [RBAC HTTP API](ref:api-rbac-update-a-role) for more details.
## Reset basic roles to their default
@ -336,7 +390,7 @@ You have two options to reset the basic roles permissions to their default.
> Warning: If this option is left to true, permissions will be reset on every boot.
Use the [reset_basic_roles]({{< relref "../configure-rbac/#configure-rbac-in-grafana" >}}) option to reset
Use the [reset_basic_roles](ref:configure-rbac-configure-rbac-in-grafana) option to reset
basic roles permissions to their default on Grafana instance boot up.
1. Open you configuration file and update the rbac section as follow:
@ -369,7 +423,7 @@ An alternative to the configuration option is to use the HTTP endpoint.
scope: 'permissions:type:escalate'
```
1. As a `Grafana Admin`, call the API endpoint to reset the basic roles to their default. Refer to the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#reset-basic-roles-to-their-default" >}}) for more details.
1. As a `Grafana Admin`, call the API endpoint to reset the basic roles to their default. Refer to the [RBAC HTTP API](ref:api-rbac-reset-basic-roles-to-their-default) for more details.
## Delete a custom role using Grafana provisioning
@ -395,7 +449,7 @@ Delete a custom role when you no longer need it. When you delete a custom role,
1. Reload the provisioning configuration file.
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations]({{< relref "../../../../developers/http_api/admin/#reload-provisioning-configurations" >}}).
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations](/docs/grafana/<GRAFANA_VERSION>/developers/http_api/admin/#reload-provisioning-configurations).
The following example deletes a custom role:
@ -410,4 +464,4 @@ roles:
force: true
```
You can also delete a custom role using the API. Refer to the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#delete-a-custom-role" >}}) for more details.
You can also delete a custom role using the API. Refer to the [RBAC HTTP API](ref:api-rbac-delete-a-custom-role) for more details.
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
An RBAC rollout strategy helps you determine _how_ you want to implement RBAC prior to assigning RBAC roles to users and teams.
@ -35,8 +61,8 @@ As a first step in determining your permissions rollout strategy, we recommend t
To learn more about basic roles and fixed roles, refer to the following documentation:
- [Basic role definitions]({{< relref "./rbac-fixed-basic-role-definitions/#basic-role-assignments" >}})
- [Fixed role definitions]({{< relref "./rbac-fixed-basic-role-definitions/#fixed-role-definitions" >}})
- [Basic role definitions](ref:rbac-fixed-basic-role-definitions-basic-role-assignments)
- [Fixed role definitions](ref:rbac-fixed-basic-role-definitions-fixed-role-definitions)
## User and team considerations
@ -56,7 +82,7 @@ For example:
1. Map SAML, LDAP, or Oauth roles to Grafana basic roles (viewer, editor, or admin).
2. Use the Grafana Enterprise team sync feature to synchronize teams from your SAML, LDAP, or Oauth provider to Grafana. For more information about team sync, refer to [Team sync]({{< relref "../../../../setup-grafana/configure-security/configure-team-sync/" >}}).
2. Use the Grafana Enterprise team sync feature to synchronize teams from your SAML, LDAP, or Oauth provider to Grafana. For more information about team sync, refer to [Team sync](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-team-sync/).
3. Within Grafana, assign RBAC permissions to users and teams.
@ -67,7 +93,7 @@ Consider the following guidelines when you determine if you should modify basic
- **Modify basic roles** when Grafana's definitions of what viewers, editors, and admins can do does not match your definition of these roles. You can add or remove permissions from any basic role.
{{% admonition type="note" %}}
Changes that you make to basic roles impact the role definition for all [organizations]({{< relref "../../../organization-management/" >}}) in the Grafana instance. For example, when you add the `fixed:users:writer` role's permissions to the viewer basic role, all viewers in any org in the Grafana instance can create users within that org.
Changes that you make to basic roles impact the role definition for all [organizations](/docs/grafana/<GRAFANA_VERSION>/administration/organization-management/) in the Grafana instance. For example, when you add the `fixed:users:writer` role's permissions to the viewer basic role, all viewers in any org in the Grafana instance can create users within that org.
{{% /admonition %}}
{{% admonition type="note" %}}
@ -97,13 +123,13 @@ If you have a use case that you'd like to share, feel free to contribute to this
1. In Grafana, create a team with the name `Internal employees`.
1. Assign the `fixed:datasources:explorer` role to the `Internal employees` team.
1. Add internal employees to the `Internal employees` team, or map them from a SAML, LDAP, or Oauth team using [Team Sync]({{< relref "../../../../setup-grafana/configure-security/configure-team-sync/" >}}).
1. Add internal employees to the `Internal employees` team, or map them from a SAML, LDAP, or Oauth team using [Team Sync](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/configure-team-sync/).
1. Assign the viewer role to both internal employees and contractors.
### Limit viewer, editor, or admin permissions
1. Review the list of permissions associated with the basic role.
1. [Change the permissions of the basic role]({{< relref "./manage-rbac-roles/#update-basic-role-permissions" >}}).
1. [Change the permissions of the basic role](ref:manage-rbac-roles-update-basic-role-permissions).
### Allow only members of one team to manage Alerts
@ -168,9 +194,9 @@ curl --location --request POST '<grafana_url>/api/access-control/roles/' \
### Enable an editor to create custom roles
By default, only a Grafana Server Admin can create and manage custom roles. If you want your `Editors` to do the same, [update the `Editor` basic role permissions]({{< ref "./manage-rbac-roles.md#update-basic-role-permissions" >}}). There are two ways to achieve this:
By default, only a Grafana Server Admin can create and manage custom roles. If you want your `Editors` to do the same, [update the `Editor` basic role permissions](ref:manage-rbac-roles-update-basic-role-permissions). There are two ways to achieve this:
- Add the following permissions to the `basic:editor` role, using provisioning or the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#update-a-role" >}}):
- Add the following permissions to the `basic:editor` role, using provisioning or the [RBAC HTTP API](ref:api-rbac-update-a-role):
| action | scope |
| -------------- | --------------------------- |
@ -212,9 +238,9 @@ By default, only a Grafana Server Admin can create and manage custom roles. If y
### Enable viewers to create reports
If you want your `Viewers` to create reports, [update the `Viewer` basic role permissions]({{< ref "./manage-rbac-roles.md#update-basic-role-permissions" >}}). There are two ways to achieve this:
If you want your `Viewers` to create reports, [update the `Viewer` basic role permissions](ref:manage-rbac-roles-update-basic-role-permissions). There are two ways to achieve this:
- Add the following permissions to the `basic:viewer` role, using provisioning or the [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#update-a-role" >}}):
- Add the following permissions to the `basic:viewer` role, using provisioning or the [RBAC HTTP API](ref:api-rbac-update-a-role):
@ -253,11 +279,11 @@ If you want your `Viewers` to create reports, [update the `Viewer` basic role pe
global: true
```
> **Note:** The `fixed:reports:writer` role assigns more permissions than just creating reports. For more information about fixed role permission assignments, refer to [Fixed role definitions]({{< relref "./rbac-fixed-basic-role-definitions/#fixed-role-definitions" >}}).
> **Note:** The `fixed:reports:writer` role assigns more permissions than just creating reports. For more information about fixed role permission assignments, refer to [Fixed role definitions](ref:rbac-fixed-basic-role-definitions-fixed-role-definitions).
### Prevent a Grafana Admin from creating and inviting users
To prevent a Grafana Admin from creating users and inviting them to join an organization, you must [update a basic role permission]({{< relref "./manage-rbac-roles/#update-basic-role-permissions" >}}).
To prevent a Grafana Admin from creating users and inviting them to join an organization, you must [update a basic role permission](ref:manage-rbac-roles-update-basic-role-permissions).
The permissions to remove are:
| Action | Scope |
@ -267,7 +293,7 @@ The permissions to remove are:
There are two ways to achieve this:
- Use [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#update-a-role" >}}).
- Use [RBAC HTTP API](ref:api-rbac-update-a-role).
As an example, here is a small bash script that fetches the role, modifies it using `jq` and updates it:
@ -306,7 +332,7 @@ There are two ways to achieve this:
### Prevent Viewers from accessing an App Plugin
By default, Viewers, Editors and Admins have access to all App Plugins that their organization role allows them to access.
To change this default behavior and prevent Viewers from accessing an App plugin, you must [update a basic role's permissions]({{< relref "./manage-rbac-roles/#update-basic-role-permissions" >}}).
To change this default behavior and prevent Viewers from accessing an App plugin, you must [update a basic role's permissions](ref:manage-rbac-roles-update-basic-role-permissions).
In this example, three App plugins have been installed and enabled:
| Name | ID | Required Org role |
@ -329,7 +355,7 @@ If you want to revoke their access to the On Call App plugin, you need to:
Here are two ways to achieve this:
- Use [RBAC HTTP API]({{< relref "../../../../developers/http_api/access_control/#update-a-role" >}}).
- Use [RBAC HTTP API](ref:api-rbac-update-a-role).
As an example, here is a small bash script that fetches the role, modifies it using `jq` and updates it:
@ -397,7 +423,7 @@ A user will be added to the default organization automatically but won't have an
Using Service Accounts is an efficient way to facilitate M2M communications. However, they can pose a security threat if not scoped appropriately. To limit the scope of a service account, you can begin by creating a Service Account with `No Basic Role` and then assign the necessary permissions for the account.
1. Refer to [Service Accounts](https://grafana.com/docs/grafana/latest/administration/service-accounts/) and add a new Service Account.
1. Refer to [Service Accounts](ref:service-accounts) and add a new Service Account.
1. Set the basic role to `No Basic Role`.
1. Set the fixed roles needed for the Service Account.
| Editor | `basic_editor` | `fixed:datasources:explorer`<br>`fixed:dashboards:creator`<br>`fixed:folders:creator`<br>`fixed:annotations:writer`<br>`fixed:teams:creator` if the `editors_can_admin` configuration flag is enabled<br>`fixed:alerting:writer`<br>`fixed:dashboards.insights:reader`<br>`fixed:datasources.insights:reader`<br>`fixed:library.panels:creator`<br>`fixed:library.panels:general.reader`<br>`fixed:library.panels:general.writer`<br>`fixed:alerting.provisioning.status:writer` | Default [Editor](ref:rbac-basic-roles) assignments. |
| Viewer | `basic_viewer` | `fixed:datasources.id:reader`<br>`fixed:organization:reader`<br>`fixed:annotations:reader`<br>`fixed:annotations.dashboard:writer`<br>`fixed:alerting:reader`<br>`fixed:plugins.app:reader`<br>`fixed:dashboards.insights:reader`<br>`fixed:datasources.insights:reader`<br>`fixed:library.panels:general.reader`<br>`fixed:datasources:explorer` if the `viewers_can_edit` configuration flag is enabled | Default [Viewer](ref:rbac-basic-roles) assignments. |
| No Basic Role | n/a | | Default [No Basic Role](ref:rbac-basic-roles) |
## Fixed role definitions
The following table has the existing built-in fixed role definitions. Other fixed roles might be added by plugins installed in Grafana.
The UUID presented here can be used as an identifier for [Terraform provisioning](../rbac-terraform-provisioning).
The UUID presented here can be used as an identifier for [Terraform provisioning](ref:rbac-terraform-provisioning).
{{<admonitiontype="caution">}}
These UUIDs won't be available if your instance was created before Grafana v10.2.0.
To learn how to use the roles API to determine the role UUIDs, refer to [Manage RBAC roles](/docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/access-control/manage-rbac-roles/).
To learn how to use the roles API to determine the role UUIDs, refer to [Manage RBAC roles](ref:rbac-manage-rbac-roles).
{{</admonition>}}
| Fixed role | UUID | Permissions | Description |
@ -78,9 +109,9 @@ To learn how to use the roles API to determine the role UUIDs, refer to [Manage
| `fixed:datasources.permissions:writer` | `fixed_aiQh9YDfLOKjQhYasF9_SFUjQiw` | All permissions from `fixed:datasources.permissions:reader` and <br>`datasources.permissions:write` | Create, read, or delete permissions of a data source. |
| `fixed:folders:creator` | `fixed_gGLRbZGAGB6n9uECqSh_W382RlQ` | `folders:create` | Create folders in the root level. If granted together with `folders:write` permission, also allows creating subfolders under all folders. |
| `fixed:folders:creator` | `fixed_gGLRbZGAGB6n9uECqSh_W382RlQ` | `folders:create` | Create folders in the root level. |
| `fixed:folders:reader` | `fixed_yeW-5QPeo-i5PZUIUXMlAA97GnQ` | `folders:read`<br>`dashboards:read` | Read all folders and dashboards. |
| `fixed:folders:writer` | `fixed_wJXLoTzgE7jVuz90dryYoiogL0o` | All permissions from `fixed:dashboards:writer` and <br>`folders:read`<br>`folders:write`<br>`folders:create`<br>`folders:delete`<br>`folders.permissions:read`<br>`folders.permissions:write` | Read, create, update, and delete all folders and dashboards. If granted together with `fixed:folders:creator`, allows creating subfolders under all folders. |
| `fixed:folders:writer` | `fixed_wJXLoTzgE7jVuz90dryYoiogL0o` | All permissions from `fixed:dashboards:writer` and <br>`folders:read`<br>`folders:write`<br>`folders:create`<br>`folders:delete`<br>`folders.permissions:read`<br>`folders.permissions:write` | Read, update, and delete all folders and dashboards. Create folders and subfolders. |
| `fixed:folders.permissions:writer` | `fixed_3GAgpQ_hWG8o7-lwNb86_VB37eI` | All permissions from `fixed:folders.permissions:reader` and <br>`folders.permissions:write` | Read and update all folder permissions. |
| `fixed:ldap:reader` | `fixed_lMcOPwSkxKY-qCK8NMJc5k6izLE` | `ldap.user:read`<br>`ldap.status:read` | Read the LDAP configuration and LDAP status information. |
@ -129,7 +160,7 @@ Access to Grafana alert rules is an intersection of many permissions:
There is only one exclusion at this moment. Role `fixed:alerting.provisioning:writer` does not require user to have any additional permissions and provides access to all aspects of the alerting configuration via special provisioning API.
For more information about the permissions required to access alert rules, refer to [Create a custom role to access alerts in a folder]({{< relref "./plan-rbac-rollout-strategy/#create-a-custom-role-to-access-alerts-in-a-folder" >}}).
For more information about the permissions required to access alert rules, refer to [Create a custom role to access alerts in a folder](ref:plan-rbac-rollout-strategy-create-a-custom-role-to-access-alerts-in-a-folder).
### Grafana OnCall roles (beta)
@ -139,17 +170,17 @@ Available from Grafana 9.4 in early access.
{{% admonition type="note" %}}
This feature is behind the `accessControlOnCall` feature toggle.
You can enable feature toggles through configuration file or environment variables. See configuration [docs]({{< relref "../../../../setup-grafana/configure-grafana/#feature_toggles" >}}) for details.
You can enable feature toggles through configuration file or environment variables. See configuration [docs](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-grafana/#feature_toggles) for details.
{{% /admonition %}}
If you are using [Grafana OnCall](https://grafana.com/docs/oncall/latest/get-started/), you can try out the integration between Grafana OnCall and RBAC.
For a detailed list of the available OnCall RBAC roles, refer to the table in [Available Grafana OnCall RBAC roles and granted actions](https://grafana.com/docs/oncall/latest/user-and-team-management/#available-grafana-oncall-rbac-roles--granted-actions).
If you are using [Grafana OnCall](ref:oncall), you can try out the integration between Grafana OnCall and RBAC.
For a detailed list of the available OnCall RBAC roles, refer to the table in [Available Grafana OnCall RBAC roles and granted actions](ref:available-grafana-oncall-rbac-roles--granted-actions).
The following table lists the default RBAC OnCall role assignments to the basic roles:
| Basic role | Associated fixed roles | Description |
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
You can create, change or remove [Custom roles]({{< relref "./manage-rbac-roles/#create-custom-roles-using-provisioning" >}}) and create or remove [basic role assignments]({{< relref "./assign-rbac-roles/#assign-a-fixed-role-to-a-basic-role-using-provisioning" >}}), by adding one or more YAML configuration files in the `provisioning/access-control/` directory.
You can create, change or remove [Custom roles](ref:manage-rbac-roles-create-custom-roles-using-provisioning) and create or remove [basic role assignments](ref:assign-rbac-roles-assign-a-fixed-role-to-a-basic-role-using-provisioning), by adding one or more YAML configuration files in the `provisioning/access-control/` directory.
Grafana performs provisioning during startup. After you make a change to the configuration file, you can reload it during runtime. You do not need to restart the Grafana server for your changes to take effect.
@ -37,13 +73,13 @@ Grafana performs provisioning during startup. After you make a change to the con
1. Add RBAC provisioning details to the configuration file.
Refer to [Manage RBAC roles]({{< relref "./manage-rbac-roles/" >}}) and [Assign RBAC roles]({{< relref "./assign-rbac-roles/" >}}) for instructions.
Refer to [Manage RBAC roles](ref:rbac-manage-rbac-roles) and [Assign RBAC roles](ref:rbac-assign-rbac-roles) for instructions.
Refer to [example role provisioning file]({{< relref "#example-role-configuration-file-using-grafana-provisioning" >}}) for a complete example of a provisioning file.
Refer to [example role provisioning file](#example-role-configuration-file-using-grafana-provisioning) for a complete example of a provisioning file.
1. Reload the provisioning configuration file.
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations]({{< relref "../../../../developers/http_api/admin/#reload-provisioning-configurations" >}}).
For more information about reloading the provisioning configuration at runtime, refer to [Reload provisioning configurations](/docs/grafana/<GRAFANA_VERSION>/developers/http_api/admin/#reload-provisioning-configurations).
## Example role configuration file using Grafana provisioning
@ -131,6 +167,6 @@ teams:
## Useful Links
[Provisioning RBAC setup with Terraform]({{< relref "./rbac-terraform-provisioning">}})
[Provisioning RBAC setup with Terraform](ref:rbac-terraform-provisioning)
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
You can create, change or remove [Custom roles](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/role) and create or remove [basic and custom role assignments](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/role_assignment), by using [Terraform's Grafana provider](https://registry.terraform.io/providers/grafana/grafana/latest/docs).
@ -28,15 +59,15 @@ You can create, change or remove [Custom roles](https://registry.terraform.io/pr
## Create a Service Account Token for provisioning
We recommend using service account tokens for provisioning. [Service accounts]({{< relref "../../../service-accounts/" >}}) support fine grained permissions, which allows you to easily authenticate and use the minimum set of permissions needed to provision your RBAC infrastructure.
We recommend using service account tokens for provisioning. [Service accounts](ref:service-accounts) support fine grained permissions, which allows you to easily authenticate and use the minimum set of permissions needed to provision your RBAC infrastructure.
To create a service account token for provisioning, complete the following steps.
1. [Create a new service account]({{< relref "../../../service-accounts/#create-a-service-account-in-grafana" >}}) for your CI pipeline.
1. [Assign permissions to service account]({{< relref "../../../service-accounts/#assign-roles-to-a-service-account-in-grafana" >}}):
1. [Create a new service account](ref:service-accounts-create-a-service-account-in-grafana) for your CI pipeline.
1. [Assign permissions to service account](ref:service-accounts-assign-roles-to-a-service-account-in-grafana):
- You will need roles “Role reader”, "Role writer" and roles including any permissions that will be provisioned. For example, to create or assign a role that allows creating users, a service account needs permissions to create users.
- Alternatively, you can assign "Admin" basic role to the service account.
1. [Create a new service account token]({{< relref "../../../service-accounts/#to-add-a-token-to-a-service-account" >}}) for use in Terraform.
1. [Create a new service account token](ref:service-accounts-to-add-a-token-to-a-service-account) for use in Terraform.
Alternatively, you can use basic authentication. To view all the supported authentication formats, see [here](https://registry.terraform.io/providers/grafana/grafana/latest/docs#authentication).

Note that instead of using a provisioned role, you can also look up the `uid` of an already existing fixed or custom role and use that instead.
You can use the [API endpoint for listing roles](https://grafana.com/docs/grafana/latest/developers/http_api/access_control/#create-and-manage-custom-roles) to look up role `uid`s.
You can use the [API endpoint for listing roles](ref:api-rbac-create-and-manage-custom-roles) to look up role `uid`s.
Similarly, you can look up and use `id`s of users, teams and service accounts that have not been provisioned to assign roles to them.
## Useful Links
[RBAC setup with Grafana provisioning]({{< relref "./rbac-grafana-provisioning">}})
[RBAC setup with Grafana provisioning](ref:rbac-grafana-provisioning)
Available in [Grafana Enterprise]({{< relref "../../../../introduction/grafana-enterprise/" >}}) version 7.3 and later, and [Grafana Cloud](/docs/grafana-cloud).
Available in [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/) version 7.3 and later, and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
You can enable auditing in the Grafana configuration file.
@ -38,11 +38,11 @@ enabled = true
```
All permission and role updates, and role assignments are added to audit logs.
Learn more about [access control audit logs]({{< relref "../../../../setup-grafana/configure-security/audit-grafana/#access-control" >}}).
Learn more about [access control audit logs](/docs/grafana/<GRAFANA_VERSION>/setup-grafana/configure-security/audit-grafana/#access-control).
## Missing dashboard, folder or data source permissions
[Dashboard and folder permissions]({{< relref "../../#dashboard-permissions" >}}) and [data source permissions]({{< relref "../../#data-source-permissions" >}}) can go out of sync if a Grafana instance version is upgraded, downgraded and then upgraded again.
[Dashboard and folder permissions](/docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/#dashboard-permissions) and [data source permissions](/docs/grafana/<GRAFANA_VERSION>/administration/roles-and-permissions/#data-source-permissions) can go out of sync if a Grafana instance version is upgraded, downgraded and then upgraded again.
This happens when an instance is downgraded from a version that uses RBAC to a version that uses the legacy access control, and dashboard, folder or data source permissions are updated.
These permission updates will not be applied to RBAC, so permissions will be out of sync when the instance is next upgraded to a version with RBAC.
You can use a service account to run automated workloads in Grafana, such as dashboard provisioning, configuration, or report generation. Create service accounts and tokens to authenticate applications, such as Terraform, with the Grafana API.
{{% admonition type="note" %}}
Service accounts replace [API keys]({{< relref "../api-keys/" >}}) as the primary way to authenticate applications that interact with Grafana.
{{% /admonition %}}
{{<admonitiontype="note">}}
Service accounts replace [API keys](ref:migrate-api-keys) as the primary way to authenticate applications that interact with Grafana.
{{</admonition>}}
A common use case for creating a service account is to perform operations on automated or triggered tasks. You can use service accounts to:
@ -32,15 +74,17 @@ A common use case for creating a service account is to perform operations on aut
- Set up an external SAML authentication provider
- Interact with Grafana without signing in as a user
In [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}), you can also use service accounts in combination with [role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}) to grant very specific permissions to applications that interact with Grafana.
In [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/), you can also use service accounts in combination with [role-based access control](ref:rbac) to grant very specific permissions to applications that interact with Grafana.
{{% admonition type="note" %}}
Service accounts can only act in the organization they are created for. If you have the same task that is needed for multiple organizations, we recommend creating service accounts in each organization.
Service accounts can't be used for instance-wide operations, such as global user management and organization management. For these tasks, you need to use a user with [Grafana server administrator permissions](ref:roles-and-permissions).
{{% /admonition %}}
{{<vimeo742056367>}}
_Video shows service accounts in Grafana v9.1. Refer to [Create a service account in Grafana]({{< relref "#create-a-service-account-in-grafana" >}}) for current instructions._
_Video shows service accounts in Grafana v9.1. Refer to [Create a service account in Grafana](#create-a-service-account-in-grafana) for current instructions._
## Service account tokens
@ -62,19 +106,19 @@ The added benefits of service accounts to API keys include:
- Service accounts resemble Grafana users and can be enabled/disabled, granted specific permissions, and remain active until they are deleted or disabled. API keys are only valid until their expiry date.
- Service accounts can be associated with multiple tokens.
- Unlike API keys, service account tokens are not associated with a specific user, which means that applications can be authenticated even if a Grafana user is deleted.
- You can grant granular permissions to service accounts by leveraging [role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}). For more information about permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/" >}}).
- You can grant granular permissions to service accounts by leveraging [role-based access control](ref:rbac). For more information about permissions, refer to [About users and permissions](ref:roles-and-permissions).
## Create a service account in Grafana
A service account can be used to run automated workloads in Grafana, like dashboard provisioning, configuration, or report generation. For more information about how you can use service accounts, refer to [About service accounts]({{< ref "#about-service-accounts" >}}).
A service account can be used to run automated workloads in Grafana, like dashboard provisioning, configuration, or report generation. For more information about how you can use service accounts, refer to [About service accounts](ref:service-accounts).
For more information about creating service accounts via the API, refer to [Create a service account in the HTTP API]({{< relref "../../developers/http_api/serviceaccount/#create-service-account" >}}).
For more information about creating service accounts via the API, refer to [Create a service account in the HTTP API](ref:api-create-service-account).
Note that the user who created a service account will also be able to read, update and delete the service account that they created, as well as permissions associated with that service account.
### Before you begin
- Ensure you have permission to create and edit service accounts. By default, the organization administrator role is required to create and edit service accounts. For more information about user permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/#" >}}).
- Ensure you have permission to create and edit service accounts. By default, the organization administrator role is required to create and edit service accounts. For more information about user permissions, refer to [About users and permissions](ref:roles-and-permissions).
### To create a service account
@ -90,13 +134,13 @@ Note that the user who created a service account will also be able to read, upda
## Add a token to a service account in Grafana
A service account token is a generated random string that acts as an alternative to a password when authenticating with Grafana’s HTTP API. For more information about service accounts, refer to [About service accounts in Grafana]({{< ref "#about-service-accounts" >}}).
A service account token is a generated random string that acts as an alternative to a password when authenticating with Grafana’s HTTP API. For more information about service accounts, refer to [About service accounts in Grafana](ref:service-accounts).
You can create a service account token using the Grafana UI or via the API. For more information about creating a service account token via the API, refer to [Create service account tokens using the HTTP API]({{< relref "../../developers/http_api/serviceaccount/#create-service-account-tokens" >}}).
You can create a service account token using the Grafana UI or via the API. For more information about creating a service account token via the API, refer to [Create service account tokens using the HTTP API](ref:api-create-service-account-tokens).
### Before you begin
- Ensure you have permission to create and edit service accounts. By default, the organization administrator role is required to create and edit service accounts. For more information about user permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/#" >}}).
- Ensure you have permission to create and edit service accounts. By default, the organization administrator role is required to create and edit service accounts. For more information about user permissions, refer to [About users and permissions](ref:roles-and-permissions).
### Service account token expiration dates
@ -118,9 +162,9 @@ By default, service account tokens don't have an expiration date, meaning they w
## Assign roles to a service account in Grafana
You can assign roles to a Grafana service account to control access for the associated service account tokens.
You can assign roles to a service account using the Grafana UI or via the API. For more information about assigning a role to a service account via the API, refer to [Update service account using the HTTP API]({{< relref "../../developers/http_api/serviceaccount/#update-service-account" >}}).
You can assign roles to a service account using the Grafana UI or via the API. For more information about assigning a role to a service account via the API, refer to [Update service account using the HTTP API](ref:api-update-service-account).
In [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}), you can also [assign RBAC roles]({{< relref "../roles-and-permissions/access-control/assign-rbac-roles" >}}) to grant very specific permissions to applications that interact with Grafana.
In [Grafana Enterprise](/docs/grafana/<GRAFANA_VERSION>/introduction/grafana-enterprise/), you can also [assign RBAC roles](ref:rbac-assign-rbac-roles) to grant very specific permissions to applications that interact with Grafana.
{{% admonition type="note" %}}
Since Grafana 10.2.0, the `No Basic Role` is available for organization users or service accounts. This role has no permissions. Permissions can be granted with RBAC.
@ -128,7 +172,7 @@ Since Grafana 10.2.0, the `No Basic Role` is available for organization users or
### Before you begin
- Ensure you have permission to update service accounts roles. By default, the organization administrator role is required to update service accounts permissions. For more information about user permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/#" >}}).
- Ensure you have permission to update service accounts roles. By default, the organization administrator role is required to update service accounts permissions. For more information about user permissions, refer to [About users and permissions](ref:roles-and-permissions).
### To assign a role to a service account
@ -144,7 +188,7 @@ To control what and who can do with the service account you can assign permissio
### Before you begin
- Ensure you have permission to update user and team permissions of a service accounts. By default, the organization administrator role is required to update user and teams permissions for a service account. For more information about user permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/#" >}}).
- Ensure you have permission to update user and team permissions of a service accounts. By default, the organization administrator role is required to update user and teams permissions for a service account. For more information about user permissions, refer to [About users and permissions](ref:roles-and-permissions).
- Ensure you have permission to read teams.
### User and team permissions for a service account
@ -183,7 +227,7 @@ This can help you diagnose permissions-related issues with token authorization.
These endpoints provide details on a service account's token.
If you haven't added a token to a service account, do so before proceeding.
For details, refer to [Add a token to a service account]({{< relref "#add-a-token-to-a-service-account-in-grafana" >}}).
For details, refer to [Add a token to a service account](#add-a-token-to-a-service-account-in-grafana).
Deprecated: [Service accounts]({{< relref "../service-accounts/" >}}) have replaced API keys as the primary way to authenticate applications that interact with Grafana.
API keys are deprecated. [Service accounts](ref:service-accounts) now replace API keys for authenticating with the **HTTP APIs** and interacting with Grafana.
{{% /admonition %}}
An API key is a randomly generated string that external systems use to interact with Grafana HTTP APIs.
API keys specify a role—either **Admin**, **Editor**, or **Viewer**—that determine the permissions associated with interacting with Grafana.
When you create an API key, you specify a **Role** that determines the permissions associated with the API key. Role permissions control that actions the API key can perform on Grafana resources.
Compared to API keys, service accounts have limited scopes that provide more security. For more information on the benefits of service accounts, refer to [service account benefits](ref:service-accounts-benefits).
{{% admonition type="note" %}}
If you use Grafana v9.1 or newer, use service accounts instead of API keys. For more information, refer to [Grafana service accounts]({{< relref "../service-accounts/" >}}).
{{% /admonition %}}
{{<section>}}
## Create an API key
Create an API key when you want to manage your computed workload with a user.
This topic shows you how to create an API key using the Grafana UI. You can also create an API key using the Grafana HTTP API. For more information about creating API keys via the API, refer to [Create API key via API]({{< relref "../../developers/http_api/create-api-tokens-for-org/#how-to-create-a-new-organization-and-an-api-token" >}}).
### Before you begin
To follow these instructions, you need at least one of the following:
- Administrator permissions
- Editor permissions
- Service account writer
- To ensure you have permission to create and edit API keys, follow the instructions in [Roles and permissions]({{< relref "../roles-and-permissions/#" >}}).
### Steps
To create an API key, complete the following steps:
When you migrate an API key to a service account, a service account is created with a service account token. Your existing API key—now migrated to a service account token—will continue working as before.
1. Sign in to Grafana.
1. Click **Administration** in the left-side menu, **Users and access**, and select **API Keys**.
1. Click **Add API key**.
1. Enter a unique name for the key.
1. In the **Role** field, select one of the following access levels you want to assign to the key.
- **Admin**: Enables a user to use APIs at the broadest, most powerful administrative level.
- **Editor** or **Viewer** to limit the key's users to those levels of power.
1. In the **Time to live** field, specify how long you want the key to be valid.
- The maximum length of time is 30 days (one month). You enter a number and a letter. Valid letters include `s` for seconds,`m` for minutes, `h` for hours, `d `for days, `w` for weeks, and `M `for month. For example, `12h` is 12 hours and `1M` is 1 month (30 days).
- If you are unsure about how long an API key should be valid, we recommend that you choose a short duration, such as a few hours. This approach limits the risk of having API keys that are valid for a long time.
1. Click **Add**.
## Migrate API keys to Grafana service accounts
As an alternative to using API keys for authentication, you can use a service account-based authentication system. When compared to API keys, service accounts have limited scopes that provide more security than using API keys.
For more information about the benefits of service accounts, refer to [Grafana service account benefits]({{< relref "../service-accounts/#service-account-benefits" >}}).
The service account endpoints generate a machine user for authentication instead of using API keys. When you migrate an API key to a service account, a service account will be created with a service account token.
{{% admonition type="note" %}}
If you're currently using API keys for authentication, we strongly recommend to use Grafana Service Accounts instead. Rest assured, when migrating to Service Accounts, your existing API keys will continue working as before. To find the migrated API keys, navigate to the Service Accounts section and select the Service Account Tokens tab. For more information, please refer to the [Grafana service account tokens]({{< relref "../service-accounts/#service-account-tokens" >}}) details.
{{% /admonition %}}
## Ways of migrating API keys to service accounts
If you are currently using API keys in your environment, you need to reconfigure your setup to use service accounts.
Depending on your current setup, you may need to use one or all of the following methods to migrate your environment to service accounts:
To find the migrated API keys, click **Administration** in the left-side menu, then **Users and access -> Service Accounts**, select the service account, and locate the **Token**.
- The Grafana user interface: Use this method if you have been using the UI to manage your API keys and want to switch to using service accounts.
- The Grafana API: Use this method if you have been using API calls to manage your API keys and want to switch to using service accounts programmatically.
- Terraform: If you have a Terraform configuration that sets up API keys, you need to reconfigure your Terraform to use service accounts instead.
By following these steps, you can successfully migrate your integration from API keys to service accounts and continue using Grafana seamlessly.
### Migrate API keys to Grafana service accounts using the Grafana user interface
## Migrate API keys using the Grafana user interface
This section shows you how to migrate API keys to Grafana service accounts using the Grafana user interface. You can choose to migrate a single API key or all API keys. When you migrate all API keys, you can no longer create API keys and must use service accounts instead.
@ -99,7 +64,7 @@ To follow these instructions, you need at least one of the following:
- Editor permissions
- Service account writer
For more information about permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions/#" >}}).
For more information about permissions, refer to [Roles and permissions](ref:roles-and-permissions).
#### Steps
@ -118,9 +83,9 @@ To migrate a single API key to a service account, complete the following steps:
1. Find the API Key you want to migrate.
1. Click **Migrate to service account**.
### Migrate API keys to Grafana service accounts for API calls
## Migrate API keys using the HTTP API
This section shows you how to migrate API keys to Grafana service accounts for Grafana API workflows. For references see: [Grafana Service Accounts for the Grafana API]({{< relref "../../developers/http_api/serviceaccount/#create-service-account" >}}).
This section shows you how to programmatically migrate API keys to Grafana service accounts using the HTTP API. For API additional information, refer to [Service account HTTP APIs](ref:api-service-account).
### Migrate API keys to Grafana service accountsin Terraform
## Migrate API keys using Terraform
{{<admonitiontype="note">}}
The terraform resource `api_key` is removed from the Grafana Terraform Provider in v3.0.0.
@ -201,9 +166,7 @@ terraform {
}
```
This section shows you how to migrate your Terraform configuration for API keys to Grafana service accounts. For resources, see [Grafana Service Accounts in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/service_account_token).
For migration your cloud stack api keys, use the `grafana_cloud_stack_service_account` and `gafana_cloud_stack_service_account_token` resources see [Grafana Cloud Stack Service Accounts in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_stack_service_account).
This section shows you how to migrate your Terraform configuration for API keys to Grafana service accounts. For additional information, refer to [Grafana Service Accounts in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/service_account_token).
### Migrate Cloud **Stack** API keys to Grafana cloud stack service accounts in Terraform
## Migrate Cloud Stack API keys using Terraform
This section shows you how to migrate your Terraform configuration for Grafana cloud stack API keys to Grafana cloud stack service accounts.
This section shows you how to migrate your Terraform configuration for Grafana cloud stack API keys to Grafana cloud stack service accounts. For migration your cloud stack api keys, use the `grafana_cloud_stack_service_account` and `gafana_cloud_stack_service_account_token` resources see [Grafana Cloud Stack Service Accounts in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_stack_service_account).
For migration your cloud stack api keys, use the `grafana_cloud_stack_service_account` and `gafana_cloud_stack_service_account_token` resources. For additional information, refer to [Grafana Cloud Stack Service Accounts in Terraform](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/cloud_stack_service_account).
{{% admonition type="note" %}}
This is only relevant for Grafana Cloud **Stack** API keys `grafana_cloud_stack_api_key`. Grafana Cloud API keys resource `grafana_cloud_api_key` are not deprecated and should be used for authentication for managing your Grafana cloud.
@ -83,10 +83,7 @@ Grafana-managed rules are the most flexible alert rule type. They allow you to c
Multiple alert instances can be created as a result of one alert rule (also known as a multi-dimensional alerting).
{{% admonition type="note" %}}
For Grafana Cloud, there are limits on how many Grafana-managed alert rules you can create. These are as follows:
- Free: 100 alert rules
- Paid: 2000 alert rules
For Grafana Cloud Free Forever, you can create up to 100 free Grafana-managed alert rules with each alert rule having a maximum of 1000 alert instances.
{{% /admonition %}}
Grafana managed alert rules can only be edited or deleted by users with Edit permissions for the folder storing the rules.
@ -235,14 +232,12 @@ Annotations add metadata to provide more information on the alert in your alert
1. Optional: Add a custom annotation
1. Optional: Add a **dashboard and panel link**.
Links alerts to panels in a dashboard.
Links alert rules to panels in a dashboard.
{{% admonition type="note" %}}
At the moment, alerts are only supported in the [time series](ref:time-series) and [alert list](ref:alert-list) visualizations.
At the moment, alert rules are only supported in [time series](ref:time-series) and [alert list](ref:alert-list) visualizations.
{{% /admonition %}}
{{<docs/playtitle="visualizations with linked alerts in Grafana"url="https://play.grafana.org/d/000000074/">}}
1. Click **Save rule**.
## Configure no data and error handling
@ -256,7 +251,7 @@ You can configure the alert instance state when its evaluation returns no data:
| No Data | The default option. Sets alert instance state to `No data`. <br/> The alert rule also creates a new alert instance `DatasourceNoData` with the name and UID of the alert rule, and UID of the datasource that returned no data as labels. |
| Alerting | Sets alert instance state to `Alerting`. It waits until the [pending period](ref:pending-period) has finished. |
| Alerting | Sets the alert instance state to `Pending` and then transitions to `Alerting` once the [pending period](ref:pending-period) ends. If you sent the pending period to 0, the alert instance state is immediately set to `Alerting`. |
| Normal | Sets alert instance state to `Normal`. |
| Keep Last State | Maintains the alert instance in its last state. Useful for mitigating temporary issues, refer to [Keep last state](ref:keep-last-state). |
@ -265,18 +260,8 @@ You can also configure the alert instance state when its evaluation returns an e
| Error | The default option. Sets alert instance state to `Error`. <br/> The alert rule also creates a new alert instance `DatasourceError` with the name and UID of the alert rule, and UID of the datasource that returned no data as labels. |
| Alerting | Sets alert instance state to `Alerting`. It waits until the [pending period](ref:pending-period) has finished. |
| Alerting | Sets alert instance state to `Alerting`. It transitions from `Pending` to `Alerting` after the [pending period](ref:pending-period) has finished. |
| Normal | Sets alert instance state to `Normal`. |
| Keep Last State | Maintains the alert instance in its last state. Useful for mitigating temporary issues, refer to [Keep last state](ref:keep-last-state). |
When you configure the No data or Error behavior to `Alerting` or `Normal`, Grafana will attempt to keep a stable set of fields under notification `Values`. If your query returns no data or an error, Grafana re-uses the latest known set of fields in `Values`, but will use `-1` in place of the measured value.
## Create alerts from panels
Create alerts from any panel type. This means you can reuse the queries in the panel and create alerts based on them.
1. Navigate to a dashboard in the **Dashboards** section.
2. In the top right corner of the panel, click on the three dots (ellipses).
3. From the dropdown menu, select **More...** and then choose **New alert rule**.
This will open the alert rule form, allowing you to configure and create your alert based on the current panel's query.
description: Configure the MQTT notifier integration for Alerting
keywords:
- grafana
- alerting
- guide
- contact point
- mqtt
labels:
products:
- cloud
- enterprise
- oss
menuTitle: MQTT notifier
title: Configure the MQTT notifier for Alerting
weight: 80
---
# Configure the MQTT notifier for Alerting
Use the Grafana Alerting - MQTT integration to send notifications to an MQTT broker when your alerts are firing.
## Procedure
To configure the MQTT integration for Alerting, complete the following steps.
1. In the left-side menu, click **Alerts & IRM** and then **Alerting**.
1. On the **Contact Points** tab, click **+ Add contact point**.
1. Enter a descriptive name for the contact point.
1. From the Integration list, select **MQTT**.
1. Enter your broker URL in the **Broker URL** field. Supports `tcp`, `ssl`, `mqtt`, `mqtts`, `ws`, `wss` schemes. For example: `tcp://127.0.0.1:1883`.
1. Enter the MQTT topic name in the **Topic** field.
1. In **Optional MQTT settings**, specify additional settings for the MQTT integration if needed.
1. Click **Test** to check that your integration works.
A test alert notification should be sent to the MQTT broker.
1. Click **Save** contact point.
The integration sends data in JSON format by default. You can change that using **Message format** field in the **Optional MQTT settings** section. There are two supported formats:
- **JSON**: Sends the alert notification in JSON format.
- **Text**: Sends the rendered alert notification message in plain text format.
## MQTT JSON payload
If the JSON message format is selected in **Optional MQTT settings**, the payload is sent in the following structure.
```json
{
"receiver": "My MQTT integration",
"status": "firing",
"orgId": 1,
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "High memory usage",
"team": "blue",
"zone": "us-1"
},
"annotations": {
"description": "The system has high memory usage",
"message": "**Firing**\n\nLabels:\n - alertname = T2\n - team = blue\n - zone = us-1\nAnnotations:\n - description = This is the alert rule checking the second system\n - runbook_url = https://myrunbook.com\n - summary = This is my summary\nSource: https://play.grafana.org/alerting/1afz29v7z/edit\nSilence: https://play.grafana.org/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DT2%2Cteam%3Dblue%2Czone%3Dus-1\n\nLabels:\n - alertname = T1\n - team = blue\n - zone = eu-1\nAnnotations:\nSource: https://play.grafana.org/alerting/d1rdpdv7k/edit\nSilence: https://play.grafana.org/alerting/silence/new?alertmanager=grafana&matchers=alertname%3DT1%2Cteam%3Dblue%2Czone%3Deu-1\n"
}
```
### Payload fields
Each notification payload contains the following fields.
Whether you’re just starting out or you're a more experienced user of Grafana Alerting, learn more about the fundamentals and available features that help you create, manage, and respond to alerts; and improve your team’s ability to resolve issues quickly. For a hands-on introduction, refer to our [tutorial to get started with Grafana Alerting](http://grafana.com/tutorials/alerting-get-started/).
Whether you’re just starting out or you're a more experienced user of Grafana Alerting, learn more about the fundamentals and available features that help you create, manage, and respond to alerts; and improve your team’s ability to resolve issues quickly.
{{<admonitiontype="tip">}}
For a hands-on introduction, refer to our [tutorial to get started with Grafana Alerting](http://grafana.com/tutorials/alerting-get-started/).
{{</admonition>}}
The following diagram gives you an overview of Grafana Alerting and introduces you to some of the fundamental features that are the principles of how Grafana Alerting works.
| **Normal** | The state of an alert when the condition (threshold) is not met. |
| **Pending** | The state of an alert that has breached the threshold but for less than the [pending period](ref:pending-period). |
| **Alerting** | The state of an alert that has breached the threshold for longer than the [pending period](ref:pending-period). |
| **NoData** | The state of an alert whose query returns no data or all values are null. You can [change the default behavior](/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/#configure-no-data-and-error-handling). |
| **Error** | The state of an alert when an error or timeout occurred evaluating the alert rule. You can [change the default behavior](/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/#configure-no-data-and-error-handling). |
| **NoData** | The state of an alert whose query returns no data or all values are null. You can [change the default behavior of the no data state](#modify-the-no-data-and-error-state). |
| **Error** | The state of an alert when an error or timeout occurred evaluating the alert rule. You can [change the default behavior of the error state](#modify-the-no-data-and-error-state). |
{{<figuresrc="/media/docs/alerting/alert-instance-states-v3.png"caption="Alert instance state diagram"alt="A diagram of the distinct alert instance states and transitions."max-width="750px">}}
@ -64,18 +64,46 @@ Alert instances will be routed for [notifications](ref:notifications) when they
An alert instance is considered stale if its dimension or series has disappeared from the query results entirely for two evaluation intervals.
Stale alert instances that are in the **Alerting**, **NoData**, or **Error** states transition to the **Normal** state as **Resolved**, and include the `grafana_state_reason` annotation with the value **MissingSeries**. They are routed for notifications like other resolved alert instances.
Stale alert instances that are in the **Alerting**, **NoData**, or **Error** states transition to the **Normal** state as **Resolved**. Once transitioned, these resolved alert instances are routed for notifications like other resolved alerts.
### Keep last state
### Modify the no data and error state
The "Keep Last State" option helps mitigate temporary data source issues, preventing alerts from unintentionally firing, resolving, and re-firing.
In [Configure no data and error handling,](ref:no-data-and-error-handling) you can decide to keep the last state of the alert instance when a `NoData` and/or `Error` state is encountered. Just like normal evaluation, the alert instance transitions from `Pending` to `Alerting` after the pending period has elapsed.
In [Configure no data and error handling](ref:no-data-and-error-handling), you can change the default behaviour when the evaluation returns no data or an error. You can set the alert instance state to `Alerting`, `Normal`, or keep the last state.
{{<figuresrc="/media/docs/alerting/alert-rule-configure-no-data-and-error.png"alt="A screenshot of the `Configure no data and error handling` option in Grafana Alerting."max-width="500px">}}
To reduce the number of **No Data** or **Error** state alerts received, try the following.
1. Use the **Keep last state** option. For more information, refer to the section below. This option allows the alert to retain its last known state when there is no data available, rather than switching to a **No Data** state.
1. For **No Data** alerts, you can optimize your alert rule by expanding the time range of the query. However, if the time range is too big, it affects the performance of the query and can lead to errors due to timeout.
To minimize timeouts resulting in the **Error** state, reduce the time range to request less data every evaluation cycle.
1. Change the default [evaluation time out](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#evaluation_timeout). The default is set at 30 seconds. To increase the default evaluation timeout, open a support ticket from the [Cloud Portal](https://grafana.com/docs/grafana-cloud/account-management/support/#grafana-cloud-support-options). Note that this should be a last resort, because it may affect the performance of all alert rules and cause missed evaluations if the timeout is too long.
#### Keep last state
The "Keep Last State" option helps mitigate temporary data source issues, preventing alerts from unintentionally firing, resolving, and re-firing.
However, in situations where strict monitoring is critical, relying solely on the "Keep Last State" option may not be appropriate. Instead, consider using an alternative or implementing additional alert rules to ensure that issues with prolonged data source disruptions are detected.
### `grafana_state_reason` annotation
Occasionally, an alert instance may be in a state that isn't immediately clear to everyone. For example:
- Stale alert instances in the `Alerting` state transition to the `Normal` state when the series disappear.
- If "no data" handling is configured to transition to a state other than `NoData`.
- If "error" handling is configured to transition to a state other than `Error`.
- If the alert rule is deleted, paused, or updated in some cases, the alert instance also transitions to the `Normal` state.
In these situations, the evaluation state may differ from the alert state, and it might be necessary to understand the reason for being in that state when receiving the notification.
The `grafana_state_reason` annotation is included in these situations, providing the reason in the notifications that explain why the alert instance transitioned to its current state. For example:
- Stale alert instances in the `Normal` state include the `grafana_state_reason` annotation with the value **MissingSeries**.
- If "no data" or "error" handling transitions to the `Normal` state, the `grafana_state_reason` annotation is included with the value **NoData** or **Error**, respectively.
- If the alert rule is deleted or paused, the `grafana_state_reason` is set to **Paused** or **RuleDeleted**. For some updates, it is set to **Updated**.
### Special alerts for `NoData` and `Error`
When evaluation of an alert rule produces state `NoData` or `Error`, Grafana Alerting generates a new alert instance that have the following additional labels:
@ -136,7 +136,7 @@ These functions are available for **Reduce** and **Classic condition** expressio
An alert condition is the query or expression that determines whether the alert fires or not depending on the value it yields. There can be only one condition which determines the triggering of the alert.
After you have defined your queries and/or expressions, choose one of them as the alert rule condition. By default, the last expression added is used as the alert condition.
After you have defined your queries and expressions, choose one of them as the alert rule condition. By default, the last expression added is used as the alert condition.
When the queried data satisfies the defined condition, Grafana triggers the associated alert, which can be configured to send notifications through various channels like email, Slack, or PagerDuty.
@ -57,7 +57,7 @@ An alert event is displayed each time an alert instance changes its state over a
{{% admonition type="note" %}}
For Grafana Enterprise and OSS users:
The feature is available starting with Grafana 11.2.
To try out the new alert history page, enable the `alertingCentralAlertHistory` feature toggle and configure [Loki annotations](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/alerting/set-up/configure-alert-state-history/).
Users can only see the history and transitions of alert rules they have access to (RBAC).
@ -28,18 +39,13 @@ Grafana Alerting uses the Prometheus model of separating the evaluation of alert
When running multiple instances of Grafana, all alert rules are evaluated on all instances. You can think of the evaluation of alert rules as being duplicated by the number of running Grafana instances. This is how Grafana Alerting makes sure that as long as at least one Grafana instance is working, alert rules are still be evaluated and notifications for alerts are still sent.
You can find this duplication in state history and it is a good way to confirm if you are using high availability.
You can find this duplication in state history and it is a good way to [verify your high availability setup](#verify-your-high-availability-setup).
While the alert generator evaluates all alert rules on all instances, the alert receiver makes a best-effort attempt to avoid sending duplicate notifications. Alertmanager chooses availability over consistency, which may result in occasional duplicated or out-of-order notifications. It takes the opinion that duplicate or out-of-order notifications are better than no notifications.
While the alert generator evaluates all alert rules on all instances, the alert receiver makes a best-effort attempt to avoid duplicate notifications. The alertmanagers use a gossip protocol to share information between them to prevent sending duplicated notifications.
The Alertmanager uses a gossip protocol to share information about notifications between Grafana instances. It also gossips silences, which means a silence created on one Grafana instance is replicated to all other Grafana instances. Both notifications and silences are persisted to the database periodically, and during graceful shut down.
Alertmanager chooses availability over consistency, which may result in occasional duplicated or out-of-order notifications. It takes the opinion that duplicate or out-of-order notifications are better than no notifications.
{{% admonition type="note" %}}
If using a mix of `execute_alerts=false` and `execute_alerts=true` on the HA nodes, since the alert state is not shared amongst the Grafana instances, the instances with `execute_alerts=false` do not show any alert status.
This is because the HA settings (`ha_peers`, etc) only apply to the alert notification delivery (i.e. de-duplication of alert notifications, and silences, as mentioned above).
{{% /admonition %}}
Alertmanagers also gossip silences, which means a silence created on one Grafana instance is replicated to all other Grafana instances. Both notifications and silences are persisted to the database periodically, and during graceful shut down.
## Enable alerting high availability using Memberlist
@ -56,6 +62,8 @@ Since gossiping of notifications and silences uses both TCP and UDP port `9094`,
By default, it is set to listen to all interfaces (`0.0.0.0`).
1. Set `[ha_peer_timeout]` in the `[unified_alerting]` section of the custom.ini to specify the time to wait for an instance to send a notification via the Alertmanager. The default value is 15s, but it may increase if Grafana servers are located in different geographic regions or if the network latency between them is high.
For a demo, see this [example using Docker Compose](https://github.com/grafana/alerting-ha-docker-examples/tree/main/memberlist).
## Enable alerting high availability using Redis
As an alternative to Memberlist, you can use Redis for high availability. This is useful if you want to have a central
@ -68,19 +76,7 @@ database for HA and cannot support the meshing of all Grafana servers.
1. Optional: Set `ha_redis_prefix` to something unique if you plan to share the Redis server with multiple Grafana instances.
1. Optional: Set `ha_redis_tls_enabled` to `true` and configure the corresponding `ha_redis_tls_*` fields to secure communications between Grafana and Redis with Transport Layer Security (TLS).
The following metrics can be used for meta monitoring, exposed by the `/metrics` endpoint in Grafana:
| alertmanager_cluster_messages_received_total | Total number of cluster messages received. |
| alertmanager_cluster_messages_received_size_total | Total size of cluster messages received. |
| alertmanager_cluster_messages_sent_total | Total number of cluster messages sent. |
| alertmanager_cluster_messages_sent_size_total | Total number of cluster messages received. |
| alertmanager_cluster_messages_publish_failures_total | Total number of messages that failed to be published. |
| alertmanager_cluster_members | Number indicating current number of members in cluster. |
| alertmanager_peer_position | Position the Alertmanager instance believes it's in. The position determines a peer's behavior in the cluster. |
| alertmanager_cluster_pings_seconds | Histogram of latencies for ping messages. |
| alertmanager_cluster_pings_failures_total | Total number of failed pings. |
For a demo, see this [example using Docker Compose](https://github.com/grafana/alerting-ha-docker-examples/tree/main/redis).
## Enable alerting high availability using Kubernetes
@ -149,3 +145,58 @@ The following metrics can be used for meta monitoring, exposed by the `/metrics`
ha_peer_timeout = 15s
ha_reconnect_timeout = 2m
```
## Verify your high availability setup
When running multiple Grafana instances, all alert rules are evaluated on every instance. This multiple evaluation of alert rules is visible in the [state history](ref:state-history) and provides a straightforward way to verify that your high availability configuration is working correctly.
{{% admonition type="note" %}}
If using a mix of `execute_alerts=false` and `execute_alerts=true` on the HA nodes, since the alert state is not shared amongst the Grafana instances, the instances with `execute_alerts=false` do not show any alert status.
The HA settings (`ha_peers`, etc.) apply only to communication between alertmanagers, synchronizing silences and attempting to avoid duplicate notifications, as described in the introduction.
{{% /admonition %}}
You can also confirm your high availability setup by monitoring Alertmanager metrics exposed by Grafana.
| alertmanager_cluster_members | Number indicating current number of members in cluster. |
| alertmanager_cluster_messages_received_total | Total number of cluster messages received. |
| alertmanager_cluster_messages_received_size_total | Total size of cluster messages received. |
| alertmanager_cluster_messages_sent_total | Total number of cluster messages sent. |
| alertmanager_cluster_messages_sent_size_total | Total number of cluster messages received. |
| alertmanager_cluster_messages_publish_failures_total | Total number of messages that failed to be published. |
| alertmanager_cluster_pings_seconds | Histogram of latencies for ping messages. |
| alertmanager_cluster_pings_failures_total | Total number of failed pings. |
| alertmanager_peer_position | The position an Alertmanager instance believes it holds, which defines its role in the cluster. Peers should be numbered sequentially, starting from zero. |
You can confirm the number of Grafana instances in your alerting high availability setup by querying the `alertmanager_cluster_members` and `alertmanager_peer_position` metrics.
Note that these alerting high availability metrics are exposed via the `/metrics` endpoint in Grafana, and are not automatically collected or displayed. If you have a Prometheus instance connected to Grafana, add a `scrape_config` to scrape Grafana metrics and then query these metrics in Explore.
```yaml
- job_name: grafana
honor_timestamps: true
scrape_interval: 15s
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
follow_redirects: true
static_configs:
- targets:
- grafana:3000
```
For more information on monitoring alerting metrics, refer to [Alerting meta-monitoring](ref:meta-monitoring). For a demo, see [alerting high availability examples using Docker Compose](https://github.com/grafana/alerting-ha-docker-examples/).
## Prevent duplicate notifications
In high-availability mode, each Grafana instance runs its own pre-configured alertmanager to handle alert notifications.
When multiple Grafana instances are running, all alert rules are evaluated on each instance. By default, each instance sends firing alerts to its respective alertmanager. This results in notification handling being duplicated across all running Grafana instances.
Alertmanagers in HA mode communicate with each other to coordinate notification delivery. However, this setup can sometimes lead to duplicated or out-of-order notifications. By design, HA prioritizes sending duplicate notifications over the risk of missing notifications.
To avoid duplicate notifications, you can configure a shared alertmanager to manage notifications for all Grafana instances. For more information, refer to [add an external alertmanager](/docs/grafana/<GRAFANA_VERSION>/alerting/set-up/configure-alertmanager/).
| `fixed:alerting.instances:writer` | All permissions from `fixed:alerting.instances:reader` and<br>`alert.instances:create`<br>`alert.instances:write` for organization scope <br>`alert.instances.external:write` for scope `datasources:*` | Create, update and expire all silences. |
| `fixed:alerting.instances:reader` | `alert.instances:read` for organization scope <br>`alert.instances.external:read` for scope `datasources:*` | Read all alerts and silences. |
| `fixed:alerting.notifications:writer` | All permissions from `fixed:alerting.notifications:reader` and<br>`alert.notifications:write`for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Create, update, and delete contact points, templates, mute timings and notification policies for Grafana and external Alertmanager. |
| `fixed:alerting.notifications:reader` | `alert.notifications:read` for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Read all Grafana and Alertmanager contact points, templates, and notification policies. |
| `fixed:alerting.rules:writer` | All permissions from `fixed:alerting.rules:reader` and <br>`alert.rule:create`<br>`alert.rule:write`<br>`alert.rule:delete`<br>`alert.silences:create`<br>`alert.silences:write` for scope `folders:*`<br>`alert.rules.external:write` for scope `datasources:*` | Create, update, and delete all alert rules and manage rule-specific silences. |
| `fixed:alerting.rules:reader` | `alert.rule:read`, `alert.silences:read` for scope `folders:*`<br>`alert.rules.external:read` for scope `datasources:*`<br>`alert.notifications.time-intervals:read`<br>`alert.notifications.receivers:list` | Read all alert rules and read rule-specific silences. |
| `fixed:alerting:writer` | All permissions from `fixed:alerting.rules:writer`<br>`fixed:alerting.instances:writer`<br>`fixed:alerting.notifications:writer` | Create, update, and delete all alert rules, silences, contact points, templates, mute timings, and notification policies. |
| `fixed:alerting:reader` | All permissions from `fixed:alerting.rules:reader`<br>`fixed:alerting.instances:reader`<br>`fixed:alerting.notifications:reader` | Read-only permissions for all alert rules, alerts, contact points, and notification policies. |
| `fixed:alerting.provisioning.secrets:reader` | `alert.provisioning:read` and `alert.provisioning.secrets:read` | Read-only permissions for Provisioning API and let export resources with decrypted secrets. |
| `fixed:alerting.provisioning:writer` | `alert.provisioning:read` and `alert.provisioning:write` | Create, update and delete Grafana alert rules, notification policies, contact points, templates, etc via provisioning API. |
| `fixed:alerting.provisioning.status:writer` | `alert.provisioning.provenance:write` | Set provenance status to alert rules, notification policies, contact points, etc. Should be used together with regular writer roles. |
| Display name in UI / Fixed role | Permissions | Description |
| Silences Writer: `fixed:alerting.instances:writer` | All permissions from `fixed:alerting.instances:reader` and<br>`alert.instances:create`<br>`alert.instances:write` for organization scope <br>`alert.instances.external:write` for scope `datasources:*` | Add and update silences in Grafana and external providers. |
| Instances and Silences Reader: `fixed:alerting.instances:reader` | `alert.instances:read` for organization scope <br>`alert.instances.external:read` for scope `datasources:*` | Read alert instances and silences in Grafana and external providers. |
| Notifications Writer: `fixed:alerting.notifications:writer` | All permissions from `fixed:alerting.notifications:reader` and<br>`alert.notifications:write`for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Add, update, and delete notification policies and contact points in Grafana and external providers. |
| Notifications Reader: `fixed:alerting.notifications:reader` | `alert.notifications:read` for organization scope<br>`alert.notifications.external:read` for scope `datasources:*` | Read notification policies and contact points in Grafana and external providers. |
| Rules Writer: `fixed:alerting.rules:writer` | All permissions from `fixed:alerting.rules:reader` and <br>`alert.rule:create`<br>`alert.rule:write`<br>`alert.rule:delete`<br>`alert.silences:create`<br>`alert.silences:write` for scope `folders:*`<br>`alert.rules.external:write` for scope `datasources:*` | Create, update, and delete all alert rules and manage rule-specific silences. |
| Rules Reader: `fixed:alerting.rules:reader` | `alert.rule:read`, `alert.silences:read` for scope `folders:*`<br>`alert.rules.external:read` for scope `datasources:*`<br>`alert.notifications.time-intervals:read`<br>`alert.notifications.receivers:list` | Read all alert rules and rule-specific silences in Grafana and external providers. |
| Full access: `fixed:alerting:writer` | All permissions from `fixed:alerting.rules:writer`<br>`fixed:alerting.instances:writer`<br>`fixed:alerting.notifications:writer` | Add, update, and delete alert rules, silences, contact points, and notification policies in Grafana and external providers. |
| Full read-only access: `fixed:alerting:reader` | All permissions from `fixed:alerting.rules:reader`<br>`fixed:alerting.instances:reader`<br>`fixed:alerting.notifications:reader` | Read alert rules, alert instances, silences, contact points, and notification policies in Grafana and external providers. |
| Read via Provisioning API + Export Secrets: `fixed:alerting.provisioning.secrets:reader` | `alert.provisioning:read` and `alert.provisioning.secrets:read` | Read alert rules, alert instances, silences, contact points, and notification policies using the provisioning API and use export with decrypted secrets. |
| Access to alert rules provisioning API: `fixed:alerting.provisioning:writer` | `alert.provisioning:read` and `alert.provisioning:write` | Manage all alert rules, notification policies, contact points, templates, in the organization using the provisioning API. |
| Set provisioning status: `fixed:alerting.provisioning.status:writer` | `alert.provisioning.provenance:write` | Set provisioning rules for Alerting resources. Should be used together with other regular roles (Notifications Writer and/or Rules Writer.) |
@ -99,11 +99,11 @@ Grafana's [HTTP API endpoints for generating and managing API Keys]({{< relref "
#### Migration path
While upgrading to Grafana v10, you don't need to take any action; your API keys will be automatically migrated. To test or perform the migration from API keys to service accounts before upgrading to Grafana v10, follow our [migration documentation]({{< relref "../administration/api-keys/#migrate-api-keys-to-grafana-service-account" >}}").
While upgrading to Grafana v10, you don't need to take any action; your API keys will be automatically migrated. To test or perform the migration from API keys to service accounts before upgrading to Grafana v10, follow our [migration documentation](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/service-accounts/migrate-api-keys/).
#### Learn more
- [Documentation on migrating from API keys to service accounts]({{< relref "../administration/api-keys/" >}})
- [Documentation on migrating from API keys to service accounts](https://grafana.com/docs/grafana/<GRAFANA_VERSION>/administration/service-accounts/migrate-api-keys/)
- [Blog post announcement with a video demo including how to migrate](https://grafana.com/blog/2022/08/24/new-in-grafana-9.1-service-accounts-are-now-ga/)
`grafana cli admin reset-admin-password <new password>` resets the password for the admin user using the CLI. You might need to do this if you lose the admin password.
`grafana cli admin reset-admin-password <new password>` resets the password for the admin user using the CLI. You might need to do this if you lose the admin password. By default, this command uses the default ID of the admin user, which is 1. If you know the ID of the admin user, you can use the `--user-id` flag to specify the user ID. If the `--user-id` flag is not specified and the command cannot find the admin user, it returns the list of current admin users' username and ID. From that list you can determine the ID of the admin user and run the command again with the `--user-id` flag.
If there are two flags being used to set the homepath and the config file path, then running the command returns this error:
@ -227,6 +227,14 @@ If you have not lost the admin password, we recommend that you change the user p
If you need to set the password in a script, then you can use the [Grafana User API]({{< relref "./developers/http_api/user/#change-password" >}}).
#### Reset admin password
If you installed Grafana using Homebrew, you can reset the admin password using the following command:
@ -58,7 +58,6 @@ In the following JSON, id is shown as null which is the default value assigned t
"to": "now"
},
"timepicker": {
"time_options": [],
"refresh_intervals": []
},
"templating": {
@ -137,17 +136,6 @@ The grid has a negative gravity that moves panels up if there is empty space abo
"now": true,
"hidden": false,
"nowDelay": "",
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
],
"refresh_intervals": [
"5s",
"10s",
@ -175,7 +163,6 @@ Usage of the fields is explained below:
| **now** | |
| **hidden** | whether timepicker is hidden or not |
| **nowDelay** | override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values. |
| **time_options** | options available in the time picker dropdown |
| **refresh_intervals** | interval options available in the refresh picker dropdown |