Grafana sits on top of the credentials for every metrics, logs and database back end it queries, so a weak Grafana instance is a shortcut into the systems it watches. A typical deployment holds data source passwords, cloud keys and bearer tokens in its database, issues service account tokens to Terraform and CI pipelines, and runs third-party plugin code inside the server. It covers self-managed Grafana (OSS and Enterprise) and notes where Grafana Cloud differs. It is written for platform, SRE and security engineers who run Grafana and want a concrete baseline for its identities, secrets, plugins and logs.
Key takeaways
- Service account tokens are the machine identities of Grafana. They replace deprecated API keys, carry the permissions of their service account, and by default never expire unless you set
token_expiration_day_limit. - The data source store is the real prize. Grafana encrypts data source secrets with envelope encryption, but anyone who holds the
secret_key(or the KMS key) and a database copy can recover them, and an Admin can repoint a data source to capture credentials. - Organisation Admin is a privileged role. It can add data sources, manage users, create service accounts and install plugins; treat it like any other privileged access and keep it small.
- Plugins run with server privileges. Leave signature checking on, keep
allow_loading_unsigned_pluginsempty and decide who may install from the catalogue. - Audit logs are an Enterprise and Cloud feature. OSS operators must rely on server logs and the reverse proxy, so plan detection around what your edition actually records.
How identity and access work in Grafana
Grafana has layered permissions, and most misconfigurations come from mixing them up.
| Layer | Who holds it | Scope | Typical risk |
|---|---|---|---|
| Grafana server administrator ("Grafana Admin") | Users only (the default admin account and anyone promoted) | Whole instance: all organisations, users, server settings and statistics | Default admin/admin credential left in place; does not exist in Grafana Cloud |
| Organisation role: Admin, Editor, Viewer, or No basic role | Users and service accounts | Every resource in one organisation | Editors see and change all dashboards; Viewers can still query every data source they can reach |
| Folder, dashboard and data source permissions | Users, teams, service accounts, basic roles | Individual resources | Folder permissions widen silently through team membership |
| RBAC fixed and custom roles (Enterprise and Cloud) | Users, teams, service accounts | Specific actions such as datasources:query or dashboards:write | Custom roles drift without review |
Human sign-in can use the built-in login form, LDAP, OAuth 2.0 / OIDC providers or SAML (Enterprise and Cloud). For a production instance:
- Use the identity provider, not local passwords: connect OIDC or SAML, map groups to roles and teams, and set
disable_login_form = trueonce break-glass access is proven. Keepallow_sign_up = false(the default). - Remove the default administrator path: the configuration reference states that
admin_userandadmin_passwordboth default toadmin. Set a strong value before first start, or usedisable_initial_admin_creationwhere the identity provider provisions the first server admin. - Bound sessions: the defaults are 7 days of inactivity (
login_maximum_inactive_lifetime_duration) and 30 days total (login_maximum_lifetime_duration). Shorten both for instances that expose production data. - Keep brute force protection on:
disable_brute_force_login_protectiondefaults to false, and the documentation describes a five minute block when the attempt budget is spent inside a five minute window. - Treat anonymous access as an exception:
[auth.anonymous] enabled = truegives every visitor theorg_roleyou set. Grafana documentation calls public dashboards the more secure way to share. If anonymous access is unavoidable, use Viewer,hide_version = true, adevice_limitand a separate organisation with minimal data sources.
See the Least Privilege Techniques Guide for role design patterns that apply here.
Admin roles and privileged access
The organisation role table in the Grafana documentation shows that only the organisation Admin can add, edit or delete data sources, add users and teams, and change organisation settings. By default the same role is needed to create service accounts and change their roles. Editors can create and change dashboards, folders and library panels and use Explore. Viewers can still query data sources directly. Three privileged positions deserve named owners and review.
- Grafana server administrator: limit to two or three named people plus one break-glass account whose password is held in a vault.
- Organisation Admin: each Admin can read the configuration of every data source and point a data source at any reachable URL. On Enterprise, use RBAC fixed roles instead of full Admin for narrower jobs.
- Plugin administration:
plugin_admin_enabledis true by default, which lets Grafana administrators install, update and uninstall plugins from the UI. Set it to false where plugins are deployed through configuration management, so a compromised admin session cannot add server-side code.
Since Grafana 10.2.0 the None basic role starts with no permissions, the cleanest starting point for automation identities on Enterprise and Cloud.
Use data source permissions to restrict sensitive back ends. Each data source has a Permissions tab with three levels: query, edit (query, change configuration and delete) and admin (edit plus change permissions). Restrict production databases and security log stores to the teams that need them. See the Privileged Access Management Guide for break-glass and review practice.
Integrations, API tokens and service accounts
Service accounts are Grafana's non-human identities. Typical uses are Terraform and other tools calling the HTTP API, scheduled reports and alert pipelines. Their tokens are generated random strings sent as Authorization: Bearer headers, and they inherit the service account's permissions.
| Credential | Recognisable format | What it can do | Lifecycle controls |
|---|---|---|---|
| Service account token (self-managed and Cloud stack) | Prefix glsa_, then 32 alphanumeric characters, an underscore and 8 hex characters (gitleaks rule grafana-service-account-token) | Grafana HTTP API within one organisation, limited to the service account's role and permissions | Optional expiry per token; token_expiration_day_limit caps it; disable or delete the service account |
| Legacy API key (deprecated) | Base64 JSON starting eyJrIjoi (gitleaks rule grafana-api-key) | HTTP API with an Admin, Editor or Viewer role | Expiry date only; migrate to service accounts and hide the API keys page |
| Grafana Cloud API token / access policy token | Prefix glc_ (gitleaks rule grafana-cloud-api-token) | Grafana Cloud account management and telemetry send or query, depending on scope | Managed in Cloud access policies, outside the Grafana instance |
| Data source credentials | Whatever the back end uses: database passwords, cloud keys, bearer tokens, client certificates | Full access the back-end account allows, independent of Grafana roles | Rotated at the back end; stored encrypted in secureJsonData |
Service account rules that hold up
- One service account per integration: service accounts only work in the organisation they were created in and cannot perform instance-wide operations such as global user management. Name them consistently, for example
sa-terraform-prod-dashboards, and record an owner. - Several tokens, one purpose: Grafana allows multiple tokens per service account so that applications sharing the same permissions can be audited separately and tokens can be rotated without an outage. Create the new token, deploy it, then delete the old one.
- Force expiry: tokens have no expiration date by default. Set
token_expiration_day_limitin the[service_accounts]section; Grafana then rejects new tokens with no expiry or with an expiry beyond the limit. Existing tokens are not affected, so inventory them separately. - Least privilege: start from Viewer or
Noneand add RBAC permissions; do not give Terraform a full Admin service account if it only manages dashboards in two folders. Check what a token can really do with the/api/access-control/user/permissionsendpoint. - Control who can mint tokens: creating a service account needs Admin or the fixed roles
fixed:roles:readerandfixed:serviceaccounts:creator, and the creator can manage what they created. Users or teams granted Edit on a service account can add and delete its tokens, so review those grants too. - Finish the API key migration: API keys are deprecated. Migrating all keys converts them to service account tokens that keep working and stops new API keys being created. The Terraform
grafana_api_keyresource was removed in provider v3.0.0, so pipelines pinned to old provider versions are a common hiding place for long-lived keys.
Data source credentials
Grafana stores data source secrets (passwords, tokens, TLS keys) in secureJsonData, encrypted before they are written to its database. Since v9.0, envelope encryption is the default: data encryption keys protect the secrets, and a key encryption key, either the secret_key setting or a key held in AWS KMS, Azure Key Vault, Google Cloud KMS or HashiCorp Vault, protects the data keys. Practical consequences:
- Change
secret_keybefore first use and keep it out of images and repositories. Better, move the key encryption key into a KMS so that a stolen database and configuration file are not enough on their own. - Rotate data keys with the documented
grafana cli admin secrets-migrationoperations after a suspected exposure, and re-encrypt secrets afterwards. - Provision secrets from the environment: provisioning files support
$ENV_VAR_NAMEand${ENV_VAR_NAME}lookups insecureJsonData. Use them, or a secrets manager that injects them, instead of committing passwords in YAML. Note the documented double-expansion caveat for values that contain$. - Give each data source a dedicated read-only back-end account: Grafana roles do not limit a leaked back-end credential.
- Limit where data sources can point:
data_source_proxy_whitelistrestricts proxied data source URLs, and on Enterprise the[security.egress]allow and deny lists, plusheader_drop_listandcookie_drop_list, stop users steering server-side requests at internal hosts. The documentation warns that a backend plugin can bypass request security. See the SSRF Prevention Guide.
For the wider credential lifecycle see the Service Account Security Guide and the API Key Management Guide.
Plugins and the software supply chain
Data source, panel and app plugins can include backend components that run on the Grafana server. At start-up Grafana verifies the signature of every plugin in its plugin directory and reports one of five statuses.
| Signature status | Meaning | Action |
|---|---|---|
| Core | Built into Grafana | Covered by Grafana upgrades |
| Signed | Signature verified (Private, Community or Commercial level) | Allowed if approved by your plugin policy |
| Unsigned | No signature; not loaded unless listed in allow_loading_unsigned_plugins | Keep the list empty in production; unsigned plugins are not supported in Grafana Cloud |
| Invalid signature | Signature does not verify | Investigate and remove |
| Modified signature | Plugin changed since signing; Grafana documentation notes this may indicate malicious intent and such plugins are never loaded, even if allow-listed | Treat as a possible compromise of the server or the build |
- Keep an approved plugin list with owners, and remove unused plugins.
- Watch the server log for the warnings "Some plugin scanning errors were found" and "Running an unsigned plugin".
See the Software Supply Chain Security Guide and the Plugin and Extension Architecture Security Guide.
Logging and detection
Grafana Enterprise and Grafana Cloud produce audit logs; OSS does not. Enterprise can export them to a file, a Loki-compatible endpoint or the console logger, and Cloud uses the Loki exporter after a support request. Only API requests, or UI actions that trigger an API request, generate an audit record. Records are JSON with user, action, resources, requestUri, ipAddress and result fields.
| What to alert on | Audit log pattern (Enterprise and Cloud) | Why it matters |
|---|---|---|
| New service account token | action: create, resources service-account and service-account-token | New long-lived machine credential; check owner and expiry |
| API key created after migration | action: create, resource api-key, requestUri: /api/auth/keys | Should not happen once keys are migrated and hidden |
| Data source changed | action: update or create, resource datasource | A changed URL can send stored credentials to an attacker-controlled host |
| Data source permissions removed | action: disable-permissions, resource datasource | Widens query access to the whole organisation |
| Role or permission changes | grant-user-role, set-user-roles, assign-builtin-role, update on user plus org | Privilege escalation inside Grafana |
| Failed logins in bulk | action: login-AUTH-MODULE with result.statusType: failure | Password spraying against local or LDAP accounts |
On OSS, forward the Grafana server log and the reverse proxy access log to your SIEM, and alert on requests to /api/serviceaccounts, /api/datasources, /api/admin/ and /api/auth/keys from unexpected sources. Two Grafana flaws are in the CISA Known Exploited Vulnerabilities catalog: CVE-2021-43798 (path traversal, added 2025-10-09) and CVE-2021-39226 (authentication bypass, added 2022-08-25). Old flaws stay exploited on instances that are never upgraded. See the SIEM Guide.
Leaked tokens: Grafana can use GitHub Secret Scanning to check whether its service account tokens have been published. The [secretscan] feature is off by default; when enabled it revokes a leaked token (or only notifies) and can call a webhook. Pair it with the gitleaks rules above. See the Push Protection Guide.
Metrics to track:
- Percentage of service account tokens with an expiry date, and the oldest token age.
- Number of legacy API keys remaining (target zero, with the API keys page hidden).
- Count of organisation Admins and server admins per instance, reviewed quarterly.
- Plugins installed but not on the approved list (target zero).
- Share of sensitive data sources with explicit permissions rather than organisation-wide query access.
Hardening baseline
Settings from the Grafana configuration reference; they live in grafana.ini and need a restart.
| Setting | Section | Default | Baseline |
|---|---|---|---|
admin_password | [security] | admin | Strong value from a secret store, or disable_initial_admin_creation = true |
secret_key | [security] | Shipped default | Unique per instance, or KMS-backed envelope encryption |
cookie_secure | [security] | false | true (requires HTTPS) |
cookie_samesite | [security] | lax | strict, or lax where OAuth/SAML login needs it |
login_cookie_name | [auth] | grafana_session | __Host-grafana_session |
strict_transport_security | [security] | false | true once HTTPS is enforced end to end |
allow_embedding | [security] | false (sends X-Frame-Options: deny) | Keep false unless a specific portal needs embedding |
content_security_policy | [security] | false | true, test the template in report-only mode first |
enforce_domain | [server] | false | true, to reduce DNS rebinding risk |
hide_version | [auth.anonymous] | false | true |
basic_auth_username / basic_auth_password | [metrics] | Unset (metrics readable without authentication) | Set, or block /metrics at the proxy |
token_expiration_day_limit | [service_accounts] | No limit | For example 90, aligned to your rotation policy |
allow_loading_unsigned_plugins | [plugins] | Empty | Empty |
plugin_admin_enabled | [plugins] | true | false where plugins are deployed by configuration management |
enabled | [auth.anonymous] | false | false, or a separate low-privilege organisation |
Network placement: Grafana listens on port 3000 by default. Put it behind a TLS-terminating proxy or set protocol = https, keep it off the open internet, and use TLS to its database and data sources. See the TLS Server Configuration Baseline Guide.
Rolling out the baseline
- Inventory: instances, versions, admins, service accounts, tokens and expiry, API keys, data sources and plugins.
- Upgrade first: bring every instance to a supported release so the settings above exist and known exploited flaws are closed.
- Identity: connect the identity provider, map groups to roles, then disable the login form after testing a break-glass account. Roll back by re-enabling the form in configuration.
- Machine identities: migrate API keys, split shared service accounts, set
token_expiration_day_limit, and rotate tokens that predate the limit. - Secrets: move the key encryption key to a KMS, re-encrypt secrets, and move provisioned passwords into environment variables or a secret store.
- HTTP settings: test cookie, HSTS and CSP settings on staging, CSP in report-only mode first.
- Detection: enable audit logs on Enterprise, forward them and the proxy logs to the SIEM, and add the alerts above.
Small versus large estates: a single OSS instance can reach most of this baseline with configuration alone, but without audit logs it depends on proxy logging and tight Admin membership. Large multi-team estates gain most from Enterprise or Cloud: RBAC, request security and audit export.
Common misconfigurations
- Default administrator left in place: the shipped
admin/admincredential, or one shared admin password. Valid default accounts are a recognised technique (MITRE ATT&CK T1078.001). - Admin service accounts with tokens that never expire: one "automation" account with the Admin role used by every pipeline, its token in several CI systems. A leak of that token is equivalent to an organisation Admin session.
- Secrets in provisioning files and images: data source passwords committed in provisioning YAML or a
secret_keybaked into a container image (ATT&CK T1552.001, Credentials In Files). - Organisation-wide query access to sensitive back ends: every Viewer able to query the security log store or a production database because no data source permissions were set.
- Internet-facing instance with anonymous access and an old version: the combination that turns flaws such as CVE-2021-43798 into a data source credential leak (ATT&CK T1190).
Framework mapping
| Control area | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | ATT&CK technique addressed |
|---|---|---|---|
| Service account and token lifecycle | AC-2, IA-5 | PR.AA-01 | T1528 Steal Application Access Token, T1550.001 Application Access Token |
| Roles, RBAC and data source permissions | AC-6 | PR.AA-05 | T1078 Valid Accounts |
| Hardening settings and plugin policy | CM-6, CM-7 | PR.PS-01 | T1195.002 Compromise Software Supply Chain |
| Encryption of stored secrets and transport | SC-28, SC-8 | PR.DS-02 | T1552.001 Credentials In Files |
| Audit logging and monitoring | AU-2, AU-12 | PR.PS-04, DE.CM-09 | All of the above |
| Patching | SI-2 | PR.PS-01 | T1190 Exploit Public-Facing Application |
Practitioner checklist
- Replace or disable the default
adminaccount and limit server admins to named people plus one vaulted break-glass account. - Connect OIDC or SAML, map groups to roles and teams, keep
allow_sign_up = falseand disable the login form once tested. - Migrate every legacy API key to service accounts and hide the API keys page.
- Set
token_expiration_day_limitand rotate any token without an expiry date. - Give each integration its own least-privilege service account with a named owner.
- Move the key encryption key to a KMS, set a unique
secret_keyand remove plaintext secrets from provisioning files. - Restrict sensitive data sources with explicit permissions and dedicated read-only back-end accounts.
- Keep plugin signature checks on, maintain an approved plugin list and set
plugin_admin_enabled = falsewhere plugins are deployed by pipeline. - Apply the cookie, HSTS, CSP,
enforce_domainand metrics authentication settings. - Forward audit logs (Enterprise and Cloud) or proxy and server logs (OSS) to the SIEM and alert on token, data source and role changes.
Standards and references
- Grafana Labs: Service accounts
- Grafana Labs: Configure security hardening
- Grafana Labs: Audit a Grafana instance
- Grafana Labs: Configure database encryption
- Grafana Labs: Plugin signatures
- Grafana Labs: Roles and permissions
- CISA: Known Exploited Vulnerabilities Catalog
- NIST: SP 800-53 Rev. 5
Related NHI Mgmt Group resources: Datadog API and Application Keys Security Guide · Service Account Security Guide · Secrets Management Guide · Non-Human Identity (NHI) Guide