Grafana是一個跨平臺的開源的度量分析和可視化工具,能夠經過將採集的數據查詢而後可視化的展現,並及時通知。在實際的運維統一平臺中,常常須要將grafana的圖表集成進來。之因此不選擇本身利用echart本身實現,主要有如下兩個緣由:安全
通常來講,咱們的grafana是開啓了登陸驗證的,尤爲是對於一個企業而言,大多集成了ldap或是公司的統一身份體系。而集成的方法大可能是經過iframe。這種解決方案,會遇到登陸驗證的問題。用戶瀏覽grafana儀表板頁面的時候須要強制它們進行雙重驗證(一次用於個人網站,一次用於grafana)。這種體驗很是很差,咱們但願能夠只登陸一次。那你們可能首先想到了sso。對於不少開源項目來講,支持sso,可能須要定製開發,不只僅是grafana。
目前支持的是兩種方案:運維
今天咱們主要利用的是代理的思路去解決。dom
咱們的整體需求是集成端不須要額外作過多的工做,讓代理完成basic auth。socket
grafana默認開啓了basic auth的認證,能夠經過修改grafana.ini 配置文件實現:工具
#################################### Basic Auth ########################## ; [auth.basic] ; ;enabled = true ;
固然認證的用戶必須是真實存在的,也就是須要提早在grafana中建立。這樣的好處是:咱們能夠給該用戶設置具體的權限,好比只具有瀏覽權限,並且能夠限定只能訪問某個文件夾下的圖表。性能
此外通常來講,相似grafana這種公司級別的產品,不會開啓外網訪問。
同時,也能夠在代理實現一些白名單的功能,好比辦公網的網段,就更加安全了。網站
整體相對來講,利用代理解決iframe 集成grafana強制登陸兩次的問題,
在安全上和操做性上,比較合適。lua
咱們知道http 的basic auth 實際上是相對簡單的一種認證方式。Authorization請求首部中,包含了用戶填寫的用戶名、密碼。插件
GET /protected_docs HTTP/1.1 Authorization: Basic Y2h5aW5ncDoxMjM0NTY=
其中 Y2h5aW5ncDoxMjM0NTY= 是 base64(用戶名:密碼)。代理
envoy 並無提供相似的filter。可是envoy支持了lua編寫filter。因此這個問題就變得很簡單了,編寫basic auth filter。此時想到openresty。那麼利用openresty也能夠實現。
直接上envoy.yaml:
static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 80 filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: auto stat_prefix: ingress_http access_log: - name: envoy.file_access_log config: path: "/dev/stdout" format: "[ACCESS_LOG][%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" \"%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%\"\n" route_config: name: local_route virtual_hosts: - name: gateway domains: - "*" routes: - match: prefix: "/" route: cluster: grafana retry_policy: retry_on: "5xx" num_retries: 2 http_filters: - name: envoy.lua config: inline_code: | function envoy_on_request(request_handle) request_handle:headers():add("Authorization", "Basic Z2FvaGo6bG92ZioxMzE0") end - name: envoy.router config: {} clusters: - name: grafana connect_timeout: 0.5s type: strict_dns lb_policy: round_robin hosts: - socket_address: address: grafana.xxx.com port_value: 80 admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 90
你們注意看envoy.lua處配置。
大體上利用 envoy_on_request方法,對請求添加 Authorization 頭。
詳細請參考envoy官方docs。
這裏簡單說下,其實envoy的lua 插件,能夠對request和response作攔截處理。以下:
-- Called on the request path. function envoy_on_request(request_handle) -- Wait for the entire request body and add a request header with the body size. request_handle:headers():add("request_body_size", request_handle:body():length()) end -- Called on the response path. function envoy_on_response(response_handle) -- Wait for the entire response body and a response header with the the body size. response_handle:headers():add("response_body_size", response_handle:body():length()) -- Remove a response header named 'foo' response_handle:headers():remove("foo") end
那麼實現其餘的擴展功能,也很容易了。
其實envoy很快將支持經過Web Assembly 來擴展,wasm性能更高,能夠利用rust,c,go等語言編寫邏輯,而後編譯成機器碼執行。屆時envoy必將大放光彩。