fix: (rbac) validate es permission

This commit is contained in:
xushuhui 2022-04-26 18:45:15 +08:00
parent 4602562297
commit 236d340b3b
10 changed files with 349 additions and 265 deletions

View File

@ -1,6 +1,6 @@
{ {
"DELETE-/_ingest/pipeline/:id": "ingest.delete_pipeline", "DELETE-/_ingest/pipeline/:id": "ingest.delete_pipeline",
"DELETE-/_scripts/:id": "DELETE-_script", "DELETE-/_scripts/:id": "script.delete",
"DELETE-/_search/scroll": "clear_scroll", "DELETE-/_search/scroll": "clear_scroll",
"DELETE-/_search/scroll/:scroll_id": "clear_scroll", "DELETE-/_search/scroll/:scroll_id": "clear_scroll",
"DELETE-/_snapshot/:repository": "snapshot.delete_repository", "DELETE-/_snapshot/:repository": "snapshot.delete_repository",
@ -11,7 +11,7 @@
"DELETE-/:index/_aliases/:name": "indices.delete_alias", "DELETE-/:index/_aliases/:name": "indices.delete_alias",
"DELETE-/:index/_doc/:id": "doc.delete", "DELETE-/:index/_doc/:id": "doc.delete",
"GET-/": "info", "GET-/": "cluster.info",
"GET-/_alias": "indices.get_alias", "GET-/_alias": "indices.get_alias",
"GET-/_alias/:name": "indices.get_alias", "GET-/_alias/:name": "indices.get_alias",
"GET-/_analyze": "indices.analyze", "GET-/_analyze": "indices.analyze",
@ -60,8 +60,8 @@
"GET-/_cluster/state/:metric/:index": "cluster.state", "GET-/_cluster/state/:metric/:index": "cluster.state",
"GET-/_cluster/stats": "cluster.stats", "GET-/_cluster/stats": "cluster.stats",
"GET-/_cluster/stats/nodes/:node_id": "cluster.stats", "GET-/_cluster/stats/nodes/:node_id": "cluster.stats",
"GET-/_count": "count", "GET-/_count": "cluster.count",
"GET-/_field_caps": "field_caps",
"GET-/_flush": "indices.flush", "GET-/_flush": "indices.flush",
"GET-/_flush/synced": "indices.flush_synced", "GET-/_flush/synced": "indices.flush_synced",
"GET-/_ingest/pipeline": "ingest.get_pipeline", "GET-/_ingest/pipeline": "ingest.get_pipeline",
@ -71,10 +71,10 @@
"GET-/_ingest/processor/grok": "ingest.processor_grok", "GET-/_ingest/processor/grok": "ingest.processor_grok",
"GET-/_mapping": "indices.get_mapping", "GET-/_mapping": "indices.get_mapping",
"GET-/_mget": "mget", "GET-/_mget": "cluster.mget",
"GET-/_msearch": "msearch", "GET-/_msearch": "cluster.msearch",
"GET-/_msearch/template": "msearch_template", "GET-/_msearch/template": "cluster.msearch_template",
"GET-/_mtermvectors": "mtermvectors", "GET-/_mtermvectors": "cluster.mtermvectors",
"GET-/_nodes": "nodes.info", "GET-/_nodes": "nodes.info",
"GET-/_nodes/hot_threads": "nodes.hot_threads", "GET-/_nodes/hot_threads": "nodes.hot_threads",
"GET-/_nodes/hotthreads": "nodes.hot_threads", "GET-/_nodes/hotthreads": "nodes.hot_threads",
@ -93,15 +93,15 @@
"GET-/_nodes/:node_id/usage": "nodes.usage", "GET-/_nodes/:node_id/usage": "nodes.usage",
"GET-/_nodes/:node_id/usage/:metric": "nodes.usage", "GET-/_nodes/:node_id/usage/:metric": "nodes.usage",
"GET-/_nodes/:node_id/:metric": "nodes.info", "GET-/_nodes/:node_id/:metric": "nodes.info",
"GET-/_rank_eval": "rank_eval", "GET-/_rank_eval": "cluster.rank_eval",
"GET-/_recovery": "indices.recovery", "GET-/_recovery": "indices.recovery",
"GET-/_refresh": "indices.refresh", "GET-/_refresh": "indices.refresh",
"GET-/_remote/info": "cluster.remote_info", "GET-/_remote/info": "cluster.remote_info",
"GET-/_render/template": "render_search_template", "GET-/_render/template": "render_search_template",
"GET-/_render/template/:id": "render_search_template", "GET-/_render/template/:id": "render_search_template",
"GET-/_scripts/painless/_execute": "scripts_painless_execute", "GET-/_scripts/painless/_execute": "scripts.painless_execute",
"GET-/_scripts/:id": "get_script", "GET-/_scripts/:id": "scripts.get",
"GET-/_search": "search", "GET-/_search": "cluster.search",
"GET-/_search/scroll": "scroll", "GET-/_search/scroll": "scroll",
"GET-/_search/scroll/:scroll_id": "scroll", "GET-/_search/scroll/:scroll_id": "scroll",
"GET-/_search/template": "search_template", "GET-/_search/template": "search_template",
@ -128,25 +128,25 @@
"GET-/:index/_alias": "indices.get_alias", "GET-/:index/_alias": "indices.get_alias",
"GET-/:index/_alias/:name": "indices.get_alias", "GET-/:index/_alias/:name": "indices.get_alias",
"GET-/:index/_analyze": "indices.analyze", "GET-/:index/_analyze": "indices.analyze",
"GET-/:index/_count": "count", "GET-/:index/_count": "indices.count",
"GET-/:index/_doc/:id": "doc.get", "GET-/:index/_doc/:id": "doc.get",
"GET-/:index/_field_caps": "field_caps", "GET-/:index/_field_caps": "indices.field_caps",
"GET-/:index/_flush": "indices.flush", "GET-/:index/_flush": "indices.flush",
"GET-/:index/_flush/synced": "indices.flush_synced", "GET-/:index/_flush/synced": "indices.flush_synced",
"GET-/:index/_mapping": "indices.get_mapping", "GET-/:index/_mapping": "indices.get_mapping",
"GET-/:index/_mappings": "indices.get_mapping", "GET-/:index/_mappings": "indices.get_mapping",
"GET-/:index/_mapping/field/:fields": "indices.get_field_mapping", "GET-/:index/_mapping/field/:fields": "indices.get_field_mapping",
"GET-/:index/_mget": "mget", "GET-/:index/_mget": "indices.mget",
"GET-/:index/_msearch": "msearch", "GET-/:index/_msearch": "indices.msearch",
"GET-/:index/_msearch/template": "msearch_template", "GET-/:index/_msearch/template": "indices.msearch_template",
"GET-/:index/_mtermvectors": "mtermvectors", "GET-/:index/_mtermvectors": "indices.mtermvectors",
"GET-/:index/_rank_eval": "rank_eval", "GET-/:index/_rank_eval": "indices.rank_eval",
"GET-/:index/_recovery": "indices.recovery", "GET-/:index/_recovery": "indices.recovery",
"GET-/:index/_refresh": "indices.refresh", "GET-/:index/_refresh": "indices.refresh",
"GET-/:index/_search": "search", "GET-/:index/_search": "indices.search",
"GET-/:index/_search/template": "search_template", "GET-/:index/_search/template": "indices.search_template",
"GET-/:index/_search_shards": "search_shards", "GET-/:index/_search_shards": "indices.search_shards",
"GET-/:index/_segments": "indices.segments", "GET-/:index/_segments": "indices.segments",
"GET-/:index/_settings": "indices.get_settings", "GET-/:index/_settings": "indices.get_settings",
"GET-/:index/_settings/:name": "indices.get_settings", "GET-/:index/_settings/:name": "indices.get_settings",
@ -156,35 +156,39 @@
"GET-/:index/_upgrade": "indices.get_upgrade", "GET-/:index/_upgrade": "indices.get_upgrade",
"GET-/:index/_validate/query": "indices.validate_query", "GET-/:index/_validate/query": "indices.validate_query",
"HEAD-/": "info", "HEAD-/": "cluster.info",
"HEAD-/_alias/:name": "indices.exists_alias", "HEAD-/_alias/:name": "indices.exists_alias",
"HEAD-/_template/:name": "indices.exists_template", "HEAD-/_template/:name": "indices.exists_template",
"HEAD-/:index": "indices.exists", "HEAD-/:index": "indices.exists",
"HEAD-/:index/_alias/:name": "indices.exists_alias", "HEAD-/:index/_alias/:name": "indices.exists_alias",
"HEAD-/:index/_analyze": "indices.analyze",
"HEAD-/:index/_mapping/{type}": "indices.exists_type",
"HEAD-/:index/_doc/{id}": "doc.exists",
"HEAD-/:index/_doc/{id}/_source": "doc.exists_source",
"POST-/_aliases": "indices.update_aliases", "POST-/_aliases": "indices.update_aliases",
"POST-/_analyze": "indices.analyze", "POST-/_analyze": "indices.analyze",
"POST-/_bulk": "bulk", "POST-/_bulk": "cluster.bulk",
"POST-/_cache/clear": "indices.clear_cache", "POST-/_cache/clear": "indices.clear_cache",
"POST-/_cluster/allocation/explain": "cluster.allocation_explain", "POST-/_cluster/allocation/explain": "cluster.allocation_explain",
"POST-/_cluster/reroute": "cluster.reroute", "POST-/_cluster/reroute": "cluster.reroute",
"POST-/_count": "count", "POST-/_count": "cluster.count",
"POST-/_DELETE-_by_query/:task_id/_rethrottle": "reindex_rethrottle", "POST-/_delete_by_query/:task_id/_rethrottle": "reindex_rethrottle",
"POST-/_field_caps": "field_caps", "POST-/_field_caps": "cluster.field_caps",
"POST-/_flush": "indices.flush", "POST-/_flush": "indices.flush",
"POST-/_flush/synced": "indices.flush_synced", "POST-/_flush/synced": "indices.flush_synced",
"POST-/_forcemerge": "indices.forcemerge", "POST-/_forcemerge": "indices.forcemerge",
"POST-/_ingest/pipeline/_simulate": "ingest.simulate", "POST-/_ingest/pipeline/_simulate": "ingest.simulate",
"POST-/_ingest/pipeline/:id/_simulate": "ingest.simulate", "POST-/_ingest/pipeline/:id/_simulate": "ingest.simulate",
"POST-/_mget": "mget", "POST-/_mget": "cluster.mget",
"POST-/_msearch": "msearch", "POST-/_msearch": "cluster.msearch",
"POST-/_msearch/template": "msearch_template", "POST-/_msearch/template": "cluster.msearch_template",
"POST-/_mtermvectors": "mtermvectors", "POST-/_mtermvectors": "cluster.mtermvectors",
"POST-/_nodes/reload_secure_settings": "nodes.reload_secure_settings", "POST-/_nodes/reload_secure_settings": "nodes.reload_secure_settings",
"POST-/_nodes/:node_id/reload_secure_settings": "nodes.reload_secure_settings", "POST-/_nodes/:node_id/reload_secure_settings": "nodes.reload_secure_settings",
"POST-/_rank_eval": "rank_eval", "POST-/_rank_eval": "cluster.rank_eval",
"POST-/_refresh": "indices.refresh", "POST-/_refresh": "indices.refresh",
"POST-/_reindex": "reindex", "POST-/_reindex": "reindex",
"POST-/_reindex/:task_id/_rethrottle": "reindex_rethrottle", "POST-/_reindex/:task_id/_rethrottle": "reindex_rethrottle",
@ -217,7 +221,7 @@
"POST-/:index/_cache/clear": "indices.clear_cache", "POST-/:index/_cache/clear": "indices.clear_cache",
"POST-/:index/_close": "indices.close", "POST-/:index/_close": "indices.close",
"POST-/:index/_count": "count", "POST-/:index/_count": "count",
"POST-/:index/_DELETE-_by_query": "DELETE-_by_query", "POST-/:index/_delete_by_query": "indices.delete_by_query",
"POST-/:index/_doc": "doc.create", "POST-/:index/_doc": "doc.create",
"POST-/:index/_doc/:id": "doc.put", "POST-/:index/_doc/:id": "doc.put",
"POST-/:index/_doc/:id/_update": "doc.update", "POST-/:index/_doc/:id/_update": "doc.update",

View File

@ -1,8 +1,5 @@
{ {
"bulk": [
"bulk"
],
"cat": [ "cat": [
"cat.*", "cat.*",
"cat.indices", "cat.indices",
@ -36,32 +33,38 @@
"cluster.allocation_explain", "cluster.allocation_explain",
"cluster.put_settings", "cluster.put_settings",
"cluster.reroute", "cluster.reroute",
"cluster.state" "cluster.count",
], "cluster.state",
"count": [ "cluster.info",
"*", "cluster.bulk",
"count" "cluster.mget",
"cluster.ping",
"cluster.msearch",
"cluster.msearch_template",
"cluster.mtermvectors",
"cluster.rank_eval",
"cluster.search"
], ],
"doc": [ "doc": [
"doc.*", "doc.*",
"doc.update", "doc.update",
"doc.put", "doc.put",
"doc.create", "doc.create",
"doc.delete" "doc.delete",
"doc.get",
"doc.exists",
"doc.count",
"doc.exists_source",
"doc.bulk",
"doc.explain",
"doc.mget",
"doc.msearch",
"doc.msearch_template",
"doc.mtermvectors",
"doc.search"
], ],
"exists": [
"exists"
],
"explain": [
"explain"
],
"field_caps": [
"field_caps"
],
"get": [
"get"
],
"indices": [ "indices": [
"indices.*", "indices.*",
"indices.exists_alias", "indices.exists_alias",
@ -103,11 +106,19 @@
"indices.stats", "indices.stats",
"indices.delete_by_query", "indices.delete_by_query",
"indices.rollover", "indices.rollover",
"indices.shard_stores" "indices.count",
], "indices.shard_stores",
"info": [ "indices.bulk",
"info" "indices.mget",
"indices.msearch",
"indices.msearch_template",
"indices.mtermvectors",
"indices.rank_eval",
"indices.search",
"indices.search_shards",
"indices.field_caps"
], ],
"ingest": [ "ingest": [
"ingest.*", "ingest.*",
"ingest.delete_pipeline", "ingest.delete_pipeline",
@ -116,18 +127,7 @@
"ingest.get_pipeline", "ingest.get_pipeline",
"ingest.processor_grok" "ingest.processor_grok"
], ],
"mget": [
"mget"
],
"msearch": [
"msearch"
],
"msearch_template": [
"msearch_template"
],
"mtermvectors": [
"mtermvectors"
],
"nodes": [ "nodes": [
"nodes.*", "nodes.*",
"nodes.info", "nodes.info",
@ -136,42 +136,27 @@
"nodes.usage", "nodes.usage",
"nodes.hot_threads" "nodes.hot_threads"
], ],
"ping": [
"ping"
],
"rank_eval": [
"rank_eval"
],
"reindex": [ "reindex": [
"reindex" "reindex.*",
], "reindex.rethrottle"
"reindex_rethrottle": [
"reindex_rethrottle"
], ],
"render_search_template": [ "render_search_template": [
"render_search_template" "render_search_template.*"
], ],
"scripts": [ "scripts": [
"scripts.*", "scripts.*",
"scripts.get", "scripts.get",
"scripts.put", "scripts.put",
"scripts.delete" "scripts.delete",
], "scripts.painless_execute"
"scripts_painless_execute": [
"scripts_painless_execute"
], ],
"scroll": [ "scroll": [
"scroll.delete" "scroll.*"
],
"search": [
"search"
],
"search_shards": [
"search_shards"
],
"search_template": [
"search_template"
], ],
"snapshot": [ "snapshot": [
"snapshot.*", "snapshot.*",
"snapshot.get_repository", "snapshot.get_repository",
@ -184,12 +169,9 @@
"snapshot.verify_repository", "snapshot.verify_repository",
"snapshot.get" "snapshot.get"
], ],
"source": [
"source.*",
"source.head",
"source.get"
],
"tasks": [ "tasks": [
"tasks.*",
"tasks.list", "tasks.list",
"tasks.cancel", "tasks.cancel",
"tasks.get" "tasks.get"

View File

@ -26,7 +26,7 @@ type RolePermission struct {
Cluster []string `json:"cluster"` Cluster []string `json:"cluster"`
ClusterPrivilege []string `json:"cluster_privilege"` ClusterPrivilege []string `json:"cluster_privilege"`
Index []string `json:"index"` Index []string `json:"index"`
IndexPrivilege []string `json:"index_privilege"` IndexPrivilege map[string][]string `json:"index_privilege"`
} }
type ConsolePermisson struct { type ConsolePermisson struct {
Platform []Platform `json:"platform"` Platform []Platform `json:"platform"`

View File

@ -306,10 +306,7 @@ func GetRole(id string) (role rbac.Role, err error) {
} }
return return
} }
func ListRoleByName(names []string) (roles []rbac.Role, err error) {
return
}
func SearchRole(keyword string, from, size int) (roles orm.Result, err error) { func SearchRole(keyword string, from, size int) (roles orm.Result, err error) {
query := orm.Query{} query := orm.Query{}

View File

@ -75,6 +75,7 @@ func CreateUser(localUser *User, req dto.CreateUser) (id string, err error) {
Name: v.Name, Name: v.Name,
}) })
} }
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil { if err != nil {
@ -237,3 +238,6 @@ func SearchUser(keyword string, from, size int) (users orm.Result, err error) {
return return
} }
func UpdateUserPassword(localUser *User, id string, password string) (err error) {
return
}

View File

@ -3,75 +3,61 @@ package biz
import ( import (
"errors" "errors"
httprouter "infini.sh/framework/core/api/router" httprouter "infini.sh/framework/core/api/router"
"net/http" "strings"
) )
type EsRequest struct { type EsRequest struct {
Method string `json:"method"`
Cluster []string `json:"cluster"`
Index []string `json:"index"`
Doc string `json:"doc"` Doc string `json:"doc"`
Path string `json:"path"` Privilege string `json:"privilege"`
ClusterRequest
IndexRequest
}
type ClusterRequest struct {
Cluster []string `json:"cluster"`
Privilege []string `json:"privilege"`
}
type IndexRequest struct {
Cluster []string `json:"cluster"`
Index []string `json:"index"`
Privilege []string `json:"privilege"`
} }
func NewEsRequest(r *http.Request, ps httprouter.Params) EsRequest { func NewIndexRequest(ps httprouter.Params, privilege []string) IndexRequest {
//GET elasticsearch/c6dgjtgvi076f32oibj0/index/test/_mappings
clusterId := ps.ByName("id")
index := ps.ByName("index") index := ps.ByName("index")
clusterId := ps.ByName("id")
doc := ps.ByName("docId") return IndexRequest{
//如果index存在说明调用的是index api
return EsRequest{
Cluster: []string{clusterId}, Cluster: []string{clusterId},
Index: []string{index}, Index: []string{index},
Doc: doc, Privilege: privilege,
Path: r.URL.Path, }
Method: r.Method, }
func NewClusterRequest(ps httprouter.Params, privilege []string) ClusterRequest {
clusterId := ps.ByName("id")
return ClusterRequest{
Cluster: []string{clusterId},
Privilege: privilege,
} }
} }
func ValidateEsPermission(req EsRequest, userRole RolePermission) (err error) {
route, err := EsApiRoutes.Handle(req.Method, req.Path) //func ValidateEsPermission(req EsRequest, userRole RolePermission) (err error) {
if err != nil { //
// route, err := EsApiRoutes.Handle(req.Method, req.Path)
return // if err != nil {
} //
if len(req.Index) > 0 { // return
err = validateIndex(req, userRole, route) // }
if err != nil { // if len(req.Index) > 0 {
return err // err = ValidateIndex(req, userRole, route)
} // if err != nil {
} // return err
err = validateCluster(req, userRole, route) // }
return // }
} // err = ValidateCluster(req, userRole, route)
func validateIndex(req EsRequest, userRole RolePermission, route string) (err error) { // return
//}
func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
userIndexMap := make(map[string]struct{}) userIndexMap := make(map[string]struct{})
privilegeMap := make(map[string]struct{})
for _, v := range userRole.Index {
userIndexMap[v] = struct{}{}
}
for _, v := range userRole.IndexPrivilege {
privilegeMap[v] = struct{}{}
}
for _, v := range req.Index {
if _, ok := userIndexMap[v]; !ok {
err = errors.New("no index permission")
return
}
}
if _, ok := privilegeMap[route]; !ok {
err = errors.New("no index api permission")
return
}
return
}
func validateCluster(req EsRequest, userRole RolePermission, route string) (err error) {
userClusterMap := make(map[string]struct{}) userClusterMap := make(map[string]struct{})
for _, v := range userRole.Cluster { for _, v := range userRole.Cluster {
userClusterMap[v] = struct{}{} userClusterMap[v] = struct{}{}
@ -82,19 +68,68 @@ func validateCluster(req EsRequest, userRole RolePermission, route string) (err
return return
} }
} }
for _, v := range userRole.Index {
userIndexMap[v] = struct{}{}
}
for _, v := range userRole.ClusterPrivilege { for _, v := range req.Index {
if v == route { if _, ok := userIndexMap[v]; !ok {
err = errors.New("no index permission")
return
}
}
for _, val := range req.Privilege {
prefix := val[:strings.Index(val, ".")]
for _, v := range req.Index {
privilege, ok := userRole.IndexPrivilege[v]
if !ok {
err = errors.New("no index api permission in user role")
return err
}
for _, p := range privilege {
if p == prefix+".*" {
return nil
}
if p == val {
return nil return nil
} }
} }
}
}
return errors.New("no index api permission in user role")
}
func ValidateCluster(req ClusterRequest, userRole RolePermission) (err error) {
userClusterMap := make(map[string]struct{})
for _, v := range userRole.Cluster {
userClusterMap[v] = struct{}{}
}
for _, v := range req.Cluster {
if _, ok := userClusterMap[v]; !ok {
err = errors.New("no cluster permission")
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
}
}
}
return errors.New("no cluster api permission") return errors.New("no cluster api permission")
} }
func FilterCluster() {
}
func CombineUserRoles(roleNames []string) RolePermission { func CombineUserRoles(roleNames []string) RolePermission {
newRole := RolePermission{} newRole := RolePermission{}
m := make(map[string][]string)
for _, val := range roleNames { for _, val := range roleNames {
role := RoleMap[val] role := RoleMap[val]
for _, v := range role.Cluster { for _, v := range role.Cluster {
@ -108,8 +143,17 @@ func CombineUserRoles(roleNames []string) RolePermission {
} }
for _, v := range role.Index { for _, v := range role.Index {
newRole.Index = append(newRole.Index, v.Name...) newRole.Index = append(newRole.Index, v.Name...)
newRole.IndexPrivilege = append(newRole.IndexPrivilege, v.Privilege...) for _, name := range v.Name {
if _, ok := m[name]; ok {
m[name] = append(m[name], v.Privilege...)
} else {
m[name] = v.Privilege
}
}
} }
} }
newRole.IndexPrivilege = m
return newRole return newRole
} }

View File

@ -7,7 +7,7 @@ import (
func Test_validateIndex(t *testing.T) { func Test_validateIndex(t *testing.T) {
type args struct { type args struct {
req EsRequest req IndexRequest
userRole RolePermission userRole RolePermission
route string route string
} }
@ -16,64 +16,64 @@ func Test_validateIndex(t *testing.T) {
args args args args
want string want string
}{ }{
{"no index permission", //{"no index permission",
args{ // args{
req: EsRequest{ // req: EsRequest{
Method: "GET", // Method: "GET",
Cluster: []string{"cluster1"}, // Cluster: []string{"cluster1"},
Index: []string{"index2"}, // Index: []string{"index2"},
Path: "/index1/_mapping", // Path: "/index1/_mapping",
}, // },
userRole: RolePermission{ // userRole: RolePermission{
Cluster: []string{ // Cluster: []string{
"cluster1", // "cluster1",
}, // },
Index: []string{ // Index: []string{
"index1", // "index1",
}, // },
ClusterPrivilege: []string{ // ClusterPrivilege: []string{
"cat.*", // "cat.*",
}, // },
IndexPrivilege: []string{ // IndexPrivilege: []string{
"indices.get_mapping", // "indices.get_mapping",
}, // },
}, // },
route: "indices.get_mapping", // route: "indices.get_mapping",
}, "no index permission", // }, "no index permission",
}, //},
{"no index api permission", //{"no index api permission",
args{ // args{
req: EsRequest{ // req: EsRequest{
Method: "GET", // Method: "GET",
Cluster: []string{"cluster1"}, // Cluster: []string{"cluster1"},
Index: []string{"index1"}, // Index: []string{"index1"},
Path: "/index1/_mapping", // Path: "/index1/_mapping",
}, // },
userRole: RolePermission{ // userRole: RolePermission{
Cluster: []string{ // Cluster: []string{
"cluster1", // "cluster1",
}, // },
Index: []string{ // Index: []string{
//
"index1", // "index1",
}, // },
ClusterPrivilege: []string{ // ClusterPrivilege: []string{
"cat.*", // "cat.*",
}, // },
IndexPrivilege: []string{ // IndexPrivilege: []string{
"indices.delete", // "indices.delete",
}, // },
}, // },
route: "indices.get_mapping", // route: "indices.get_mapping",
}, // },
"no index api permission", // "no index api permission",
}, //},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got := validateIndex(tt.args.req, tt.args.userRole, tt.args.route) got := ValidateIndex(tt.args.req, tt.args.userRole)
assert.EqualError(t, got, tt.want) assert.EqualError(t, got, tt.want)
}) })
@ -81,9 +81,8 @@ func Test_validateIndex(t *testing.T) {
} }
func Test_validateCluster(t *testing.T) { func Test_validateCluster(t *testing.T) {
type args struct { type args struct {
req EsRequest req ClusterRequest
userRole RolePermission userRole RolePermission
route string
} }
tests := []struct { tests := []struct {
name string name string
@ -92,11 +91,10 @@ func Test_validateCluster(t *testing.T) {
}{ }{
{"no cluster permission", {"no cluster permission",
args{ args{
req: EsRequest{ req: ClusterRequest{
Method: "GET",
Cluster: []string{"cluster1"}, Cluster: []string{"cluster1"},
Index: []string{"index2"}, Privilege: []string{"indices.get_mapping"},
Path: "/index1/_mapping",
}, },
userRole: RolePermission{ userRole: RolePermission{
Cluster: []string{ Cluster: []string{
@ -108,20 +106,15 @@ func Test_validateCluster(t *testing.T) {
ClusterPrivilege: []string{ ClusterPrivilege: []string{
"cat.*", "cat.*",
}, },
IndexPrivilege: []string{
"indices.get_mapping",
}, },
},
route: "indices.get_mapping",
}, "no cluster permission", }, "no cluster permission",
}, },
{"no cluster api permission", {"no cluster api permission",
args{ args{
req: EsRequest{ req: ClusterRequest{
Method: "GET",
Cluster: []string{"cluster1"}, Cluster: []string{"cluster1"},
Index: []string{"index1"}, Privilege: []string{"indices.get_mapping"},
Path: "/index1/_mapping",
}, },
userRole: RolePermission{ userRole: RolePermission{
Cluster: []string{ Cluster: []string{
@ -134,12 +127,8 @@ func Test_validateCluster(t *testing.T) {
ClusterPrivilege: []string{ ClusterPrivilege: []string{
"cat.*", "cat.*",
}, },
IndexPrivilege: []string{
"indices.delete",
}, },
}, },
route: "indices.get_mapping",
},
"no cluster api permission", "no cluster api permission",
}, },
} }
@ -147,7 +136,7 @@ func Test_validateCluster(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
got := validateCluster(tt.args.req, tt.args.userRole, tt.args.route) got := ValidateCluster(tt.args.req, tt.args.userRole)
assert.EqualError(t, got, tt.want) assert.EqualError(t, got, tt.want)
}) })

View File

@ -19,21 +19,60 @@ func LoginRequired(h httprouter.Handle) httprouter.Handle {
h(w, r, ps) 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 { func EsPermissionRequired(h httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
claims, err := biz.ValidateLogin(r.Header.Get("Authorization")) //claims, err := biz.ValidateLogin(r.Header.Get("Authorization"))
if err != nil { //if err != nil {
w = handleError(w, http.StatusUnauthorized, err) // w = handleError(w, http.StatusUnauthorized, err)
return // return
} //}
req := biz.NewEsRequest(r, ps) //req := biz.NewEsRequest(r, ps)
newRole := biz.CombineUserRoles(claims.Roles) //newRole := biz.CombineUserRoles(claims.Roles)
err = biz.ValidateEsPermission(req, newRole) //err = biz.ValidateEsPermission(req, newRole)
if err != nil { //if err != nil {
w = handleError(w, http.StatusForbidden, err) // w = handleError(w, http.StatusForbidden, err)
return // return
} //}
h(w, r, ps) h(w, r, ps)
} }
} }

View File

@ -2,6 +2,7 @@ package api
import ( import (
"infini.sh/console/config" "infini.sh/console/config"
m "infini.sh/console/internal/middleware"
"infini.sh/console/plugin/api/alerting" "infini.sh/console/plugin/api/alerting"
"infini.sh/console/plugin/api/index_management" "infini.sh/console/plugin/api/index_management"
"infini.sh/framework/core/api" "infini.sh/framework/core/api"
@ -23,22 +24,23 @@ func Init(cfg *config.AppConfig) {
//api.HandleAPIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction) //api.HandleAPIMethod(api.GET, "/api/dict/:id",handler.GetDictItemAction)
api.HandleAPIMethod(api.DELETE, path.Join(pathPrefix, "dict/:id"), handler.DeleteDictItemAction) api.HandleAPIMethod(api.DELETE, path.Join(pathPrefix, "dict/:id"), handler.DeleteDictItemAction)
api.HandleAPIMethod(api.PUT, path.Join(pathPrefix, "dict/:id"), handler.UpdateDictItemAction) api.HandleAPIMethod(api.PUT, path.Join(pathPrefix, "dict/:id"), handler.UpdateDictItemAction)
api.HandleAPIMethod(api.POST, path.Join(esPrefix, "doc/:index/_search"), handler.HandleSearchDocumentAction) api.HandleAPIMethod(api.POST, path.Join(esPrefix, "doc/:index/_search"), handler.HandleSearchDocumentAction)
api.HandleAPIMethod(api.POST, path.Join(esPrefix, "doc/:index"), handler.HandleAddDocumentAction) api.HandleAPIMethod(api.POST, path.Join(esPrefix, "doc/:index"), handler.HandleAddDocumentAction)
api.HandleAPIMethod(api.PUT, path.Join(esPrefix, "doc/:index/:docId"), handler.HandleUpdateDocumentAction) api.HandleAPIMethod(api.PUT, path.Join(esPrefix, "doc/:index/:docId"), handler.HandleUpdateDocumentAction)
api.HandleAPIMethod(api.DELETE, path.Join(esPrefix, "doc/:index/:docId"), handler.HandleDeleteDocumentAction) api.HandleAPIMethod(api.DELETE, path.Join(esPrefix, "doc/:index/:docId"), m.ClusterRequired(handler.HandleDeleteDocumentAction, "doc.delete"))
api.HandleAPIMethod(api.GET, path.Join(esPrefix, "doc/_validate"), handler.ValidateDocIDAction) api.HandleAPIMethod(api.GET, path.Join(esPrefix, "doc/_validate"), handler.ValidateDocIDAction)
api.HandleAPIMethod(api.POST, path.Join(pathPrefix, "rebuild/*id"), handler.HandleReindexAction) api.HandleAPIMethod(api.POST, path.Join(pathPrefix, "rebuild/*id"), handler.HandleReindexAction)
api.HandleAPIMethod(api.GET, path.Join(pathPrefix, "rebuild/_search"), handler.HandleGetRebuildListAction) api.HandleAPIMethod(api.GET, path.Join(pathPrefix, "rebuild/_search"), handler.HandleGetRebuildListAction)
api.HandleAPIMethod(api.DELETE, path.Join(pathPrefix, "rebuild/:id"), handler.HandleDeleteRebuildAction) api.HandleAPIMethod(api.DELETE, path.Join(pathPrefix, "rebuild/:id"), handler.HandleDeleteRebuildAction)
api.HandleAPIMethod(api.GET, path.Join(esPrefix, "_cat/indices"), handler.HandleGetIndicesAction) api.HandleAPIMethod(api.GET, path.Join(esPrefix, "_cat/indices"), m.ClusterRequired(handler.HandleGetIndicesAction, "cat.indices"))
api.HandleAPIMethod(api.GET, path.Join(esPrefix, "index/:index/_mappings"), handler.HandleGetMappingsAction) api.HandleAPIMethod(api.GET, path.Join(esPrefix, "index/:index/_mappings"), m.IndexRequired(handler.HandleGetMappingsAction, "indices.get_mapping"))
api.HandleAPIMethod(api.GET, path.Join(esPrefix, "index/:index/_settings"), handler.HandleGetSettingsAction) api.HandleAPIMethod(api.GET, path.Join(esPrefix, "index/:index/_settings"), m.IndexRequired(handler.HandleGetSettingsAction, "indices.get_settings"))
api.HandleAPIMethod(api.PUT, path.Join(esPrefix, "index/:index/_settings"), handler.HandleUpdateSettingsAction) api.HandleAPIMethod(api.PUT, path.Join(esPrefix, "index/:index/_settings"), m.IndexRequired(handler.HandleUpdateSettingsAction, "indices.put_mapping"))
api.HandleAPIMethod(api.DELETE, path.Join(esPrefix, "index/:index"), handler.HandleDeleteIndexAction) api.HandleAPIMethod(api.DELETE, path.Join(esPrefix, "index/:index"), m.IndexRequired(handler.HandleDeleteIndexAction, "indices.delete"))
api.HandleAPIMethod(api.POST, path.Join(esPrefix, "index/:index"), handler.HandleCreateIndexAction) api.HandleAPIMethod(api.POST, path.Join(esPrefix, "index/:index"), m.IndexRequired(handler.HandleCreateIndexAction, "indices.create"))
api.HandleAPIMethod(api.POST, path.Join(pathPrefix, "elasticsearch/command"), handler.HandleAddCommonCommandAction) api.HandleAPIMethod(api.POST, path.Join(pathPrefix, "elasticsearch/command"), handler.HandleAddCommonCommandAction)
api.HandleAPIMethod(api.PUT, path.Join(pathPrefix, "elasticsearch/command/:cid"), handler.HandleSaveCommonCommandAction) api.HandleAPIMethod(api.PUT, path.Join(pathPrefix, "elasticsearch/command/:cid"), handler.HandleSaveCommonCommandAction)

View File

@ -74,6 +74,29 @@ func loadRolePermission() {
biz.RoleMap["admin"] = biz.Role{ biz.RoleMap["admin"] = biz.Role{
Platform: enum.AdminPrivilege, Platform: enum.AdminPrivilege,
Cluster: []struct {
Id string `json:"id"`
Name string `json:"name"`
}{
{
Id: "c97rd2les10hml00pgh0",
Name: "docker-cluster",
},
},
ClusterPrivilege: []string{"cat.*"},
Index: []struct {
Name []string `json:"name"`
Privilege []string `json:"privilege"`
}{
{
Name: []string{".infini_rbac-role"},
Privilege: []string{"indices.get_mapping"},
},
{
Name: []string{".infini_rbac-user", ".infini_rbac-role"},
Privilege: []string{"cat.*"},
},
},
} }
res, err := biz.SearchRole("", 0, 100) res, err := biz.SearchRole("", 0, 100)
if err != nil { if err != nil {