update validate
This commit is contained in:
parent
abe934cef3
commit
e5d119885e
|
@ -1,7 +1,6 @@
|
||||||
package biz
|
package biz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"infini.sh/console/internal/core"
|
|
||||||
"infini.sh/console/model/rbac"
|
"infini.sh/console/model/rbac"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,8 +17,6 @@ type Token struct {
|
||||||
|
|
||||||
var TokenMap = make(map[string]Token)
|
var TokenMap = make(map[string]Token)
|
||||||
|
|
||||||
var EsApiRoutes = core.NewRouter()
|
|
||||||
|
|
||||||
|
|
||||||
type RolePermission struct {
|
type RolePermission struct {
|
||||||
Platform []string `json:"platform,omitempty"`
|
Platform []string `json:"platform,omitempty"`
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"infini.sh/console/internal/biz/enum"
|
"infini.sh/console/internal/biz/enum"
|
||||||
|
"infini.sh/console/model/rbac"
|
||||||
httprouter "infini.sh/framework/core/api/router"
|
httprouter "infini.sh/framework/core/api/router"
|
||||||
"infini.sh/framework/core/util"
|
"infini.sh/framework/core/util"
|
||||||
"src/github.com/golang-jwt/jwt"
|
"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) {
|
func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
||||||
|
|
||||||
userClusterMap := make(map[string]struct{})
|
userClusterMap := make(map[string]struct{})
|
||||||
|
@ -60,7 +66,7 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
||||||
for _, val := range req.Privilege {
|
for _, val := range req.Privilege {
|
||||||
position := strings.Index(val, ".")
|
position := strings.Index(val, ".")
|
||||||
if position == -1 {
|
if position == -1 {
|
||||||
err = errors.New("invalid privilege parmeter")
|
err = errors.New("invalid privilege parameter")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
prefix := val[:position]
|
prefix := val[:position]
|
||||||
|
@ -71,42 +77,43 @@ func ValidateIndex(req IndexRequest, userRole RolePermission) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if util.StringInArray(privilege, prefix+".*") {
|
if util.StringInArray(privilege, prefix+".*") {
|
||||||
return nil
|
continue
|
||||||
}
|
}
|
||||||
if util.StringInArray(privilege, val) {
|
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) {
|
func ValidateCluster(req ClusterRequest, roleNames []string) (err error) {
|
||||||
userClusterMap := make(map[string]struct{})
|
userClusterMap := GetRoleClusterMap(roleNames)
|
||||||
for _, v := range userRole.Cluster {
|
|
||||||
userClusterMap[v] = struct{}{}
|
|
||||||
}
|
|
||||||
for _, v := range req.Cluster {
|
for _, v := range req.Cluster {
|
||||||
if _, ok := userClusterMap[v]; !ok {
|
userClusterPermissions, ok := userClusterMap[v]
|
||||||
err = errors.New("no cluster permission")
|
if !ok && userClusterMap["*"] == nil{
|
||||||
|
err = fmt.Errorf("no cluster[%s] permission", v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
if util.StringInArray(userClusterPermissions, "*") {
|
||||||
|
continue
|
||||||
// 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(userRole.ClusterPrivilege, privilege) {
|
// if include api.* for example: cat.* , return nil
|
||||||
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 {
|
func CombineUserRoles(roleNames []string) RolePermission {
|
||||||
|
@ -139,26 +146,43 @@ func CombineUserRoles(roleNames []string) RolePermission {
|
||||||
newRole.IndexPrivilege = m
|
newRole.IndexPrivilege = m
|
||||||
return newRole
|
return newRole
|
||||||
}
|
}
|
||||||
func FilterCluster(roles []string, cluster []string) []string {
|
func GetRoleClusterMap(roles []string) map[string][]string {
|
||||||
newRole := CombineUserRoles(roles)
|
userClusterMap := make(map[string][]string, 0)
|
||||||
userClusterMap := make(map[string]struct{}, 0)
|
for _, roleName := range roles {
|
||||||
for _, v := range newRole.Cluster {
|
role, ok := RoleMap[roleName]
|
||||||
userClusterMap[v] = struct{}{}
|
if ok {
|
||||||
}
|
for _, ic := range role.Privilege.Elasticsearch.Cluster.Resources {
|
||||||
realCluster := make([]string, 0)
|
userClusterMap[ic.ID] = append(userClusterMap[ic.ID], role.Privilege.Elasticsearch.Cluster.Permissions...)
|
||||||
for _, v := range cluster {
|
}
|
||||||
if _, ok := userClusterMap[v]; ok {
|
|
||||||
realCluster = append(realCluster, v)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
return realCluster
|
||||||
}
|
}
|
||||||
func FilterIndex(roles []string, index []string) []string {
|
func GetRoleIndex(roles, clusterIDs []string) map[string][]string {
|
||||||
realIndex := make([]string, 0)
|
userClusterMap := make(map[string]struct{}, len(clusterIDs))
|
||||||
newRole := CombineUserRoles(roles)
|
for _, clusterID := range clusterIDs {
|
||||||
for _, v := range index {
|
userClusterMap[clusterID] = struct{}{}
|
||||||
if _, ok := newRole.IndexPrivilege[v]; ok {
|
}
|
||||||
realIndex = append(realIndex, v)
|
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
|
return realIndex
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,20 +1,5 @@
|
||||||
package dto
|
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 {
|
type CreateUser struct {
|
||||||
NickName string `json:"nick_name"`
|
NickName string `json:"nick_name"`
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,10 @@ func ClusterRequired(h httprouter.Handle, route ...string) httprouter.Handle {
|
||||||
w = handleError(w, http.StatusUnauthorized, err)
|
w = handleError(w, http.StatusUnauthorized, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newRole := biz.CombineUserRoles(claims.Roles)
|
//newRole := biz.CombineUserRoles(claims.Roles)
|
||||||
clusterReq := biz.NewClusterRequest(ps, route)
|
clusterReq := biz.NewClusterRequest(ps, route)
|
||||||
|
|
||||||
err = biz.ValidateCluster(clusterReq, newRole)
|
err = biz.ValidateCluster(clusterReq, claims.Roles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w = handleError(w, http.StatusForbidden, err)
|
w = handleError(w, http.StatusForbidden, err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue