菜单
Grafana Cloud Enterprise

审计 Grafana 实例

审计允许你追踪 Grafana 实例的重要变更。默认情况下,审计日志记录到文件,但审计功能也支持直接将日志发送到 Loki。

注意

要启用将 Grafana Cloud 审计日志发送到你的 Grafana Cloud Logs 实例,请提交支持工单。请注意,这些审计日志的摄取适用标准摄取和保留率。

只有触发 API 请求的 API 请求或 UI 操作会生成审计日志。

注意

Grafana EnterpriseGrafana Cloud 中可用。

审计日志

审计日志是代表用户操作的 JSON 对象,例如:

  • 对仪表盘和数据源等资源的修改。
  • 用户登录失败。

格式

审计日志包含以下字段。后面带有 * 的字段始终可用,其他字段取决于记录的操作类型。

字段名类型描述
timestamp*字符串请求发生的日期和时间,采用协调世界时 (UTC) 和 RFC3339 格式。
user*对象有关发出请求的用户的信息。如果 isAnonymous=false,则 UserIDApiKeyID 字段之一将包含内容。
user.userId数字发出请求的 Grafana 用户的 ID。
user.orgId*数字发出请求的用户当前所在的组织。
user.orgRole字符串发出请求的用户当前的角色。
user.name字符串发出请求的 Grafana 用户的名称。
user.authTokenId数字用户认证令牌的 ID。
user.apiKeyId数字用于发出请求的 Grafana API 密钥的 ID。
user.isAnonymous*布尔值如果发出请求的是匿名用户,则为 true。否则为 false
action*字符串请求操作。例如,createupdatemanage-permissions
request*对象有关 HTTP 请求的信息。
request.params对象请求的路径参数。
request.query对象请求的查询参数。
request.body字符串请求体。当它不是有效的 JSON 时,填充为 <non-marshalable format>
result*对象有关 HTTP 响应的信息。
result.statusType字符串如果请求操作成功,则为 success。否则为 failure
result.statusCode数字请求的 HTTP 状态码。
result.failureMessage字符串HTTP 错误消息。
result.body字符串响应体。当它不是有效的 JSON 时,填充为 <non-marshalable format>
resources数组有关请求操作影响的资源的信息。对于非资源操作(如 loginlogout),此字段可以为 null。
resources[x].id*数字资源的 ID。
resources[x].type*字符串记录的资源类型:alertalert-notificationannotationapi-keyauth-tokendashboarddatasourcefolderorgpanelplaylistreportteamuserversion
requestUri*字符串请求 URI。
ipAddress*字符串发出请求的 IP 地址。
userAgent*字符串发出请求所使用的代理。
grafanaVersion*字符串创建此日志时的 Grafana 当前版本。
additionalData对象可以提供的有关请求的附加信息。

additionalData 字段可以包含以下信息:

字段名操作描述
loginUsernamelogin在 Grafana 认证表单中使用的登录名。
extUserInfologin用于登录的外部系统提供的用户信息。
authTokenCountlogin登录用户的活动认证令牌数量。
terminationReasonlogout用户退出的原因,例如手动退出或令牌过期。
billing_rolebilling-information与发送的计费信息关联的计费角色。

记录的操作

审计日志包含以下类别操作的记录。每个操作通过 JSON 记录中的 actionresources[...].type 字段区分。

例如,创建 API 密钥会生成如下审计日志:

json
{
  "action": "create",
  "resources": [
    {
      "id": 1,
      "type": "api-key"
    }
  ],
  "timestamp": "2021-11-12T22:12:36.144795692Z",
  "user": {
    "userId": 1,
    "orgId": 1,
    "orgRole": "Admin",
    "username": "admin",
    "isAnonymous": false,
    "authTokenId": 1
  },
  "request": {
    "body": "{\"name\":\"example\",\"role\":\"Viewer\",\"secondsToLive\":null}"
  },
  "result": {
    "statusType": "success",
    "statusCode": 200,
    "responseBody": "{\"id\":1,\"name\":\"example\"}"
  },
  "resources": [
    {
      "id": 1,
      "type": "api-key"
    }
  ],
  "requestUri": "/api/auth/keys",
  "ipAddress": "127.0.0.1:54652",
  "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:94.0) Gecko/20100101 Firefox/94.0",
  "grafanaVersion": "8.3.0-pre"
}

有些操作只能通过其 requestUri 字段来区分。对于这些操作,提供了 requestUri 字段的相关模式。

请注意,几乎所有这些记录的操作都对应于 API 请求或触发 API 请求的 UI 操作。因此,操作 {"action": "email", "resources": [{"type": "report"}]} 对应于用户请求通过电子邮件发送报告预览的操作,而不是预定的操作。

会话

操作区分字段
登录 *{"action": "login-AUTH-MODULE"} *
退出 **{"action": "logout"}
强制用户退出{"action": "logout-user"}
移除用户认证令牌{"action": "revoke-auth-token", "resources": [{"type": "auth-token"}, {"type": "user"}]}
创建 API 密钥{"action": "create", "resources": [{"type": "api-key"}]}
删除 API 密钥{"action": "delete", "resources": [{"type": "api-key"}]}

* 其中 AUTH-MODULE 是认证模块的名称:grafanasamlldap 等。
** 包括手动退出、令牌过期/撤销和SAML 单点退出

服务账号

操作区分字段
创建服务账号{"action": "create", "resources": [{"type": "service-account"}]}
更新服务账号{"action": "update", "resources": [{"type": "service-account"}]}
删除服务账号{"action": "delete", "resources": [{"type": "service-account"}]}
创建服务账号令牌{"action": "create", "resources": [{"type": "service-account"}, {"type": "service-account-token"}]}
删除服务账号令牌{"action": "delete", "resources": [{"type": "service-account"}, {"type": "service-account-token"}]}
隐藏 API 密钥{"action": "hide-api-keys"}
迁移 API 密钥{"action": "migrate-api-keys"}
迁移 API 密钥{"action": "migrate-api-keys"}, "resources": [{"type": "api-key"}]}

访问控制

操作区分字段
创建角色{"action": "create", "resources": [{"type": "role"}]}
更新角色{"action": "update", "resources": [{"type": "role"}]}
删除角色{"action": "delete", "resources": [{"type": "role"}]}
分配内置角色{"action": "assign-builtin-role", "resources": [{"type": "role"}, {"type": "builtin-role"}]}
移除内置角色{"action": "remove-builtin-role", "resources": [{"type": "role"}, {"type": "builtin-role"}]}
授予团队角色{"action": "grant-team-role", "resources": [{"type": "team"}]}
设置团队角色{"action": "set-team-roles", "resources": [{"type": "team"}]}
撤销团队角色{"action": "revoke-team-role", "resources": [{"type": "role"}, {"type": "team"}]}
授予用户角色{"action": "grant-user-role", "resources": [{"type": "role"}, {"type": "user"}]}
设置用户角色{"action": "set-user-roles", "resources": [{"type": "user"}]}
撤销用户角色{"action": "revoke-user-role", "resources": [{"type": "role"}, {"type": "user"}]}
设置用户在文件夹上的权限{"action": "set-user-permissions-on-folder", "resources": [{"type": "folder"}, {"type": "user"}]}
设置团队在文件夹上的权限{"action": "set-team-permissions-on-folder", "resources": [{"type": "folder"}, {"type": "team"}]}
设置基本角色在文件夹上的权限{"action": "set-basic-role-permissions-on-folder", "resources": [{"type": "folder"}, {"type": "builtin-role"}]}
设置用户在仪表盘上的权限{"action": "set-user-permissions-on-dashboards", "resources": [{"type": "dashboard"}, {"type": "user"}]}
设置团队在仪表盘上的权限{"action": "set-team-permissions-on-dashboards", "resources": [{"type": "dashboard"}, {"type": "team"}]}
设置基本角色在仪表盘上的权限{"action": "set-basic-role-permissions-on-dashboards", "resources": [{"type": "dashboard"}, {"type": "builtin-role"}]}
设置用户在团队上的权限{"action": "set-user-permissions-on-teams", "resources": [{"type": "teams"}, {"type": "user"}]}
设置用户在服务账号上的权限{"action": "set-user-permissions-on-service-accounts", "resources": [{"type": "service-account"}, {"type": "user"}]}
设置用户在数据源上的权限{"action": "set-user-permissions-on-data-sources", "resources": [{"type": "datasource"}, {"type": "user"}]}
设置团队在数据源上的权限{"action": "set-team-permissions-on-data-sources", "resources": [{"type": "datasource"}, {"type": "team"}]}
设置基本角色在数据源上的权限{"action": "set-basic-role-permissions-on-data-sources", "resources": [{"type": "datasource"}, {"type": "builtin-role"}]}

用户管理

操作区分字段
创建用户{"action": "create", "resources": [{"type": "user"}]}
更新用户{"action": "update", "resources": [{"type": "user"}]}
删除用户{"action": "delete", "resources": [{"type": "user"}]}
禁用用户{"action": "disable", "resources": [{"type": "user"}]}
启用用户{"action": "enable", "resources": [{"type": "user"}]}
更新密码{"action": "update-password", "resources": [{"type": "user"}]}
发送密码重置邮件{"action": "send-reset-email"}
重置密码{"action": "reset-password"}
更新权限{"action": "update-permissions", "resources": [{"type": "user"}]}
发送注册邮件{"action": "signup-email"}
点击注册链接{"action": "signup"}
重新加载 LDAP 配置{"action": "ldap-reload"}
在 LDAP 中获取用户{"action": "ldap-search"}
与 LDAP 同步用户{"action": "ldap-sync", "resources": [{"type": "user"}]

团队和组织管理

操作区分字段
添加团队 *{"action": "create", "requestUri": "/api/teams"}
更新团队 *{"action": "update", "requestUri": "/api/teams/TEAM-ID"}*
删除团队 *{"action": "delete", "requestUri": "/api/teams/TEAM-ID"}*
为团队添加外部组 *{"action": "create", "requestUri": "/api/teams/TEAM-ID/groups"}*
为团队移除外部组 *{"action": "delete", "requestUri": "/api/teams/TEAM-ID/groups/GROUP-ID"}*
将用户添加到团队{"action": "create", "resources": [{"type": "user"}, {"type": "team"}]}
更新团队成员权限{"action": "update", "resources": [{"type": "user"}, {"type": "team"}]}
从团队中移除用户{"action": "delete", "resources": [{"type": "user"}, {"type": "team"}]}
创建组织{"action": "create", "resources": [{"type": "org"}]}
更新组织{"action": "update", "resources": [{"type": "org"}]}
删除组织{"action": "delete", "resources": [{"type": "org"}]}
将用户添加到组织{"action": "create", "resources": [{"type": "org"}, {"type": "user"}]}
更改用户在组织中的角色{"action": "update", "resources": [{"type": "user"}, {"type": "org"}]}
从组织中移除用户{"action": "delete", "resources": [{"type": "user"}, {"type": "org"}]}
邀请外部用户加入组织{"action": "org-invite", "resources": [{"type": "org"}, {"type": "user"}]}
撤销邀请{"action": "revoke-org-invite", "resources": [{"type": "org"}]}

* 其中 TEAM-ID 是受影响团队的 ID,GROUP-ID(如果存在)是外部组的 ID。

文件夹和仪表盘管理

操作区分字段
创建文件夹{"action": "create", "resources": [{"type": "folder"}]}
更新文件夹{"action": "update", "resources": [{"type": "folder"}]}
更新文件夹权限{"action": "manage-permissions", "resources": [{"type": "folder"}]}
删除文件夹{"action": "delete", "resources": [{"type": "folder"}]}
创建/更新仪表盘{"action": "create-update", "resources": [{"type": "dashboard"}]}
导入仪表盘{"action": "create", "resources": [{"type": "dashboard"}]}
更新仪表盘权限{"action": "manage-permissions", "resources": [{"type": "dashboard"}]}
恢复旧的仪表盘版本{"action": "restore", "resources": [{"type": "dashboard"}]}
删除仪表盘{"action": "delete", "resources": [{"type": "dashboard"}]}

库元素管理

操作区分字段
创建库元素{"action": "create", "resources": [{"type": "library-element"}]}
更新库元素{"action": "update", "resources": [{"type": "library-element"}]}
删除库元素{"action": "delete", "resources": [{"type": "library-element"}]}

数据源管理

操作区分字段
创建数据源{"action": "create", "resources": [{"type": "datasource"}]}
更新数据源{"action": "update", "resources": [{"type": "datasource"}]}
删除数据源{"action": "delete", "resources": [{"type": "datasource"}]}
启用数据源权限{"action": "enable-permissions", "resources": [{"type": "datasource"}]}
禁用数据源权限{"action": "disable-permissions", "resources": [{"type": "datasource"}]}
授予角色、团队或用户数据源权限 *{"action": "create", "resources": [{"type": "datasource"}, {"type": "dspermission"}]}*
移除数据源权限 *{"action": "delete", "resources": [{"type": "datasource"}, {"type": "dspermission"}]}
为数据源启用缓存{"action": "enable-cache", "resources": [{"type": "datasource"}]}
为数据源禁用缓存{"action": "disable-cache", "resources": [{"type": "datasource"}]}
更新数据源缓存配置{"action": "update", "resources": [{"type": "datasource"}]}

* resources 还可能包含第三项,其 "type" 设置为 "user""team"

数据源查询

操作区分字段
查询数据源{"action": "query", "resources": [{"type": "datasource"}]}

报告

操作区分字段
创建报告{"action": "create", "resources": [{"type": "report"}, {"type": "dashboard"}]}
更新报告{"action": "update", "resources": [{"type": "report"}, {"type": "dashboard"}]}
删除报告{"action": "delete", "resources": [{"type": "report"}]}
删除报告{"action": "email", "resources": [{"type": "report"}]}
更新报告设置{"action": "change-settings"}

注释、播放列表和快照管理

操作区分字段
创建注释{"action": "create", "resources": [{"type": "annotation"}]}
创建 Graphite 注释{"action": "create-graphite", "resources": [{"type": "annotation"}]}
更新注释{"action": "update", "resources": [{"type": "annotation"}]}
修补注释{"action": "patch", "resources": [{"type": "annotation"}]}
删除注释{"action": "delete", "resources": [{"type": "annotation"}]}
删除面板中的所有注释{"action": "mass-delete", "resources": [{"type": "dashboard"}, {"type": "panel"}]}
创建播放列表{"action": "create", "resources": [{"type": "playlist"}]}
更新播放列表{"action": "update", "resources": [{"type": "playlist"}]}
删除播放列表{"action": "delete", "resources": [{"type": "playlist"}]}
创建快照{"action": "create", "resources": [{"type": "dashboard"}, {"type": "snapshot"}]}
删除快照{"action": "delete", "resources": [{"type": "snapshot"}]}
按删除密钥删除快照{"action": "delete", "resources": [{"type": "snapshot"}]}

配置管理 (Provisioning)

操作区分字段
重新加载已配置的仪表盘{"action": "provisioning-dashboards"}
重新加载已配置的数据源{"action": "provisioning-datasources"}
重新加载已配置的插件{"action": "provisioning-plugins"}
重新加载已配置的警报{"action": "provisioning-alerts"}
重新加载已配置的访问控制{"action": "provisioning-accesscontrol"}

插件管理

操作区分字段
安装插件{"action": "install"}
卸载插件{"action": "uninstall"}

其他

操作区分字段
设置许可令牌{"action": "create", "requestUri": "/api/licensing/token"}
保存账单信息{"action": "billing-information"}

云迁移管理

注意

Cloud Migration Assistant 目前处于 公开预览版。Grafana Labs 提供有限支持,且在正式发布前可能会发生重大更改。

要使用此功能,请在 Grafana 配置文件中或在 Grafana Cloud 的管理 > 通用 > 功能开关中启用 onPremToCloudMigrations 功能开关。

操作区分字段
连接到云实例{"action": "connect-instance"}
断开与云实例的连接{"action": "disconnect-instance"}
构建快照{"action": "build", "resources": [{"type": "snapshot"}]}
上传快照{"action": "upload", "resources": [{"type": "snapshot"}]}

通用操作

除了上面列出的操作外,针对 API 的任何 HTTP 请求 (POST, PATCH, PUTDELETE) 都将记录为以下通用操作之一。

此外,您还可以记录 GET 请求。请参见下方如何配置。

操作区分字段
POST 请求{"action": "post-action"}
PATCH 请求{"action": "partial-update"}
PUT 请求{"action": "update"}
DELETE 请求{"action": "delete"}
GET 请求{"action": "retrieve"}

配置

注意

审计功能默认禁用。

审计日志可以保存到文件、发送到 Loki 实例或发送到 Grafana 默认日志记录器。默认情况下,只有文件导出器启用。您可以在配置文件中选择使用哪个导出器。

选项包括 file, loki, 和 logger。使用空格分隔多个模式,例如 file loki

默认情况下,当用户创建或更新仪表盘时,其内容不会出现在日志中,因为这会显著增加日志大小。如果这些信息对您很重要,并且您可以处理生成的数据量,则可以在配置中启用此选项。

ini
[auditing]
# Enable the auditing feature
enabled = false
# List of enabled loggers
loggers = file
# Keep dashboard content in the logs (request or response fields); this can significantly increase the size of your logs.
log_dashboard_content = false
# Keep requests and responses body; this can significantly increase the size of your logs.
verbose = false
# Write an audit log for every status code.
# By default it only logs the following ones: 2XX, 3XX, 401, 403 and 500.
log_all_status_codes = false
# Maximum response body (in bytes) to be audited; 500KiB by default.
# May help reducing the memory footprint caused by auditing.
max_response_size_bytes = 512000

每个导出器都有自己的配置字段。

文件导出器

审计日志保存到文件。您可以配置保存这些文件的文件夹。当文件大小超过限制以及新的一天开始时,日志会进行轮换。

ini
[auditing.logs.file]
# Path to logs folder
path = data/log
# Maximum log files to keep
max_files = 5
# Max size in megabytes per log file
max_file_size_mb = 256

Loki 导出器

审计日志通过 HTTP 或 gRPC 发送到 Loki 服务。

注意

Loki 导出器的 HTTP 选项仅在 Grafana Enterprise 7.4 及更高版本中可用。

ini
[auditing.logs.loki]
# Set the communication protocol to use with Loki (can be grpc or http)
type = grpc
# Set the address for writing logs to Loki
url = localhost:9095
# Defaults to true. If true, it establishes a secure connection to Loki
tls = true
# Set the tenant ID for Loki communication, which is disabled by default.
# The tenant ID is required to interact with Loki running in multi-tenant mode.
tenant_id =

如果您有多个 Grafana 实例向同一个 Loki 服务发送日志,或者如果您使用 Loki 用于非审计日志,审计日志将带有附加标签以帮助识别它们

  • host - 运行 Grafana 实例的操作系统主机名。
  • grafana_instance - 应用程序 URL。
  • kind - auditing

如果在 Loki 实例中需要基本身份验证才能摄取日志,您可以在 URL 字段中指定凭据。例如

ini
# Set the communication protocol to use with Loki (can be grpc or http)
type = http
# Set the address for writing logs to Loki
url = user:password@localhost:3000

控制台导出器

审计日志发送到 Grafana 默认日志记录器。审计日志使用 auditing.console 记录器,并以 debug 级别记录,请参阅文档的日志配置部分了解如何启用调试日志记录。不建议在生产环境中使用此方式访问审计日志。