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框架中。這樣登錄後,便可以拿到用戶信息。

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