diff --git a/config/map.json b/config/map.json index 9b00c6e7..cb35bded 100644 --- a/config/map.json +++ b/config/map.json @@ -1,8 +1,8 @@ { "DELETE-/_ingest/pipeline/:id": "ingest.delete_pipeline", "DELETE-/_scripts/:id": "script.delete", - "DELETE-/_search/scroll": "clear_scroll", - "DELETE-/_search/scroll/:scroll_id": "clear_scroll", + "DELETE-/_search/scroll": "scroll.delete", + "DELETE-/_search/scroll/:scroll_id":"scroll.delete", "DELETE-/_snapshot/:repository": "snapshot.delete_repository", "DELETE-/_snapshot/:repository/:snapshot": "snapshot.delete", "DELETE-/_template/:name": "indices.delete_template", @@ -102,10 +102,10 @@ "GET-/_scripts/painless/_execute": "scripts.painless_execute", "GET-/_scripts/:id": "scripts.get", "GET-/_search": "cluster.search", - "GET-/_search/scroll": "scroll", - "GET-/_search/scroll/:scroll_id": "scroll", + "GET-/_search/scroll": "scroll.get", + "GET-/_search/scroll/:scroll_id": "scroll.get", "GET-/_search/template": "search_template", - "GET-/_search_shards": "search_shards", + "GET-/_search_shards": "cluster.search_shards", "GET-/_segments": "indices.segments", "GET-/_settings": "indices.get_settings", "GET-/_settings/:name": "indices.get_settings", @@ -192,16 +192,16 @@ "POST-/_refresh": "indices.refresh", "POST-/_reindex": "reindex", "POST-/_reindex/:task_id/_rethrottle": "reindex_rethrottle", - "POST-/_render/template": "render_search_template", - "POST-/_render/template/:id": "render_search_template", + "POST-/_render/template": "render_search_template.create", + "POST-/_render/template/:id": "render_search_template.get", "POST-/_scripts/painless/_execute": "scripts_painless_execute", - "POST-/_scripts/:id": "put_script", - "POST-/_scripts/:id/:context": "put_script", - "POST-/_search": "search", - "POST-/_search/scroll": "scroll", - "POST-/_search/scroll/:scroll_id": "scroll", + "POST-/_scripts/:id": "scripts.put", + "POST-/_scripts/:id/:context": "scripts.put", + + "POST-/_search/scroll": "scroll.create", + "POST-/_search/scroll/:scroll_id": "scroll.create", "POST-/_search/template": "search_template", - "POST-/_search_shards": "search_shards", + "POST-/_snapshot/:repository": "snapshot.create_repository", "POST-/_snapshot/:repository/_verify": "snapshot.verify_repository", "POST-/_snapshot/:repository/:snapshot": "snapshot.create", @@ -217,53 +217,53 @@ "POST-/:index/_alias/:name": "indices.put_alias", "POST-/:index/_aliases/:name": "indices.put_alias", "POST-/:index/_analyze": "indices.analyze", - "POST-/:index/_bulk": "bulk", + "POST-/:index/_bulk": "indices.bulk", "POST-/:index/_cache/clear": "indices.clear_cache", "POST-/:index/_close": "indices.close", - "POST-/:index/_count": "count", + "POST-/:index/_count": "indices.count", "POST-/:index/_delete_by_query": "indices.delete_by_query", "POST-/:index/_doc": "doc.create", - "POST-/:index/_doc/:id": "doc.put", + "POST-/:index/_doc/:id": "doc.update", "POST-/:index/_doc/:id/_update": "doc.update", - "POST-/:index/_field_caps": "field_caps", + "POST-/:index/_field_caps": "indices.field_caps", "POST-/:index/_flush": "indices.flush", "POST-/:index/_flush/synced": "indices.flush_synced", "POST-/:index/_forcemerge": "indices.forcemerge", - "POST-/:index/_mget": "mget", - "POST-/:index/_msearch": "msearch", - "POST-/:index/_msearch/template": "msearch_template", - "POST-/:index/_mtermvectors": "mtermvectors", + "POST-/:index/_mget": "indices.mget", + "POST-/:index/_msearch": "indices.msearch", + "POST-/:index/_msearch/template": "indices.msearch_template", + "POST-/:index/_mtermvectors": "indices.mtermvectors", "POST-/:index/_open": "indices.open", - "POST-/:index/_rank_eval": "rank_eval", + "POST-/:index/_rank_eval": "indices.rank_eval", "POST-/:index/_refresh": "indices.refresh", - "POST-/:index/_search": "search", - "POST-/:index/_search/template": "search_template", - "POST-/:index/_search_shards": "search_shards", + "POST-/:index/_search": "indices.search", + "POST-/:index/_search/template": "indices.search_template", + "POST-/:index/_search_shards": "indices.search_shards", "POST-/:index/_shrink/:target": "indices.shrink", "POST-/:index/_split/:target": "indices.split", - "POST-/:index/_update_by_query": "update_by_query", + "POST-/:index/_update_by_query": "indices.update_by_query", "POST-/:index/_upgrade": "indices.upgrade", "POST-/:index/_validate/query": "indices.validate_query", "POST-/:index/_mapping": "indices.put_mapping", "POST-/:index/_mappings": "indices.put_mapping", - "PUT-/_bulk": "bulk", + "PUT-/_bulk": "cluster.bulk", "PUT-/_cluster/settings": "cluster.put_settings", "PUT-/_ingest/pipeline/:id": "ingest.put_pipeline", - "PUT-/_scripts/:id": "put_script", - "PUT-/_scripts/:id/:context": "put_script", - "PUT-/_settings": "indices.put_settings", + "PUT-/_scripts/:id": "scripts.put", + "PUT-/_scripts/:id/:context": "scripts.put", + "PUT-/_settings": "cluster.settings_put", "PUT-/_snapshot/:repository": "snapshot.create_repository", "PUT-/_snapshot/:repository/:snapshot": "snapshot.create", "PUT-/_template/:name": "indices.put_template", - "PUT-/:index": "indices.create", + "PUT-/:index": "indices.put", "PUT-/:index/_alias/:name": "indices.put_alias", "PUT-/:index/_aliases/:name": "indices.put_alias", - "PUT-/:index/_bulk": "bulk", - "PUT-/:index/_doc": "index", - "PUT-/:index/_doc/:id": "index", + "PUT-/:index/_bulk": "indices.put_bulk", + + "PUT-/:index/_doc/:id": "doc.put", "PUT-/:index/_settings": "indices.put_settings", "PUT-/:index/_shrink/:target": "indices.shrink", diff --git a/config/permission.json b/config/permission.json index 28fb3a84..c5d94519 100644 --- a/config/permission.json +++ b/config/permission.json @@ -43,13 +43,14 @@ "cluster.msearch_template", "cluster.mtermvectors", "cluster.rank_eval", - "cluster.search" + "cluster.search", + "cluster.search_shards" ], "doc": [ "doc.*", "doc.update", - "doc.put", + "doc.create", "doc.delete", "doc.get", @@ -71,6 +72,7 @@ "indices.get_alias", "indices.recovery", "indices.delete", + "indices.put", "indices.clear_cache", "indices.update_by_query", "indices.shrink", @@ -143,6 +145,8 @@ ], "render_search_template": [ + "render_search_template.*", + "render_search_template.create", "render_search_template.*" ], "scripts": [ @@ -154,7 +158,10 @@ ], "scroll": [ - "scroll.*" + "scroll.*", + "scroll.delete", + "scroll.get", + "scroll.create" ], "snapshot": [ diff --git a/internal/biz/enum/const.go b/internal/biz/enum/const.go index a0dcefea..88926055 100644 --- a/internal/biz/enum/const.go +++ b/internal/biz/enum/const.go @@ -10,13 +10,14 @@ const UserAll = "system.user:all" const RoleRead = "system.role:read" const RoleAll = "system.role:all" -var RuleRead = []string{"rule::read"} -var RuleAll = []string{"rule::read", "rule::write"} +const RuleRead = "alerting.rule:read" +const RuleAll = "alerting.rule:all" + +const InstanceRead = "gateway.instance:read" +const InstanceAll = "gateway.instance:all" -var InstanceRead = []string{"instance::read"} -var InstanceAll = []string{"instance::read", "instance::write"} var AdminPrivilege = []string{ - "system.role:read", "system.role:all", "system.user:read", "system.user:all", + UserRead, UserAll, RoleRead, RoleAll, } var BuildRoles = make(map[string]map[string]interface{}, 0) @@ -32,16 +33,4 @@ func init() { "created": time.Now(), } - //自定义角色=》 =》permissionKey - // userrole=> [cluster::all,clust] => permissionValue [cluster::read,cluster::write] - // login=> userrole=> cluster::all =>permissionList[] - // cluster search api require = (cluster::read) - //Permission = map[string][]string{ - // - // UserRead : {UserRead}, - // UserAll: {UserRead, UserWrite}, - //} - //zhangsan userrole [cluster::read,cluster::write] - // cluster/_search reqire(cluster::read) - } diff --git a/internal/biz/permission.go b/internal/biz/permission.go index d8f0cbb6..2db9398d 100644 --- a/internal/biz/permission.go +++ b/internal/biz/permission.go @@ -3,7 +3,7 @@ package biz import "infini.sh/console/internal/core" var ClusterApis = make(map[string][]string) -var IndexApis = make([]string, 0) +var IndexApis = make([]string, 50) var RoleMap = make(map[string]Role) var EsApiRoutes = core.NewRouter() @@ -22,11 +22,11 @@ type Role struct { } `json:"index,omitempty"` } type RolePermission struct { - Platform []string `json:"platform,omitempty"` - Cluster []string `json:"cluster"` - ClusterPrivilege []string `json:"cluster_privilege"` - Index []string `json:"index"` - IndexPrivilege map[string][]string `json:"index_privilege"` + Platform []string `json:"platform,omitempty"` + Cluster []string `json:"cluster"` + ClusterPrivilege []string `json:"cluster_privilege"` + + IndexPrivilege map[string][]string `json:"index_privilege"` } type ConsolePermisson struct { Platform []Platform `json:"platform"` diff --git a/internal/biz/validate.go b/internal/biz/validate.go index ccab4af0..37b3ec35 100644 --- a/internal/biz/validate.go +++ b/internal/biz/validate.go @@ -3,6 +3,7 @@ package biz import ( "errors" httprouter "infini.sh/framework/core/api/router" + "infini.sh/framework/core/util" "strings" ) @@ -39,24 +40,7 @@ func NewClusterRequest(ps httprouter.Params, privilege []string) ClusterRequest } } -//func ValidateEsPermission(req EsRequest, userRole RolePermission) (err error) { -// -// route, err := EsApiRoutes.Handle(req.Method, req.Path) -// if err != nil { -// -// return -// } -// if len(req.Index) > 0 { -// err = ValidateIndex(req, userRole, route) -// if err != nil { -// return err -// } -// } -// err = ValidateCluster(req, userRole, route) -// return -//} func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) { - userIndexMap := make(map[string]struct{}) userClusterMap := make(map[string]struct{}) for _, v := range userRole.Cluster { @@ -68,36 +52,31 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) { return } } - for _, v := range userRole.Index { - userIndexMap[v] = struct{}{} - } - for _, v := range req.Index { - if _, ok := userIndexMap[v]; !ok { - err = errors.New("no index permission") - return - } - } for _, val := range req.Privilege { - prefix := val[:strings.Index(val, ".")] + position := strings.Index(val, ".") + if position == -1 { + err = errors.New("invalid privilege parmeter") + return err + } + prefix := val[:position] for _, v := range req.Index { privilege, ok := userRole.IndexPrivilege[v] if !ok { - err = errors.New("no index api permission in user role") + err = errors.New("no index permission") return err } - for _, p := range privilege { - if p == prefix+".*" { - return nil - } - if p == val { - return nil - } + if util.StringInArray(privilege, prefix+".*") { + return nil } + if util.StringInArray(privilege, val) { + return nil + } + } } - return errors.New("no index api permission in user role") + return errors.New("no index api permission") } func ValidateCluster(req ClusterRequest, userRole RolePermission) (err error) { userClusterMap := make(map[string]struct{}) @@ -110,17 +89,16 @@ func ValidateCluster(req ClusterRequest, userRole RolePermission) (err error) { return } } + // if include api.* for example: cat.* , return nil for _, privilege := range req.Privilege { prefix := privilege[:strings.Index(privilege, ".")] - for _, v := range userRole.ClusterPrivilege { - if v == prefix+".*" { - return nil - } - if v == privilege { - return nil - } + if util.StringInArray(userRole.ClusterPrivilege, prefix+".*") { + return nil + } + if util.StringInArray(userRole.ClusterPrivilege, privilege) { + return nil } } @@ -142,7 +120,7 @@ func CombineUserRoles(roleNames []string) RolePermission { newRole.Platform = append(newRole.Platform, v) } for _, v := range role.Index { - newRole.Index = append(newRole.Index, v.Name...) + for _, name := range v.Name { if _, ok := m[name]; ok { m[name] = append(m[name], v.Privilege...) diff --git a/internal/biz/validate_test.go b/internal/biz/validate_test.go index caf1e9ab..befa264f 100644 --- a/internal/biz/validate_test.go +++ b/internal/biz/validate_test.go @@ -9,65 +9,57 @@ func Test_validateIndex(t *testing.T) { type args struct { req IndexRequest userRole RolePermission - route string } tests := []struct { name string args args want string }{ - //{"no index permission", - // args{ - // req: EsRequest{ - // Method: "GET", - // Cluster: []string{"cluster1"}, - // Index: []string{"index2"}, - // Path: "/index1/_mapping", - // }, - // userRole: RolePermission{ - // Cluster: []string{ - // "cluster1", - // }, - // Index: []string{ - // "index1", - // }, - // ClusterPrivilege: []string{ - // "cat.*", - // }, - // IndexPrivilege: []string{ - // "indices.get_mapping", - // }, - // }, - // route: "indices.get_mapping", - // }, "no index permission", - //}, - //{"no index api permission", - // args{ - // req: EsRequest{ - // Method: "GET", - // Cluster: []string{"cluster1"}, - // Index: []string{"index1"}, - // Path: "/index1/_mapping", - // }, - // userRole: RolePermission{ - // Cluster: []string{ - // "cluster1", - // }, - // Index: []string{ - // - // "index1", - // }, - // ClusterPrivilege: []string{ - // "cat.*", - // }, - // IndexPrivilege: []string{ - // "indices.delete", - // }, - // }, - // route: "indices.get_mapping", - // }, - // "no index api permission", - //}, + {"no index permission", + args{ + req: IndexRequest{ + + Cluster: []string{"cluster1"}, + Index: []string{"index2"}, + Privilege: []string{"indices.mapping"}, + }, + userRole: RolePermission{ + Cluster: []string{ + "cluster1", + }, + + ClusterPrivilege: []string{ + "cat.*", + }, + IndexPrivilege: map[string][]string{ + "index1": []string{"indices.delete"}, + }, + }, + }, "no index permission", + }, + {"no index api permission", + args{ + req: IndexRequest{ + + Cluster: []string{"cluster1"}, + Index: []string{"index1"}, + Privilege: []string{"indices.mapping"}, + }, + userRole: RolePermission{ + Cluster: []string{ + "cluster1", + }, + + ClusterPrivilege: []string{ + "cat.*", + }, + IndexPrivilege: map[string][]string{ + "index1": []string{"indices.delete"}, + }, + }, + }, + "no index api permission", + }, } for _, tt := range tests { @@ -89,7 +81,7 @@ func Test_validateCluster(t *testing.T) { args args want string }{ - {"no cluster permission", + {"no cluster", args{ req: ClusterRequest{ @@ -100,16 +92,14 @@ func Test_validateCluster(t *testing.T) { Cluster: []string{ "cluster2", }, - Index: []string{ - "index1", - }, + ClusterPrivilege: []string{ "cat.*", }, }, }, "no cluster permission", }, - {"no cluster api permission", + {"no cluster api", args{ req: ClusterRequest{ @@ -120,10 +110,7 @@ func Test_validateCluster(t *testing.T) { Cluster: []string{ "cluster1", }, - Index: []string{ - "index1", - }, ClusterPrivilege: []string{ "cat.*", }, diff --git a/internal/middleware/es.go b/internal/middleware/es.go new file mode 100644 index 00000000..32e4ca94 --- /dev/null +++ b/internal/middleware/es.go @@ -0,0 +1,47 @@ +package middleware + +import ( + "infini.sh/console/internal/biz" + httprouter "infini.sh/framework/core/api/router" + "net/http" +) + +func IndexRequired(h httprouter.Handle, route ...string) httprouter.Handle { + + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) + if err != nil { + w = handleError(w, http.StatusUnauthorized, err) + return + } + newRole := biz.CombineUserRoles(claims.Roles) + + indexReq := biz.NewIndexRequest(ps, route) + + err = biz.ValidateIndex(indexReq, newRole) + if err != nil { + w = handleError(w, http.StatusForbidden, err) + return + } + h(w, r, ps) + } +} +func ClusterRequired(h httprouter.Handle, route ...string) httprouter.Handle { + + return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) + if err != nil { + w = handleError(w, http.StatusUnauthorized, err) + return + } + newRole := biz.CombineUserRoles(claims.Roles) + clusterReq := biz.NewClusterRequest(ps, route) + + err = biz.ValidateCluster(clusterReq, newRole) + if err != nil { + w = handleError(w, http.StatusForbidden, err) + return + } + h(w, r, ps) + } +} diff --git a/internal/middleware/user.go b/internal/middleware/user.go index 46fcc0fa..9b41edf8 100644 --- a/internal/middleware/user.go +++ b/internal/middleware/user.go @@ -19,63 +19,6 @@ func LoginRequired(h httprouter.Handle) httprouter.Handle { h(w, r, ps) } } -func IndexRequired(h httprouter.Handle, route ...string) httprouter.Handle { - - return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) - if err != nil { - w = handleError(w, http.StatusUnauthorized, err) - return - } - newRole := biz.CombineUserRoles(claims.Roles) - - indexReq := biz.NewIndexRequest(ps, route) - - err = biz.ValidateIndex(indexReq, newRole) - if err != nil { - w = handleError(w, http.StatusForbidden, err) - return - } - h(w, r, ps) - } -} -func ClusterRequired(h httprouter.Handle, route ...string) httprouter.Handle { - - return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) - if err != nil { - w = handleError(w, http.StatusUnauthorized, err) - return - } - newRole := biz.CombineUserRoles(claims.Roles) - clusterReq := biz.NewClusterRequest(ps, route) - - err = biz.ValidateCluster(clusterReq, newRole) - if err != nil { - w = handleError(w, http.StatusForbidden, err) - return - } - h(w, r, ps) - } -} -func EsPermissionRequired(h httprouter.Handle) httprouter.Handle { - - return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - //claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) - //if err != nil { - // w = handleError(w, http.StatusUnauthorized, err) - // return - //} - //req := biz.NewEsRequest(r, ps) - //newRole := biz.CombineUserRoles(claims.Roles) - //err = biz.ValidateEsPermission(req, newRole) - //if err != nil { - // w = handleError(w, http.StatusForbidden, err) - // return - //} - h(w, r, ps) - } -} func PermissionRequired(h httprouter.Handle, permissions ...string) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {