配置 auth 代理身份验证
您可以配置 Grafana 使其允许 HTTP 反向代理处理身份验证。流行的 Web 服务器具有非常广泛的插件式身份验证模块列表,并且任何模块都可与 AuthProxy 功能一起使用。下面详细介绍了 auth 代理的配置选项。
[auth.proxy]
# Defaults to false, but set to true to enable this feature
enabled = true
# HTTP Header name that will contain the username or email
header_name = X-WEBAUTH-USER
# HTTP Header property, defaults to `username` but can also be `email`
header_property = username
# Set to `true` to enable auto sign up of users who do not exist in Grafana DB. Defaults to `true`.
auto_sign_up = true
# Define cache time to live in minutes
# If combined with Grafana LDAP integration it is also the sync interval
# Set to 0 to always fetch and sync the latest user data
sync_ttl = 15
# Limit where auth proxy requests come from by configuring a list of IP addresses.
# This can be used to prevent users spoofing the X-WEBAUTH-USER header.
# Example `whitelist = 192.168.1.1, 192.168.1.0/24, 2001::23, 2001::0/120`
whitelist =
# Optionally define more headers to sync other user attributes
# Example `headers = Name:X-WEBAUTH-NAME Role:X-WEBAUTH-ROLE Email:X-WEBAUTH-EMAIL Groups:X-WEBAUTH-GROUPS`
headers =
# Non-ASCII strings in header values are encoded using quoted-printable encoding
;headers_encoded = false
# Check out docs on this for more details on the below setting
enable_login_token = false
通过 curl 与 Grafana 的 AuthProxy 交互
curl -H "X-WEBAUTH-USER: admin" https://127.0.0.1:3000/api/users
[
{
"id":1,
"name":"",
"login":"admin",
"email":"admin@localhost",
"isAdmin":true
}
]
然后,我们可以向 /api/user
方法发送第二个请求,该方法将返回已登录用户的详细信息。我们将使用此请求来展示 Grafana 如何自动将我们指定的新用户添加到系统中。这里我们创建一个名为“anthony”的新用户。
curl -H "X-WEBAUTH-USER: anthony" https://127.0.0.1:3000/api/user
{
"email":"anthony",
"name":"",
"login":"anthony",
"theme":"",
"orgId":1,
"isGrafanaAdmin":false
}
使 Apache 的身份验证与 Grafana 的 AuthProxy 协同工作
我将演示如何使用 Apache 来验证用户。在本例中,我们使用 Apache 的基于文本文件的身份验证处理程序(即 htpasswd 文件)进行 BasicAuth。但是,可以使用任何可用的 Apache 身份验证功能。
Apache BasicAuth
在本例中,我们使用 Apache 作为 Grafana 前面的反向代理。Apache 在将请求转发到 Grafana 后端服务之前处理用户的身份验证。
Apache 配置
<VirtualHost *:80>
ServerAdmin webmaster@authproxy
ServerName authproxy
ErrorLog "logs/authproxy-error_log"
CustomLog "logs/authproxy-access_log" common
<Proxy *>
AuthType Basic
AuthName GrafanaAuthProxy
AuthBasicProvider file
AuthUserFile /etc/apache2/grafana_htpasswd
Require valid-user
RewriteEngine On
RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
</Proxy>
RequestHeader unset Authorization
ProxyRequests Off
ProxyPass / https://127.0.0.1:3000/
ProxyPassReverse / https://127.0.0.1:3000/
</VirtualHost>
虚拟主机配置的前四行是标准的,因此我们不会详细介绍它们的用途。
我们使用一个 <proxy> 配置块来将我们的身份验证规则应用于每个代理的请求。这些规则包括要求基本身份验证,其中用户:密码凭据存储在 /etc/apache2/grafana_htpasswd 文件中。可以使用
htpasswd
命令创建此文件。配置的下一部分是棘手的部分。我们使用 Apache 的重写引擎来创建我们的 X-WEBAUTH-USER 标头,并使用经过身份验证的用户填充它。
RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER}, NS]: 这行代码有点神奇。它的作用是,对于每个请求,使用重写引擎的预读(LA-U)功能来确定处理请求后 REMOTE_USER 变量将设置为哪个值。然后将结果分配给变量 PROXY_USER。这是必要的,因为 REMOTE_USER 变量对于 RequestHeader 函数不可用。
RequestHeader set X-WEBAUTH-USER “%{PROXY_USER}e”: 现在经过身份验证的用户名存储在 PROXY_USER 变量中,我们创建一个新的 HTTP 请求标头,该标头将发送到我们的后端 Grafana,其中包含用户名。
RequestHeader unset Authorization 从 HTTP 请求中删除 Authorization 标头,然后将其转发到 Grafana。这确保了 Grafana 不会尝试使用这些凭据来验证用户(BasicAuth 是 Grafana 中支持的身份验证处理程序)。
最后 3 行只是标准的反向代理配置,用于将所有经过身份验证的请求定向到我们的 Grafana 服务器,该服务器在端口 3000 上运行。
使用 Docker 的完整演练。
对于本例,我们使用 Docker Hub 上提供的官方 Grafana Docker 镜像。
- 创建一个包含以下内容的文件
grafana.ini
[users]
allow_sign_up = false
auto_assign_org = true
auto_assign_org_role = Editor
[auth.proxy]
enabled = true
header_name = X-WEBAUTH-USER
header_property = username
auto_sign_up = true
启动 Grafana 容器,使用我们自定义的 grafana.ini 替换 /etc/grafana/grafana.ini
。我们不公开此容器的任何端口,因为它只会由我们的 Apache 容器连接。
docker run -i -v $(pwd)/grafana.ini:/etc/grafana/grafana.ini --name grafana grafana/grafana
Apache 容器
对于本例,我们使用 Docker Hub 上提供的官方 Apache docker 镜像
- 创建一个包含以下内容的文件
httpd.conf
ServerRoot "/usr/local/apache2"
Listen 80
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<IfModule unixd_module>
User daemon
Group daemon
</IfModule>
ServerAdmin [email protected]
<Directory />
AllowOverride none
Require all denied
</Directory>
DocumentRoot "/usr/local/apache2/htdocs"
ErrorLog /proc/self/fd/2
LogLevel error
<IfModule log_config_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
CustomLog /proc/self/fd/1 common
</IfModule>
<Proxy *>
AuthType Basic
AuthName GrafanaAuthProxy
AuthBasicProvider file
AuthUserFile /tmp/htpasswd
Require valid-user
RewriteEngine On
RewriteRule .* - [E=PROXY_USER:%{LA-U:REMOTE_USER},NS]
RequestHeader set X-WEBAUTH-USER "%{PROXY_USER}e"
</Proxy>
RequestHeader unset Authorization
ProxyRequests Off
ProxyPass / http://grafana:3000/
ProxyPassReverse / http://grafana:3000/
创建一个 htpasswd 文件。我们创建一个名为 anthony 的新用户,密码为 password
htpasswd -bc htpasswd anthony password
使用我们自定义的 httpd.conf 和我们的 htpasswd 文件启动 httpd 容器。该容器将在端口 80 上侦听,并且我们创建一个链接到 grafana 容器的链接,以便该容器可以将主机名 grafana 解析为 Grafana 容器的 IP 地址。
docker run -i -p 80:80 --link grafana:grafana -v $(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf -v $(pwd)/htpasswd:/tmp/htpasswd httpd:2.4
使用 grafana。
在我们的 Grafana 和 Apache 容器运行后,您现在可以连接到 https://127.0.0.1/ 并使用我们在 htpasswd 文件中创建的用户名/密码登录。
注意
如果用户从 Grafana 中删除,则用户将无法登录并重新同步,直到sync_ttl
过期。
团队同步(仅限企业版)
仅在 Grafana Enterprise v6.3+ 中可用
使用团队同步,可以设置身份验证提供商和 Grafana 中的团队之间的同步。您可以将 Grafana 值作为 HTTP 标头的一部分发送,并让 Grafana 将其映射到您的团队结构。这允许您自动将用户放入特定的团队。
为了支持该功能,auth 代理允许可选标头来映射其他用户属性。支持团队同步的特定属性是 Groups
。
# Optionally define more headers to sync other user attributes
headers = "Groups:X-WEBAUTH-GROUPS"
您使用 X-WEBAUTH-GROUPS
标头来发送每个用户的团队信息。具体来说,是用户所属的 Grafana 组 ID 集合。
首先,我们需要设置身份验证提供商和 Grafana 之间的映射。请遵循 这些说明 将组添加到 Grafana 中的团队。
完成后。您可以通过查询 API 来验证您的映射。
# First, inspect your teams and obtain the corresponding ID of the team we want to inspect the groups for.
curl -H "X-WEBAUTH-USER: admin" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" https://127.0.0.1:3000/api/teams/search
{
"totalCount": 2,
"teams": [
{
"id": 1,
"orgId": 1,
"name": "Core",
"email": "[email protected]",
"avatarUrl": "/avatar/327a5353552d2dc3966e2e646908f540",
"memberCount": 1,
"permission": 0
},
{
"id": 2,
"orgId": 1,
"name": "Loki",
"email": "[email protected]",
"avatarUrl": "/avatar/102f937d5344d33fdb37b65d430f36ef",
"memberCount": 0,
"permission": 0
}
],
"page": 1,
"perPage": 1000
}
# Then, query the groups for that particular team. In our case, the Loki team which has an ID of "2".
curl -H "X-WEBAUTH-USER: admin" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" https://127.0.0.1:3000/api/teams/2/groups
[
{
"orgId": 1,
"teamId": 2,
"groupId": "lokiTeamOnExternalSystem"
}
]
最后,每当 Grafana 收到带有 X-WEBAUTH-GROUPS: lokiTeamOnExternalSystem
标头的请求时,正在进行身份验证的用户将被放置到指定的团队中。通过使用逗号分隔的值(例如 lokiTeamOnExternalSystem,CoreTeamOnExternalSystem
)支持放置在多个团队中。
curl -H "X-WEBAUTH-USER: leonard" -H "X-WEBAUTH-GROUPS: lokiteamOnExternalSystem" https://127.0.0.1:3000/dashboards/home
{
"meta": {
"isHome": true,
"canSave": false,
...
}
通过此设置,用户leonard
将作为 Grafana 身份验证的一部分,自动加入 Loki 团队。
注意
空X-WEBAUTH-GROUPS
或缺少组标题将导致用户从所有团队中移除。
登录令牌和会话 cookie
当enable_login_token
设置为true
时,Grafana 在成功验证身份验证代理标头后,将为用户分配登录令牌和 cookie。您只需配置您的身份验证代理为 /login 路由提供标头。通过其他路由的请求将使用 cookie 进行身份验证。
在[auth]
下使用设置login_maximum_inactive_lifetime_duration
和login_maximum_lifetime_duration
来控制会话生命周期。