本文发布于Cylon的收藏册,转载请著名原文链接~
本文使用 helm 方式部署 grafana 9 并同样将 keycloak 部署在 kubernetes 集群之上;接下来使用 keycloak 作为 grafana authentication,并实现 oauth2 的用户权限管理。
在Kubernetes 集群之上使用helm部署keycloak
在 kubernetes 集群安装 keycloak 有两种方式:
下面使用 offical 提供的方式进行部署
kubectl create -f https://raw.githubusercontent.com/keycloak/keycloak-quickstarts/latest/kubernetes/keycloak.yaml
helm 部署完成后默认密码是存储在 secret 中,上面方式安装的密码默认为 admin/admin
Keycloak configuration
创建realm
Realm 管理这一组用户(users), 凭据(credentials), 角色(roles) 和 组(groups),realm之间是相互隔离,一个用户属于并登录到某个 realm,只能管理和验证其控制的用户。
下面为 grafana 创建一个 realm,如果你的环境已经存在通用的 realm,则可以使用这个 realm,默认 keycloak 的 realm 是 master,超级管理员属于这个 realm。
创建 client
Client 是可以请求Keycloak对用户进行身份验证的实体。最常见用途是希望使用Keycloak来保护自己并提供单点登录(SSO)解决方案的应用程序和服务。客户端也可以是只希望请求身份信息或访问令牌的实体,以便它们可以安全地调用由 Keycloak 保护的网络上的其他服务。因此,我们需要为 grafana 创建一个 client
根据 grafana 官方的指南,我们创建标准需如下所示
- Client ID:
grafana-oauth
- Enabled:
ON
- Client Protocol:
openid-connect
- Access Type:
confidential
- Standard Flow Enabled:
ON
- Implicit Flow Enabled:
OFF
- Direct Access Grants Enabled:
ON
- Root URL:
<grafana_root_url>
- Valid Redirect URIs:
<grafana_root_url>/login/generic_oauth
- Web Origins:
<grafana_root_url>
- Admin URL:
<grafana_root_url>
- Base URL:
<grafana_root_url>
Realm settings => Client policies => Policies
准备grafana chart包
添加 chart repo
helm repo add grafana https://grafana.github.io/helm-charts
选择 chart 包下载
# 查看仓库中所有版本
helm search repo grafana/grafana -l
# 下载指定版本的chart包
helm pull grafana/grafana --version 6.57.4
修改 values.yaml 中 grafana.ini 部分,增加
server:
domain: "{{ if (and .Values.ingress.enabled .Values.ingress.hosts) }}{{ .Values.ingress.hosts | first }}{{ else }}''{{ end }}"
server:
# The full public facing url you use in browser, used for redirects and emails
root_url: http://10.0.0.4:30033/
serve_from_sub_path: false
auth:
signout_redirect_url: http://10.0.0.5:30043/auth/realms/sso/protocol/openid-connect/logout?post_logout_redirect_uri=http%3A%2F%210.0.0.5:30033%2Flogin
auth.generic_oauth:
enabled: true
name: grafana-oauth
allow_sign_up: true
client_id: grafana-oauth
client_secret: TF1FjfEfoeBdLa3MfpCjhC1TgChWYyPV
scopes: openid email profile offline_access roles
auth_url: http://10.0.0.5:30043/realms/sso/protocol/openid-connect/auth
token_url: http://10.0.0.5:30043/realms/sso/protocol/openid-connect/token
api_url: http://10.0.0.5:30043/realms/sso/protocol/openid-connect/userinfo
role_attribute_path: contains(roles[*], 'admin') && 'Admin' || contains(roles[*], 'editor') && 'Editor' || 'Viewer'
这里主要修改三个部分
- server:
- root_url: 是在使用 keycloak 跳转时,redirect_uri 的地址,默认是 localhost:3000
- serve_from_sub_path: 从 root_url 设置中指定的子路径提供 Grafana 服务。 出于兼容性原因,默认情况下它设置为 false。
- auth: 配置登出时请求的 API,这个按照官方给出的配置即可。
- auth.generic_oauth: keycloak 的配置,这个按照官方给出的配置即可。
troubleshooting
Invalid redirect uri
Invalid redirect uri for “Valid Redirect URIs
遇到 Invalid redirect uri 错误时,检查 Access settings 配置,并将 grafana 的 auth.generic_oauth 按照下面配置即可
server 段
[server]
# Protocol (http, https, h2, socket)
protocol = http
# The ip address to bind to, empty will bind to all interfaces
http_addr =
# The http port to use
http_port = 3000
# The public facing domain name used to access grafana from a browser
domain = 192.168.64.57
# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
enforce_domain = false
# The full public facing url
# root_url = %(protocol)s://%(domain)s:%(http_port)s/
root_url = http://192.168.64.57:30606
# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
serve_from_sub_path = false
# Log web requests
router_logging = false
# the path relative working path
static_root_path = public
# enable gzip
enable_gzip = false
# https certs & key file
cert_file =
cert_key =
# Unix socket path
socket = /tmp/grafana.sock
# CDN Url
cdn_url =
# Sets the maximum time in minutes before timing out read of an incoming request and closing idle connections.
# `0` means there is no timeout for reading the request.
read_timeout = 0
Generic OAuth 部分
#################################### Generic OAuth #######################
[auth.generic_oauth]
name = OAuth
enabled = true
allow_sign_up = true
client_id = Grafana
client_secret = ad35e16d-96d1-46ab-88d8-7cdb1512b608
scopes = openid profile email
email_attribute_name = email:primary
email_attribute_path =
login_attribute_path =
name_attribute_path =
role_attribute_path =
id_token_attribute_name =
auth_url = http://192.168.64.57:30708/auth/realms/devops/protocol/openid-connect/auth
token_url = http://192.168.64.57:30708/auth/realms/devops/protocol/openid-connect/token
api_url = http://192.168.64.57:30708/auth/realms/devops/protocol/openid-connect/userinfo
allowed_domains =
team_ids =
allowed_organizations =
tls_skip_verify_insecure = false
tls_client_cert =
tls_client_key =
tls_client_ca =
login.OAuthLogin(state mismatch)
这个错误是没有配置对应user的状态或者没有配置email导致,如果配置了 email,那么吧用户放置到对应组中就恢复了
配置权限
如果使用了 role 作为权限分配,那么按照官方的配置即可,如果使用 group,则需要使用下面的规则
role_attribute_path = contains(groups[], 'admin') && 'Admin' || contains(groups[], 'editer') && 'Editor' || contains(groups[*], 'viewer') && 'Viewer'
这个表达式是一个条件表达式,用于根据用户所属的组分配角色属性值。下面是对每个字符和子表达式的翻译解释:
- role_attribute_path : 角色属性路径,表示根据条件表达式的结果来确定角色属性值。
contains(groups[*], 'admin')
: 检查用户所属的组列表中是否包含 admin 组。- &&: 逻辑与运算符,用于组合多个条件,表示两个条件都为真时整个表达式为真。
- Admin: 如果
contains(groups[*], 'admin')
为真,将角色属性设置为 Admin。 ||
: 逻辑或运算符,用于组合多个条件,表示任意一个条件为真时整个表达式为真。contains(groups[*], 'editer')
: 检查用户所属的组列表中是否包含 editer 组。'Editor'
: 如果contains(groups[*], 'editer')
为真,将角色属性设置为 Editor。contains(groups[*], 'viewer')
: 检查用户所属的组列表中是否包含 viewer 组。'Viewer'
: 如果contains(groups[*], 'viewer')
为真,将角色属性设置为 Viewer。
Reference
[1] keycloak redirect_uri is always localhost:3000 #39
[3] Configure Keycloak OAuth2 authentication
本文发布于Cylon的收藏册,转载请著名原文链接~
链接:https://www.oomkill.com/2023/12/grafana-keycloak/
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。