Influxdb授權驗證流程

Influxdb授權驗證流程分析

Qurey語句權限驗證

  1. 關于Influxdb的驗證邏輯,我們可以先參考官方文檔: Authentication and authorization in InfluxDB
    1.1 在配置文件時,[http] auth-enabled = true 將開啟授權驗證
  2. 我們從appendHTTPDService(cmd/influxdb/run/server.go)入手,在處理http request時要作授權驗證,先要創(chuàng)建授權驗證對象:
    srv.Handler.QueryAuthorizer = meta.NewQueryAuthorizer(s.MetaClient)
    srv.Handler.WriteAuthorizer = meta.NewWriteAuthorizer(s.MetaClient)
  1. Query驗證 meta.QueryAuthorizer(services/meta/data.go)
// QueryAuthorizer determines whether a user is authorized to execute a given query.
type QueryAuthorizer struct {
    Client *Client // MetaClient
}
  1. 驗證流程圖:


    influxdb_authorizer.png
  2. 通過上面這張圖我們看到授權驗證所有的接口都定義在 type Authorizer interface

type Authorizer interface {
    // AuthorizeDatabase indicates whether the given Privilege is authorized on the database with the given name.
    AuthorizeDatabase(p influxql.Privilege, name string) bool

    // AuthorizeQuery returns an error if the query cannot be executed
    AuthorizeQuery(database string, query *influxql.Query) error

    // AuthorizeSeriesRead determines if a series is authorized for reading
    AuthorizeSeriesRead(database string, measurement []byte, tags models.Tags) bool

    // AuthorizeSeriesWrite determines if a series is authorized for writing
    AuthorizeSeriesWrite(database string, measurement []byte, tags models.Tags) bool
}
  1. 首先看一下 `QueryAuthorizer.AuthorizeQuery, 以注釋的方式給出說明
func (a *QueryAuthorizer) AuthorizeQuery(u User, query *influxql.Query, database string) error {
    // Special case if no users exist.
    if n := a.Client.UserCount(); n == 0 {
        // Ensure there is at least one statement.
        if len(query.Statements) > 0 {
            // First statement in the query must create a user with admin privilege.
            // 如果沒有任何的用戶,query的一個請求必須是Create Admin User
            cu, ok := query.Statements[0].(*influxql.CreateUserStatement)
            if ok && cu.Admin {
                return nil
            }
        }
        //Inlufxdb的驗證流程規(guī)定,如果開啟了授權驗證,但還沒有創(chuàng)建任何用戶,則返回用戶下面這個錯誤
        return &ErrAuthorize{
            Query:    query,
            Database: database,
            Message:  "create admin user first or disable authentication",
        }
    }

    //請求中沒有user信息,則返回用戶下面這個錯誤
    if u == nil {
        return &ErrAuthorize{
            Query:    query,
            Database: database,
            Message:  "no user provided",
        }
    }

    // 調用User.AuthorizeQuery繼續(xù)驗證
    return u.AuthorizeQuery(database, query)
}
  1. 接著看一下UserInfo.AuthorizeQuery
func (u *UserInfo) AuthorizeQuery(database string, query *influxql.Query) error {
    // Admin privilege allows the user to execute all statements.
    // Admin用戶有一切授權,不用再繼續(xù)驗證
    if u.Admin {
        return nil
    }

    // query里的每條statement的所需的所有privilege都需要逐一驗證
    for _, stmt := range query.Statements {
        privs, err := stmt.RequiredPrivileges()
        for _, p := range privs {
            if p.Admin {
                // 走到這里說明當前用戶一定不是admin用戶,但當前statement又需要admin privilege, 則返回如下錯
                return &ErrAuthorize{
                    Query:    query,
                    User:     u.Name,
                    Database: database,
                    Message:  fmt.Sprintf("statement '%s', requires admin privilege", stmt),
                }
            }

            db := p.Name
            if db == "" {
                db = database
            }
            // 調用u.AuthorizeDatabase進一步驗證
            if !u.AuthorizeDatabase(p.Privilege, db) {
                return &ErrAuthorize{
                    Query:    query,
                    User:     u.Name,
                    Database: database,
                    Message:  fmt.Sprintf("statement '%s', requires %s on %s", stmt, p.Privilege.String(), db),
                }
            }
        }
    }
    return nil
}
  1. 最后看一下UserInfo.AuthorizeDatabaseUserInfo的定義:
type UserInfo struct {
    // User's name.
    Name string

    // Hashed password.
    Hash string

    // Whether the user is an admin, i.e. allowed to do everything.
    Admin bool

    // Map of database name to granted privilege.
    // 針對不同的database的privilege都存在這個map中
    Privileges map[string]influxql.Privilege
}

 func (ui *UserInfo) AuthorizeDatabase(privilege influxql.Privilege, database string) bool {
    if ui.Admin || privilege == influxql.NoPrivileges {
        return true
    }
    p, ok := ui.Privileges[database]
    // 查Privileges這個map
    return ok && (p == privilege || p == influxql.AllPrivileges)
}

寫語句權限驗證

  1. srv.Handler.WriteAuthorizer = meta.NewWriteAuthorizer(s.MetaClient),創(chuàng)建了寫權限驗證對象
  2. 具體實現(xiàn) WriteAuthorizer(在 services/meta/write_authorizer.go中), 實現(xiàn)比較簡單, 最終也是調用UserInfo.AuthorizeDatabase來驗證
// WriteAuthorizer determines whether a user is authorized to write to a given database.
type WriteAuthorizer struct {
    Client *Client
}

 // AuthorizeWrite returns nil if the user has permission to write to the database.
func (a WriteAuthorizer) AuthorizeWrite(username, database string) error {
    u, err := a.Client.User(username)
    if err != nil || u == nil || !u.AuthorizeDatabase(influxql.WritePrivilege, database) {
        return &ErrAuthorize{
            Database: database,
            Message:  fmt.Sprintf("%s not authorized to write to %s", username, database),
        }
    }
    return nil
}

Open權限驗證

  1. 不需要授權驗證的情況,Influxdb實現(xiàn)了openAuthorizer, 它同樣實現(xiàn)了Authorizer interface
 // OpenAuthorizer is the Authorizer used when authorization is disabled.
// It allows all operations.
type openAuthorizer struct{}

 // OpenAuthorizer can be shared by all goroutines.
var OpenAuthorizer = openAuthorizer{}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,361評論 25 708
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 14,139評論 2 59
  • 一直喜歡看清宮戲(雖然對歷史和皇帝的排序有時一團漿糊),喜歡古代女人的著裝和頭飾 除了《甄嬛傳》這種高水準、邏輯縝...
    瀟湘青女閱讀 1,103評論 0 4
  • 時間永遠定格在2017年7月8日早上一瞬間,對于臨沂市來說是個難忘的一天,對于暴走人員是一個慘不忍睹的惡夢,那就是...
    我的另一半是你閱讀 289評論 0 1

友情鏈接更多精彩內容