update validate

This commit is contained in:
liugq 2022-05-07 14:46:08 +08:00
parent abe934cef3
commit e5d119885e
7 changed files with 65 additions and 315 deletions

View File

@ -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"`

View File

@ -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

View File

@ -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
}

View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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"`

View File

@ -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