grafana 源码编译二次开发整合oauth2

背景

在已有系统中嵌入grafana仪表盘作数据展示,需要对界面进行二次开发满足风格统一,同时需要对grafana的权限部分进行修改,满足页面进行无缝跳转,同时识别当前用户。


安装

grafana 依赖于nodejs、go、git等,其安装过程略过。

grafana下载后,我选择了v7.0.0 tag分支进行开发。

如果是在window上面进行环境搭建,还需要安装GCC环境。

这里我使用的是minGW64, 这里要根据操作系统选择安装,我选择安装64位。

安装过程可以参考这里

遇到的问题
  1. go get 安装速度慢。

    1. 可以配置代理: go env -w GOPROXY=https://goproxy.cn
    2. go get 其实就是从github上下载代码,可以不用这个命令,直接到相关目录下git clone
  2. yarn install 报错gyp ERR! configure error

    yarn install --pure-lockfile --unsafe-perm

  3. yarn 切换镜像源,提高下载速度。

    yarn config set registry ‘https://registry.npm.taobao.org’

    npm config set registry https://registry.npm.taobao.org

    也可以使用cnpm:

    npm install -g cnpm --registry=https://registry.npm.taobao.org

  4. 使用Unknwon/bra 启动grafana

    1. 在$GOPATH\src\golang.org\x(需要自己建目录)执行:
      git clone https://github.com/golang/sync.git --depth 1
      (depth用于指定克隆深度,为1即表示只克隆最近一次commit)

    2. go get github.com/Unknwon/bra(也可以建好目录后,git clone)。
      这里成功后没有任何反应,检查到$GOPATH\src\github.com\Unknwon\bra目录生成后,可以停掉命令。

    3. go run bra.go init 初始化

    4. go run bra.go run 编译bra

    5. 在前后端都构建成功后,在grafana目录下执行bra run
      可以成功运行grafana, 并且文件修改自动发布。

  5. grafana 打包

    1. window下执行go run build.go build package 生成.exe可执行文件。

    2. linux下执行go run build.go build package 后会生成deb、rpm、tar.gz三个版本的压缩包。

    打包为deb、rpm需要安装fpm

    yum -y install ruby rubygems ruby-devel
    gem sources -a http://gems.ruby-china.com/ //原 http://ruby.taobao.org/ 已停止维护
    gem sources --remove http://rubygems.org/
    gem install fpm

    这里比较复杂,我只成功打包了deb, tar.gz。 打包rpm过程中报错。
    因为tar.gz已经可以满足要求,这里没有过多研究。

    打包一次接近20分钟,需耐心等待。


整合oauth2

  • 匿名登录

为了实现跳转过程中不弹出grafana的登录窗口,可以使用匿名登录配置。

#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access
;enabled = true

# specify organization name that should be used for unauthenticated users
;org_name = Main Org.

# specify role for unauthenticated users
;org_role = Viewer

将";enabled = true"中的分号删除,则配置生效。

这样所有的报表页面访问都不需要登录验证。当然整合oauth2的话,这个配置就不用开启了。

  • 整合oauth2

grafana中支持多种第三方登录验证。

  1. Github
  2. GitLab
  3. Google
  4. Grafana.com
  5. Azure AD
  6. Okta
  7. Generic
#################################### Generic OAuth ##########################
[auth.generic_oauth]
enabled = true
name = OAuth
allow_sign_up = true
client_id = grafana
client_secret = xxxxxx
scopes = server
;email_attribute_name = email:primary
;email_attribute_path =
auth_url = http://xxxxxx:8083/oauth/authorize
token_url = http://xxxxxx:8083/oauth/token
api_url = http://xxxxxxx:8083/oauth/check_token
;allowed_domains =
;team_ids =
;allowed_organizations =
;role_attribute_path =
;tls_skip_verify_insecure = false
;tls_client_cert =
;tls_client_key =
;tls_client_ca =

需要根据具体情况调整参数。

注: 将defaults.ini复制并重命名为custom.ini实现自定义配置。
其他配置说明
  1. 白名单和端口设置
#################################### 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 = 8000

# The public facing domain name used to access grafana from a browser
domain = 172.20.4.250

http_port默认为3000,但是在window下端口可能冲突。

domain为局域网ip:避免其他主机访问时,localhost路由不到。

  1. iframe页面调整导致cookie丢失。
#################################### Security ####################################
[security]
# disable creation of admin user on first start of grafana
;disable_initial_admin_creation = false


# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict", "none" and "disabled"
cookie_samesite = disabled

# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
allow_embedding = true
cookie_samesite = disabled

allow_embedding = true

源码解析

  1. 配置generic OAuth后,便可以跳转到第三方系统进行身份验证。这里由于两个系统用户信息的字段设置不同,所以需要修改一下。
  2. 包路径pkg/api,其中api.go为所有的接口路由配置。
	r.Get("/logout", hs.Logout)
	r.Post("/login", quota("session"), bind(dtos.LoginCommand{}), Wrap(hs.LoginPost))
	r.Get("/login/:name", quota("session"), hs.OAuthLogin)
	r.Get("/login", hs.LoginView)
	r.Get("/invite/:code", hs.Index)

由于使用generic_oauth,登录的url为/login/generic_oauth,所以跳转到了hs.OAuthLogin, 在pkg/api/login_oauth.go中处理。

  1. 用户信息设置
	extUser := &models.ExternalUserInfo{
		AuthModule: "oauth_" + name,
		OAuthToken: token,
		AuthId:     userInfo.Id,
		Name:       userInfo.Name,
		Login:      userInfo.Login,
		Email:      userInfo.Email,
		OrgRoles:   map[int64]models.RoleType{},
		Groups:     userInfo.Groups,
	}

源码从token中获取到用户信息,但是我们的认证中心用户信息是以json格式存放在token中的。

// 从token拿到user的json对象
user := token.Extra("user")
// 将json对象转成map
userInfo, ok := user.(map[string]interface{})
// 获取对象属性
userInfo["nickName"]
	extUser := &models.ExternalUserInfo{
		AuthModule: "oauth_" + name,
		OAuthToken: token,
		AuthId:     fmt.Sprintf("%s", userInfo["id"]),
		Name:       fmt.Sprintf("%s", userInfo["nickName"]),
		Login:      fmt.Sprintf("%s", userInfo["username"]),
		Email:      fmt.Sprintf("%s", userInfo["email"]),
		OrgRoles:   map[int64]models.RoleType{},
		//Groups:     groups,
	}

将token中的用户信息重新填入grafana框架中。这样登录后,便可以拿到用户信息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章