背景
在已有系統中嵌入grafana儀表盤作數據展示,需要對界面進行二次開發滿足風格統一,同時需要對grafana的權限部分進行修改,滿足頁面進行無縫跳轉,同時識別當前用戶。
安裝
grafana 依賴於nodejs、go、git等,其安裝過程略過。
grafana下載後,我選擇了v7.0.0 tag分支進行開發。
如果是在window上面進行環境搭建,還需要安裝GCC環境。
這裏我使用的是minGW64, 這裏要根據操作系統選擇安裝,我選擇安裝64位。
安裝過程可以參考這裏
遇到的問題
-
go get 安裝速度慢。
- 可以配置代理: go env -w GOPROXY=https://goproxy.cn
- go get 其實就是從github上下載代碼,可以不用這個命令,直接到相關目錄下git clone
-
yarn install 報錯gyp ERR! configure error
yarn install --pure-lockfile --unsafe-perm
-
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
-
使用Unknwon/bra 啓動grafana
-
在$GOPATH\src\golang.org\x(需要自己建目錄)執行:
git clone https://github.com/golang/sync.git --depth 1
(depth用於指定克隆深度,爲1即表示只克隆最近一次commit) -
go get github.com/Unknwon/bra(也可以建好目錄後,git clone)。
這裏成功後沒有任何反應,檢查到$GOPATH\src\github.com\Unknwon\bra目錄生成後,可以停掉命令。 -
go run bra.go init 初始化
-
go run bra.go run 編譯bra
-
在前後端都構建成功後,在grafana目錄下執行bra run
可以成功運行grafana, 並且文件修改自動發佈。
-
-
grafana 打包
-
window下執行go run build.go build package 生成.exe可執行文件。
-
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中支持多種第三方登錄驗證。
- Github
- GitLab
- Grafana.com
- Azure AD
- Okta
- 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實現自定義配置。
其他配置說明
- 白名單和端口設置
#################################### 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路由不到。
- 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
源碼解析
- 配置generic OAuth後,便可以跳轉到第三方系統進行身份驗證。這裏由於兩個系統用戶信息的字段設置不同,所以需要修改一下。
- 包路徑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中處理。
- 用戶信息設置
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框架中。這樣登錄後,便可以拿到用戶信息。