diff --git a/internal/biz/permission.go b/internal/biz/permission.go index f9ba38a5..cfd64286 100644 --- a/internal/biz/permission.go +++ b/internal/biz/permission.go @@ -1,7 +1,6 @@ package biz import ( - "infini.sh/console/internal/core" "infini.sh/console/model/rbac" ) @@ -18,8 +17,6 @@ type Token struct { var TokenMap = make(map[string]Token) -var EsApiRoutes = core.NewRouter() - type RolePermission struct { Platform []string `json:"platform,omitempty"` diff --git a/internal/biz/validate.go b/internal/biz/validate.go index 7ecf1509..d67943f1 100644 --- a/internal/biz/validate.go +++ b/internal/biz/validate.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "infini.sh/console/internal/biz/enum" + "infini.sh/console/model/rbac" httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/util" "src/github.com/golang-jwt/jwt" @@ -44,6 +45,11 @@ func NewClusterRequest(ps httprouter.Params, privilege []string) ClusterRequest } } +func ValidateElasticsearch(req rbac.ElasticsearchPrivilege, roleNames []string) (err error) { + + return nil +} + func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) { userClusterMap := make(map[string]struct{}) @@ -60,7 +66,7 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) { for _, val := range req.Privilege { position := strings.Index(val, ".") if position == -1 { - err = errors.New("invalid privilege parmeter") + err = errors.New("invalid privilege parameter") return err } prefix := val[:position] @@ -71,42 +77,43 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) { return err } if util.StringInArray(privilege, prefix+".*") { - return nil + continue } if util.StringInArray(privilege, val) { - return nil + continue } - + return fmt.Errorf("no index api permission: %s", val) } } - return errors.New("no index api permission") + return nil } -func ValidateCluster(req ClusterRequest, userRole RolePermission) (err error) { - userClusterMap := make(map[string]struct{}) - for _, v := range userRole.Cluster { - userClusterMap[v] = struct{}{} - } +func ValidateCluster(req ClusterRequest, roleNames []string) (err error) { + userClusterMap := GetRoleClusterMap(roleNames) for _, v := range req.Cluster { - if _, ok := userClusterMap[v]; !ok { - err = errors.New("no cluster permission") + userClusterPermissions, ok := userClusterMap[v] + if !ok && userClusterMap["*"] == nil{ + err = fmt.Errorf("no cluster[%s] permission", v) return } - } - - // if include api.* for example: cat.* , return nil - for _, privilege := range req.Privilege { - prefix := privilege[:strings.Index(privilege, ".")] - - if util.StringInArray(userRole.ClusterPrivilege, prefix+".*") { - return nil + if util.StringInArray(userClusterPermissions, "*") { + continue } - if util.StringInArray(userRole.ClusterPrivilege, privilege) { - return nil + // if include api.* for example: cat.* , return nil + for _, privilege := range req.Privilege { + prefix := privilege[:strings.Index(privilege, ".")] + + if util.StringInArray(userClusterPermissions, prefix+".*") { + continue + } + if util.StringInArray(userClusterPermissions, privilege) { + continue + } + return fmt.Errorf("no cluster api permission: %s", privilege) } } + return nil - return errors.New("no cluster api permission") } func CombineUserRoles(roleNames []string) RolePermission { @@ -139,26 +146,43 @@ func CombineUserRoles(roleNames []string) RolePermission { newRole.IndexPrivilege = m return newRole } -func FilterCluster(roles []string, cluster []string) []string { - newRole := CombineUserRoles(roles) - userClusterMap := make(map[string]struct{}, 0) - for _, v := range newRole.Cluster { - userClusterMap[v] = struct{}{} - } - realCluster := make([]string, 0) - for _, v := range cluster { - if _, ok := userClusterMap[v]; ok { - realCluster = append(realCluster, v) +func GetRoleClusterMap(roles []string) map[string][]string { + userClusterMap := make(map[string][]string, 0) + for _, roleName := range roles { + role, ok := RoleMap[roleName] + if ok { + for _, ic := range role.Privilege.Elasticsearch.Cluster.Resources { + userClusterMap[ic.ID] = append(userClusterMap[ic.ID], role.Privilege.Elasticsearch.Cluster.Permissions...) + } } } + return userClusterMap +} +func GetRoleCluster(roles []string) []string { + userClusterMap := GetRoleClusterMap(roles) + realCluster := make([]string, 0, len(userClusterMap)) + for k, _ := range userClusterMap { + realCluster = append(realCluster, k) + } return realCluster } -func FilterIndex(roles []string, index []string) []string { - realIndex := make([]string, 0) - newRole := CombineUserRoles(roles) - for _, v := range index { - if _, ok := newRole.IndexPrivilege[v]; ok { - realIndex = append(realIndex, v) +func GetRoleIndex(roles, clusterIDs []string) map[string][]string { + userClusterMap := make(map[string]struct{}, len(clusterIDs)) + for _, clusterID := range clusterIDs { + userClusterMap[clusterID] = struct{}{} + } + realIndex := map[string][]string{} + for _, roleName := range roles { + role, ok := RoleMap[roleName] + if ok { + for _, ic := range role.Privilege.Elasticsearch.Cluster.Resources { + if _, ok = userClusterMap[ic.ID]; !ok { + continue + } + for _, ip := range role.Privilege.Elasticsearch.Index { + realIndex[ic.ID] = append(realIndex[ic.ID], ip.Name...) + } + } } } return realIndex diff --git a/internal/core/router.go b/internal/core/router.go deleted file mode 100644 index faeced25..00000000 --- a/internal/core/router.go +++ /dev/null @@ -1,94 +0,0 @@ -package core - -import ( - "errors" - "strings" -) - -type Router struct { - roots map[string]*node - handlers map[string]string -} - -func NewRouter() *Router { - return &Router{ - roots: make(map[string]*node), - handlers: make(map[string]string), - } -} - -// Only one * is allowed -func parsePattern(pattern string) []string { - vs := strings.Split(pattern, "/") - - parts := make([]string, 0) - for _, item := range vs { - if item != "" { - parts = append(parts, item) - if item[0] == '*' { - break - } - } - } - return parts -} - -func (r *Router) AddRoute(method string, pattern string, handler string) { - parts := parsePattern(pattern) - - key := method + "-" + pattern - _, ok := r.roots[method] - if !ok { - r.roots[method] = &node{} - } - r.roots[method].insert(pattern, parts, 0) - r.handlers[key] = handler -} - -func (r *Router) GetRoute(method string, path string) (*node, map[string]string) { - searchParts := parsePattern(path) - params := make(map[string]string) - root, ok := r.roots[method] - - if !ok { - return nil, nil - } - - n := root.search(searchParts, 0) - - if n != nil { - parts := parsePattern(n.pattern) - for index, part := range parts { - if part[0] == ':' { - params[part[1:]] = searchParts[index] - } - //if part[0] == '*' && len(part) > 1 { - // params[part[1:]] = strings.Join(searchParts[index:], "/") - // break - //} - } - return n, params - } - - return nil, nil -} - -func (r *Router) getRoutes(method string) []*node { - root, ok := r.roots[method] - if !ok { - return nil - } - nodes := make([]*node, 0) - root.travel(&nodes) - return nodes -} - -func (r *Router) Handle(method string, path string) (handle string, err error) { - n, _ := r.GetRoute(method, path) - if n == nil { - err = errors.New("router not match") - return - - } - return r.handlers[method+"-"+n.pattern], nil -} diff --git a/internal/core/router_test.go b/internal/core/router_test.go deleted file mode 100644 index ea49bbf2..00000000 --- a/internal/core/router_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package core - -import ( - "fmt" - "reflect" - "testing" -) - -func newTestRouter() *Router { - r := NewRouter() - //GET "GET/_mapping/:index": "indices.get_mapping", - r.AddRoute("GET", "/:index/_mappings", "indices.get_mapping") - r.AddRoute("GET", "/hello/:name", "gethello") - r.AddRoute("GET", "/hello/b/c", "hellobc") - r.AddRoute("GET", "/hi/:name", "getHi") - r.AddRoute("GET", "/role/xushuhui", "getRole") - - return r -} - -func TestParsePattern(t *testing.T) { - ok := reflect.DeepEqual(parsePattern("/p/:name"), []string{"p", ":name"}) - ok = ok && reflect.DeepEqual(parsePattern("/p/*"), []string{"p", "*"}) - ok = ok && reflect.DeepEqual(parsePattern("/p/*name/*"), []string{"p", "*name"}) - if !ok { - t.Fatal("test parsePattern failed") - } -} - -func TestGetRoute(t *testing.T) { - //r := newTestRouter() - //path := "/elasticsearch/c6dgjtgvi076f32oibj0/index/test/_mappings" - //paths := strings.Split(path, "/") - //newPath := "/" + strings.Join(paths[4:], "/") - //t.Log(newPath) - - //if n == nil { - // t.Fatal("nil shouldn't be returned") - //} - - //if n.pattern != "/hello/:name" { - // t.Fatal("should match /hello/:name") - //} - // - //if ps["name"] != "geektutu" { - // t.Fatal("name should be equal to 'geektutu'") - //} - - //fmt.Printf("matched path: %s, params['name']: %s\n", n.pattern, ps["name"]) - -} - -func TestGetRoute2(t *testing.T) { - r := newTestRouter() - n1, ps1 := r.GetRoute("GET", "/assets/file1.txt") - ok1 := n1.pattern == "/assets/*filepath" && ps1["filepath"] == "file1.txt" - if !ok1 { - t.Fatal("pattern shoule be /assets/*filepath & filepath shoule be file1.txt") - } - - n2, ps2 := r.GetRoute("GET", "/assets/css/test.css") - ok2 := n2.pattern == "/assets/*filepath" && ps2["filepath"] == "css/test.css" - if !ok2 { - t.Fatal("pattern shoule be /assets/*filepath & filepath shoule be css/test.css") - } - -} - -func TestGetRoutes(t *testing.T) { - r := newTestRouter() - nodes := r.getRoutes("GET") - for i, n := range nodes { - fmt.Println(i+1, n) - } - - if len(nodes) != 5 { - t.Fatal("the number of routes shoule be 4") - } -} diff --git a/internal/core/trie.go b/internal/core/trie.go deleted file mode 100644 index 2fcb5b5e..00000000 --- a/internal/core/trie.go +++ /dev/null @@ -1,83 +0,0 @@ -package core - -import ( - "fmt" - "strings" -) - -type node struct { - pattern string // 待匹配路由,例如 /p/:lang - part string // 路由中的一部分,例如 :lang - children []*node // 子节点,例如 [doc, tutorial, intro] - isWild bool // 是否精确匹配,part 含有 : 或 * 时为true -} - -func (n *node) String() string { - return fmt.Sprintf("node{pattern=%s, part=%s, isWild=%t}", n.pattern, n.part, n.isWild) -} - -func (n *node) insert(pattern string, parts []string, height int) { - if len(parts) == height { - n.pattern = pattern - return - } - - part := parts[height] - child := n.matchChild(part) - if child == nil { - child = &node{part: part, isWild: part[0] == ':' || part[0] == '*'} - n.children = append(n.children, child) - } - child.insert(pattern, parts, height+1) -} - -func (n *node) search(parts []string, height int) *node { - if len(parts) == height || strings.HasPrefix(n.part, "*") { - if n.pattern == "" { - return nil - } - return n - } - - part := parts[height] - children := n.matchChildren(part) - - for _, child := range children { - result := child.search(parts, height+1) - if result != nil { - return result - } - } - - return nil -} - -func (n *node) travel(list *[]*node) { - if n.pattern != "" { - *list = append(*list, n) - } - for _, child := range n.children { - child.travel(list) - } -} - -// 第一个匹配成功的节点,用于插入 -func (n *node) matchChild(part string) *node { - for _, child := range n.children { - if child.part == part || child.isWild { - return child - } - } - return nil -} - -// 所有匹配成功的节点,用于查找 -func (n *node) matchChildren(part string) []*node { - nodes := make([]*node, 0) - for _, child := range n.children { - if child.part == part || child.isWild { - nodes = append(nodes, child) - } - } - return nodes -} diff --git a/internal/dto/role.go b/internal/dto/role.go index f56a7c48..806dba23 100644 --- a/internal/dto/role.go +++ b/internal/dto/role.go @@ -1,20 +1,5 @@ package dto -type UpdateRole struct { - Description string `json:"description" ` - Platform []string `json:"platform"` - Cluster []string `json:"cluster" ` - Index []string `json:"index" ` - ClusterPrivilege []string `json:"cluster_privilege" ` - IndexPrivilege []string `json:"index_privilege" ` -} - -type ElasticsearchPermission struct { - Cluster []string `json:"cluster" ` - Index []string `json:"index" ` - ClusterPrivilege []string `json:"cluster_privilege" ` - IndexPrivilege []string `json:"index_privilege" ` -} type CreateUser struct { NickName string `json:"nick_name"` diff --git a/internal/middleware/es.go b/internal/middleware/es.go index 32e4ca94..c8aa78db 100644 --- a/internal/middleware/es.go +++ b/internal/middleware/es.go @@ -34,10 +34,10 @@ func ClusterRequired(h httprouter.Handle, route ...string) httprouter.Handle { w = handleError(w, http.StatusUnauthorized, err) return } - newRole := biz.CombineUserRoles(claims.Roles) + //newRole := biz.CombineUserRoles(claims.Roles) clusterReq := biz.NewClusterRequest(ps, route) - err = biz.ValidateCluster(clusterReq, newRole) + err = biz.ValidateCluster(clusterReq, claims.Roles) if err != nil { w = handleError(w, http.StatusForbidden, err) return