@@ -28,9 +28,19 @@ import (
|
|||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/filter/route"
|
"kubesphere.io/kubesphere/pkg/filter/route"
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type roleList struct {
|
||||||
|
ClusterRoles []v1.ClusterRole `json:"clusterRoles" protobuf:"bytes,2,rep,name=clusterRoles"`
|
||||||
|
Roles []v1.Role `json:"roles" protobuf:"bytes,2,rep,name=roles"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type userRuleList struct {
|
||||||
|
ClusterRules []iam.Rule `json:"clusterRules"`
|
||||||
|
Rules map[string][]iam.Rule `json:"rules"`
|
||||||
|
}
|
||||||
|
|
||||||
func Register(ws *restful.WebService) {
|
func Register(ws *restful.WebService) {
|
||||||
//roles
|
//roles
|
||||||
ws.Route(ws.GET("/users/{username}/roles").To(userRolesHandler).Filter(route.RouteLogging)).Produces(restful.MIME_JSON)
|
ws.Route(ws.GET("/users/{username}/roles").To(userRolesHandler).Filter(route.RouteLogging)).Produces(restful.MIME_JSON)
|
||||||
@@ -53,14 +63,14 @@ func userRolesHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
|
|
||||||
username := req.PathParameter("username")
|
username := req.PathParameter("username")
|
||||||
|
|
||||||
roles, err := models.GetRoles(username)
|
roles, err := iam.GetRoles(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterRoles, err := models.GetClusterRoles(username)
|
clusterRoles, err := iam.GetClusterRoles(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
@@ -79,7 +89,7 @@ func roleUsersHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
name := req.PathParameter("name")
|
name := req.PathParameter("name")
|
||||||
namespace := req.PathParameter("namespace")
|
namespace := req.PathParameter("namespace")
|
||||||
|
|
||||||
roleBindings, err := models.GetRoleBindings(namespace, name)
|
roleBindings, err := iam.GetRoleBindings(namespace, name)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
@@ -105,7 +115,7 @@ func roleUsersHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
func clusterRoleUsersHandler(req *restful.Request, resp *restful.Response) {
|
func clusterRoleUsersHandler(req *restful.Request, resp *restful.Response) {
|
||||||
name := req.PathParameter("name")
|
name := req.PathParameter("name")
|
||||||
|
|
||||||
roleBindings, err := models.GetClusterRoleBindings(name)
|
roleBindings, err := iam.GetClusterRoleBindings(name)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
@@ -138,14 +148,14 @@ func usersRulesHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
|
|
||||||
userRuleList := userRuleList{}
|
userRuleList := userRuleList{}
|
||||||
|
|
||||||
clusterRules, err := getUserClusterRules(username)
|
clusterRules, err := iam.GetUserClusterRules(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rules, err := getUserRules(username)
|
rules, err := iam.GetUserRules(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
@@ -168,14 +178,14 @@ func userRulesHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
|
|
||||||
userRuleList := userRuleList{}
|
userRuleList := userRuleList{}
|
||||||
|
|
||||||
clusterRules, err := getUserClusterRules(username)
|
clusterRules, err := iam.GetUserClusterRules(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rules, err := getUserRules(username)
|
rules, err := iam.GetUserRules(username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
@@ -193,13 +203,13 @@ func clusterRoleRulesHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
|
|
||||||
name := req.PathParameter("name")
|
name := req.PathParameter("name")
|
||||||
|
|
||||||
var rules []rule
|
var rules []iam.Rule
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
rules = clusterRoleRuleGroup
|
rules = iam.ClusterRoleRuleGroup
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
rules, err = getClusterRoleRules(name)
|
rules, err = iam.GetClusterRoleRules(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
@@ -214,13 +224,13 @@ func roleRulesHandler(req *restful.Request, resp *restful.Response) {
|
|||||||
name := req.PathParameter("name")
|
name := req.PathParameter("name")
|
||||||
namespace := req.PathParameter("namespace")
|
namespace := req.PathParameter("namespace")
|
||||||
|
|
||||||
var rules []rule
|
var rules []iam.Rule
|
||||||
|
|
||||||
if namespace == "" && name == "" {
|
if namespace == "" && name == "" {
|
||||||
rules = roleRuleGroup
|
rules = iam.RoleRuleGroup
|
||||||
} else {
|
} else {
|
||||||
var err error
|
var err error
|
||||||
rules, err = getRoleRules(namespace, name)
|
rules, err = iam.GetRoleRules(namespace, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,228 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 The KubeSphere Authors.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
package iam
|
|
||||||
|
|
||||||
import (
|
|
||||||
"k8s.io/api/rbac/v1"
|
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/util/slice"
|
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getUserRules(username string) (map[string][]rule, error) {
|
|
||||||
|
|
||||||
items := make(map[string][]rule, 0)
|
|
||||||
roles, err := models.GetRoles(username)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
namespaces := make([]string, 0)
|
|
||||||
|
|
||||||
for i := 0; i < len(roles); i++ {
|
|
||||||
if !slice.ContainsString(namespaces, roles[i].Namespace, nil) {
|
|
||||||
namespaces = append(namespaces, roles[i].Namespace)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, namespace := range namespaces {
|
|
||||||
rules := getMergeRules(namespace, roles)
|
|
||||||
if len(rules) > 0 {
|
|
||||||
items[namespace] = rules
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMergeRules(namespace string, roles []v1.Role) []rule {
|
|
||||||
rules := make([]rule, 0)
|
|
||||||
|
|
||||||
for i := 0; i < (len(roleRuleGroup)); i++ {
|
|
||||||
rule := rule{Name: roleRuleGroup[i].Name}
|
|
||||||
rule.Actions = make([]action, 0)
|
|
||||||
for j := 0; j < (len(roleRuleGroup[i].Actions)); j++ {
|
|
||||||
permit := false
|
|
||||||
for _, role := range roles {
|
|
||||||
if role.Namespace == namespace && actionValidate(role.Rules, roleRuleGroup[i].Actions[j]) {
|
|
||||||
permit = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if permit {
|
|
||||||
rule.Actions = append(rule.Actions, roleRuleGroup[i].Actions[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rule.Actions) > 0 {
|
|
||||||
rules = append(rules, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules
|
|
||||||
}
|
|
||||||
|
|
||||||
func getUserClusterRules(username string) ([]rule, error) {
|
|
||||||
|
|
||||||
rules := make([]rule, 0)
|
|
||||||
|
|
||||||
roles, err := models.GetClusterRoles(username)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < (len(clusterRoleRuleGroup)); i++ {
|
|
||||||
rule := rule{Name: clusterRoleRuleGroup[i].Name}
|
|
||||||
rule.Actions = make([]action, 0)
|
|
||||||
for j := 0; j < (len(clusterRoleRuleGroup[i].Actions)); j++ {
|
|
||||||
actionPermit := false
|
|
||||||
for _, role := range roles {
|
|
||||||
if actionValidate(role.Rules, clusterRoleRuleGroup[i].Actions[j]) {
|
|
||||||
actionPermit = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if actionPermit {
|
|
||||||
rule.Actions = append(rule.Actions, clusterRoleRuleGroup[i].Actions[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rule.Actions) > 0 {
|
|
||||||
rules = append(rules, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getClusterRoleRules(name string) ([]rule, error) {
|
|
||||||
|
|
||||||
clusterRole, err := models.GetClusterRole(name)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
rules := make([]rule, 0)
|
|
||||||
|
|
||||||
for i := 0; i < len(clusterRoleRuleGroup); i++ {
|
|
||||||
rule := rule{Name: clusterRoleRuleGroup[i].Name}
|
|
||||||
rule.Actions = make([]action, 0)
|
|
||||||
for j := 0; j < (len(clusterRoleRuleGroup[i].Actions)); j++ {
|
|
||||||
if actionValidate(clusterRole.Rules, clusterRoleRuleGroup[i].Actions[j]) {
|
|
||||||
rule.Actions = append(rule.Actions, clusterRoleRuleGroup[i].Actions[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(rule.Actions) > 0 {
|
|
||||||
rules = append(rules, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRoleRules(namespace string, name string) ([]rule, error) {
|
|
||||||
role, err := models.GetRole(namespace, name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rules := make([]rule, 0)
|
|
||||||
for i := 0; i < len(roleRuleGroup); i++ {
|
|
||||||
rule := rule{Name: roleRuleGroup[i].Name}
|
|
||||||
rule.Actions = make([]action, 0)
|
|
||||||
for j := 0; j < len(roleRuleGroup[i].Actions); j++ {
|
|
||||||
if actionValidate(role.Rules, roleRuleGroup[i].Actions[j]) {
|
|
||||||
rule.Actions = append(rule.Actions, roleRuleGroup[i].Actions[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(rule.Actions) > 0 {
|
|
||||||
rules = append(rules, rule)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rules, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func actionValidate(rules []v1.PolicyRule, action action) bool {
|
|
||||||
for _, rule := range action.Rules {
|
|
||||||
if !ruleValidate(rules, rule) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func ruleValidate(rules []v1.PolicyRule, rule v1.PolicyRule) bool {
|
|
||||||
|
|
||||||
for _, apiGroup := range rule.APIGroups {
|
|
||||||
if len(rule.NonResourceURLs) == 0 {
|
|
||||||
for _, resource := range rule.Resources {
|
|
||||||
|
|
||||||
//if len(rule.ResourceNames) == 0 {
|
|
||||||
|
|
||||||
for _, verb := range rule.Verbs {
|
|
||||||
if !verbValidate(rules, apiGroup, "", resource, "", verb) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//} else {
|
|
||||||
// for _, resourceName := range rule.ResourceNames {
|
|
||||||
// for _, verb := range rule.Verbs {
|
|
||||||
// if !verbValidate(rules, apiGroup, "", resource, resourceName, verb) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
|
||||||
for _, verb := range rule.Verbs {
|
|
||||||
if !verbValidate(rules, apiGroup, nonResourceURL, "", "", verb) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func verbValidate(rules []v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, resourceName string, verb string) bool {
|
|
||||||
for _, rule := range rules {
|
|
||||||
if slice.ContainsString(rule.APIGroups, apiGroup, nil) || slice.ContainsString(rule.APIGroups, v1.APIGroupAll, nil) {
|
|
||||||
if slice.ContainsString(rule.Verbs, verb, nil) || slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
|
||||||
if nonResourceURL == "" {
|
|
||||||
if slice.ContainsString(rule.Resources, resource, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
|
||||||
if resourceName == "" {
|
|
||||||
return true
|
|
||||||
} else if slice.ContainsString(rule.ResourceNames, resourceName, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if slice.ContainsString(rule.NonResourceURLs, nonResourceURL, nil) || slice.ContainsString(rule.NonResourceURLs, v1.NonResourceAll, nil) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
@@ -20,11 +20,11 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/models"
|
"kubesphere.io/kubesphere/pkg/models"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Register(ws *restful.WebService, subPath string) {
|
func Register(ws *restful.WebService, subPath string) {
|
||||||
@@ -74,7 +74,7 @@ func delUser(req *restful.Request, resp *restful.Response) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = models.DeleteRoleBindings(user)
|
err = iam.DeleteRoleBindings(user)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||||
|
|||||||
@@ -66,11 +66,11 @@ func preCheck() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, ns := range nsList.Items {
|
for _, ns := range nsList.Items {
|
||||||
if ns.Name == constants.KubeSphereControlNameSpace {
|
if ns.Name == constants.KubeSphereControlNamespace {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace := v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: constants.KubeSphereControlNameSpace}}
|
namespace := v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: constants.KubeSphereControlNamespace}}
|
||||||
_, err = k8sClient.CoreV1().Namespaces().Create(&namespace)
|
_, err = k8sClient.CoreV1().Namespaces().Create(&namespace)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,16 @@ type PageableResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
APIVERSION = "v1alpha1"
|
APIVersion = "v1alpha1"
|
||||||
KIND = "kubesphere"
|
|
||||||
KubeSphereControlNameSpace = "kubesphere-controls-system"
|
|
||||||
|
|
||||||
DataHome = "/etc/kubesphere"
|
KubeSystemNamespace = "kube-system"
|
||||||
IngressControllerFolder = DataHome + "/ingress-controller"
|
OpenPitrixNamespace = "openpitrix-system"
|
||||||
IngressControllerNamespace = KubeSphereControlNameSpace
|
IstioNamespace = "istio-system"
|
||||||
IngressControllerPrefix = "kubesphere-router-"
|
KubeSphereNamespace = "kubesphere-system"
|
||||||
|
KubeSphereControlNamespace = "kubesphere-controls-system"
|
||||||
|
IngressControllerNamespace = KubeSphereControlNamespace
|
||||||
|
|
||||||
|
DataHome = "/etc/kubesphere"
|
||||||
|
IngressControllerFolder = DataHome + "/ingress-controller"
|
||||||
|
IngressControllerPrefix = "kubesphere-router-"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,13 +23,9 @@ import (
|
|||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/client"
|
"kubesphere.io/kubesphere/pkg/client"
|
||||||
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
const KUBESYSTEM = "kube-system"
|
|
||||||
const OPENPITRIX = "openpitrix-system"
|
|
||||||
const ISTIO = "istio-system"
|
|
||||||
const KUBESPHERE = "kubesphere-system"
|
|
||||||
|
|
||||||
type ComponentsCount struct {
|
type ComponentsCount struct {
|
||||||
KubernetesCount int `json:"kubernetesCount"`
|
KubernetesCount int `json:"kubernetesCount"`
|
||||||
OpenpitrixCount int `json:"openpitrixCount"`
|
OpenpitrixCount int `json:"openpitrixCount"`
|
||||||
@@ -63,10 +59,10 @@ func GetComponents() (map[string]interface{}, error) {
|
|||||||
LabelSelector: label,
|
LabelSelector: label,
|
||||||
}
|
}
|
||||||
|
|
||||||
namespaces := []string{KUBESYSTEM, OPENPITRIX, ISTIO, KUBESPHERE}
|
namespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.IstioNamespace, constants.KubeSphereNamespace}
|
||||||
for _, ns := range namespaces {
|
for _, ns := range namespaces {
|
||||||
|
|
||||||
if ns != KUBESYSTEM {
|
if ns != constants.KubeSystemNamespace {
|
||||||
option.LabelSelector = ""
|
option.LabelSelector = ""
|
||||||
}
|
}
|
||||||
servicelists, err := k8sClient.CoreV1().Services(ns).List(option)
|
servicelists, err := k8sClient.CoreV1().Services(ns).List(option)
|
||||||
@@ -84,11 +80,11 @@ func GetComponents() (map[string]interface{}, error) {
|
|||||||
|
|
||||||
switch ns {
|
switch ns {
|
||||||
|
|
||||||
case KUBESYSTEM:
|
case constants.KubeSystemNamespace:
|
||||||
count.KubernetesCount++
|
count.KubernetesCount++
|
||||||
case OPENPITRIX:
|
case constants.OpenPitrixNamespace:
|
||||||
count.OpenpitrixCount++
|
count.OpenpitrixCount++
|
||||||
case KUBESPHERE:
|
case constants.KubeSphereNamespace:
|
||||||
count.KubesphereCount++
|
count.KubesphereCount++
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -33,19 +33,23 @@ import (
|
|||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/kubernetes/pkg/util/slice"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/client"
|
"kubesphere.io/kubesphere/pkg/client"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
"kubesphere.io/kubesphere/pkg/options"
|
"kubesphere.io/kubesphere/pkg/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
provider = "kubernetes"
|
provider = "kubernetes"
|
||||||
admin = "admin"
|
admin = "admin"
|
||||||
editor = "editor"
|
editor = "editor"
|
||||||
viewer = "viewer"
|
viewer = "viewer"
|
||||||
kubectlNamespace = constants.KubeSphereControlNameSpace
|
kubectlNamespace = constants.KubeSphereControlNamespace
|
||||||
kubectlConfigKey = "config"
|
kubectlConfigKey = "config"
|
||||||
openpitrix_runtime = "openpitrix_runtime"
|
openPitrixRuntimeAnnotateKey = "openpitrix_runtime"
|
||||||
|
creatorAnnotateKey = "creator"
|
||||||
)
|
)
|
||||||
|
|
||||||
var adminRules = []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}
|
var adminRules = []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}
|
||||||
@@ -96,7 +100,13 @@ func (ctl *NamespaceCtl) getKubeConfig(user string) (string, error) {
|
|||||||
|
|
||||||
func (ctl *NamespaceCtl) deleteOpRuntime(item v1.Namespace) {
|
func (ctl *NamespaceCtl) deleteOpRuntime(item v1.Namespace) {
|
||||||
|
|
||||||
runtimeId := item.Annotations["openpitrix_runtime"]
|
var runtimeId string
|
||||||
|
if item.Annotations == nil {
|
||||||
|
runtimeId = ""
|
||||||
|
} else {
|
||||||
|
runtimeId = item.Annotations[openPitrixRuntimeAnnotateKey]
|
||||||
|
}
|
||||||
|
|
||||||
if len(runtimeId) == 0 {
|
if len(runtimeId) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -107,9 +117,10 @@ func (ctl *NamespaceCtl) deleteOpRuntime(item v1.Namespace) {
|
|||||||
|
|
||||||
body, err := json.Marshal(deleteRuntime)
|
body, err := json.Marshal(deleteRuntime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error(err)
|
glog.Error("runtime release failed:", item.Name, runtimeId, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
glog.Info("runtime release succeeded:", item.Name, runtimeId)
|
||||||
|
|
||||||
// todo: if delete failed, what's to be done?
|
// todo: if delete failed, what's to be done?
|
||||||
makeHttpRequest("DELETE", url, string(body))
|
makeHttpRequest("DELETE", url, string(body))
|
||||||
@@ -137,19 +148,15 @@ func (ctl *NamespaceCtl) createOpRuntime(namespace string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *NamespaceCtl) createDefaultRoleBinding(ns, user string) error {
|
func (ctl *NamespaceCtl) createDefaultRoleBinding(ns, user string) error {
|
||||||
rolebinding, _ := ctl.K8sClient.RbacV1().RoleBindings(ns).Get(admin, metaV1.GetOptions{})
|
|
||||||
|
|
||||||
if rolebinding.Name != admin {
|
roleBinding := &rbac.RoleBinding{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns},
|
||||||
|
Subjects: []rbac.Subject{{Name: user, Kind: rbac.UserKind}}, RoleRef: rbac.RoleRef{Kind: "Role", Name: admin}}
|
||||||
|
|
||||||
roleBinding := &rbac.RoleBinding{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns},
|
_, err := ctl.K8sClient.RbacV1().RoleBindings(ns).Create(roleBinding)
|
||||||
Subjects: []rbac.Subject{{Name: user, Kind: rbac.UserKind}}, RoleRef: rbac.RoleRef{Kind: "Role", Name: admin}}
|
|
||||||
|
|
||||||
_, err := ctl.K8sClient.RbacV1().RoleBindings(ns).Create(roleBinding)
|
if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
|
glog.Error(err)
|
||||||
if err != nil {
|
return err
|
||||||
glog.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -160,72 +167,86 @@ func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
|
|||||||
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns}, Rules: editorRules}
|
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns}, Rules: editorRules}
|
||||||
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns}, Rules: viewerRules}
|
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns}, Rules: viewerRules}
|
||||||
|
|
||||||
role, _ := ctl.K8sClient.RbacV1().Roles(ns).Get(admin, metaV1.GetOptions{})
|
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
|
||||||
|
|
||||||
if role.Name != admin {
|
if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
|
return err
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
role, _ = ctl.K8sClient.RbacV1().Roles(ns).Get(editor, metaV1.GetOptions{})
|
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(editorRole)
|
||||||
|
|
||||||
if role.Name != editor {
|
if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(editorRole)
|
return err
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
role, _ = ctl.K8sClient.RbacV1().Roles(ns).Get(viewer, metaV1.GetOptions{})
|
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(viewerRole)
|
||||||
|
|
||||||
if role.Name != viewer {
|
if err != nil && !errors.IsAlreadyExists(err) {
|
||||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(viewerRole)
|
return err
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) {
|
func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) {
|
||||||
user := item.Annotations["creator"]
|
var creator string
|
||||||
|
var runtime string
|
||||||
ns := item.Name
|
ns := item.Name
|
||||||
if len(user) > 0 && len(item.Annotations[openpitrix_runtime]) == 0 {
|
|
||||||
err := ctl.createDefaultRole(ns)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := ctl.createOpRuntime(ns)
|
if item.Annotations == nil {
|
||||||
if err != nil {
|
creator = ""
|
||||||
glog.Error(err)
|
runtime = ""
|
||||||
return
|
} else {
|
||||||
}
|
runtime = item.Annotations[openPitrixRuntimeAnnotateKey]
|
||||||
|
creator = item.Annotations[creatorAnnotateKey]
|
||||||
err = ctl.createDefaultRoleBinding(ns, user)
|
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var runtime runTime
|
|
||||||
err = json.Unmarshal(resp, &runtime)
|
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
item.Annotations[openpitrix_runtime] = runtime.RuntimeId
|
|
||||||
_, err = ctl.K8sClient.CoreV1().Namespaces().Update(&item)
|
|
||||||
if err != nil {
|
|
||||||
glog.Error(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentsNamespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.IstioNamespace, constants.KubeSphereNamespace}
|
||||||
|
|
||||||
|
if len(runtime) == 0 && !slice.ContainsString(componentsNamespaces, ns, nil) {
|
||||||
|
glog.Infoln("create runtime:", ns)
|
||||||
|
var runtimeCreateError error
|
||||||
|
resp, runtimeCreateError := ctl.createOpRuntime(ns)
|
||||||
|
|
||||||
|
if runtimeCreateError == nil {
|
||||||
|
var runtime runTime
|
||||||
|
runtimeCreateError = json.Unmarshal(resp, &runtime)
|
||||||
|
if runtimeCreateError == nil {
|
||||||
|
|
||||||
|
if item.Annotations == nil {
|
||||||
|
item.Annotations = make(map[string]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
item.Annotations[openPitrixRuntimeAnnotateKey] = runtime.RuntimeId
|
||||||
|
_, runtimeCreateError = ctl.K8sClient.CoreV1().Namespaces().Update(&item)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtimeCreateError != nil {
|
||||||
|
glog.Error("runtime create error:", runtimeCreateError)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(creator) > 0 {
|
||||||
|
roleCreateError := ctl.createDefaultRole(ns)
|
||||||
|
glog.Infoln("create default role:", ns)
|
||||||
|
if roleCreateError == nil {
|
||||||
|
|
||||||
|
roleBindingError := ctl.createDefaultRoleBinding(ns, creator)
|
||||||
|
glog.Infoln("create default role binding:", ns)
|
||||||
|
if roleBindingError != nil {
|
||||||
|
glog.Error("default role binding create error:", roleBindingError)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glog.Error("default role create error:", roleCreateError)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glog.Infoln("runtime has been init:", ns, runtime)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctl *NamespaceCtl) generateObject(item v1.Namespace) *Namespace {
|
func (ctl *NamespaceCtl) generateObject(item v1.Namespace) *Namespace {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package models
|
package iam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@@ -6,11 +6,66 @@ import (
|
|||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"k8s.io/kubernetes/pkg/util/slice"
|
||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/client"
|
"kubesphere.io/kubesphere/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ClusterRoleKind = "ClusterRole"
|
const ClusterRoleKind = "ClusterRole"
|
||||||
|
|
||||||
|
func GetUserNamespaces(username string, requiredRule v1.PolicyRule) (allNamespace bool, namespaces []string, err error) {
|
||||||
|
|
||||||
|
clusterRoles, err := GetClusterRoles(username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterRules := make([]v1.PolicyRule, 0)
|
||||||
|
for _, role := range clusterRoles {
|
||||||
|
clusterRules = append(clusterRules, role.Rules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if requiredRule.Size() == 0 {
|
||||||
|
if ruleValidate(clusterRules, v1.PolicyRule{
|
||||||
|
Verbs: []string{"get", "list"},
|
||||||
|
APIGroups: []string{""},
|
||||||
|
Resources: []string{"namespaces"},
|
||||||
|
}) {
|
||||||
|
return true, nil, nil
|
||||||
|
}
|
||||||
|
} else if ruleValidate(clusterRules, requiredRule) {
|
||||||
|
return true, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
roles, err := GetRoles(username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rulesMapping := make(map[string][]v1.PolicyRule, 0)
|
||||||
|
|
||||||
|
for _, role := range roles {
|
||||||
|
rules := rulesMapping[role.Namespace]
|
||||||
|
if rules == nil {
|
||||||
|
rules = make([]v1.PolicyRule, 0)
|
||||||
|
}
|
||||||
|
rules = append(rules, role.Rules...)
|
||||||
|
rulesMapping[role.Namespace] = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
namespaces = make([]string, 0)
|
||||||
|
|
||||||
|
for namespace, rules := range rulesMapping {
|
||||||
|
if requiredRule.Size() == 0 || ruleValidate(rules, requiredRule) {
|
||||||
|
namespaces = append(namespaces, namespace)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, namespaces, nil
|
||||||
|
}
|
||||||
|
|
||||||
func DeleteRoleBindings(username string) error {
|
func DeleteRoleBindings(username string) error {
|
||||||
k8s := client.NewK8sClient()
|
k8s := client.NewK8sClient()
|
||||||
|
|
||||||
@@ -208,3 +263,61 @@ func GetClusterRoles(username string) ([]v1.ClusterRole, error) {
|
|||||||
|
|
||||||
return roles, nil
|
return roles, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ruleValidate(rules []v1.PolicyRule, rule v1.PolicyRule) bool {
|
||||||
|
|
||||||
|
for _, apiGroup := range rule.APIGroups {
|
||||||
|
if len(rule.NonResourceURLs) == 0 {
|
||||||
|
for _, resource := range rule.Resources {
|
||||||
|
|
||||||
|
//if len(Rule.ResourceNames) == 0 {
|
||||||
|
|
||||||
|
for _, verb := range rule.Verbs {
|
||||||
|
if !verbValidate(rules, apiGroup, "", resource, "", verb) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//} else {
|
||||||
|
// for _, resourceName := range Rule.ResourceNames {
|
||||||
|
// for _, verb := range Rule.Verbs {
|
||||||
|
// if !verbValidate(rules, apiGroup, "", resource, resourceName, verb) {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||||
|
for _, verb := range rule.Verbs {
|
||||||
|
if !verbValidate(rules, apiGroup, nonResourceURL, "", "", verb) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func verbValidate(rules []v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, resourceName string, verb string) bool {
|
||||||
|
for _, rule := range rules {
|
||||||
|
if slice.ContainsString(rule.APIGroups, apiGroup, nil) || slice.ContainsString(rule.APIGroups, v1.APIGroupAll, nil) {
|
||||||
|
if slice.ContainsString(rule.Verbs, verb, nil) || slice.ContainsString(rule.Verbs, v1.VerbAll, nil) {
|
||||||
|
if nonResourceURL == "" {
|
||||||
|
if slice.ContainsString(rule.Resources, resource, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||||
|
if resourceName == "" {
|
||||||
|
return true
|
||||||
|
} else if slice.ContainsString(rule.ResourceNames, resourceName, nil) || slice.ContainsString(rule.Resources, v1.ResourceAll, nil) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if slice.ContainsString(rule.NonResourceURLs, nonResourceURL, nil) || slice.ContainsString(rule.NonResourceURLs, v1.NonResourceAll, nil) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
|
||||||
"k8s.io/api/rbac/v1"
|
"k8s.io/api/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,59 +29,47 @@ const (
|
|||||||
clusterRulesConfigPath = "/etc/kubesphere/rules/clusterrules.json"
|
clusterRulesConfigPath = "/etc/kubesphere/rules/clusterrules.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
type roleList struct {
|
type Action struct {
|
||||||
ClusterRoles []v1.ClusterRole `json:"clusterRoles" protobuf:"bytes,2,rep,name=clusterRoles"`
|
|
||||||
Roles []v1.Role `json:"roles" protobuf:"bytes,2,rep,name=roles"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type action struct {
|
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Rules []v1.PolicyRule `json:"rules"`
|
Rules []v1.PolicyRule `json:"rules"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type rule struct {
|
type Rule struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Actions []action `json:"actions"`
|
Actions []Action `json:"actions"`
|
||||||
}
|
|
||||||
|
|
||||||
type userRuleList struct {
|
|
||||||
ClusterRules []rule `json:"clusterRules"`
|
|
||||||
Rules map[string][]rule `json:"rules"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rulesConfig, err := ioutil.ReadFile(rulesConfigPath)
|
rulesConfig, err := ioutil.ReadFile(rulesConfigPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
config := &[]rule{}
|
config := &[]Rule{}
|
||||||
json.Unmarshal(rulesConfig, config)
|
json.Unmarshal(rulesConfig, config)
|
||||||
if len(*config) > 0 {
|
if len(*config) > 0 {
|
||||||
roleRuleGroup = *config
|
RoleRuleGroup = *config
|
||||||
glog.Info("rules config load success")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clusterRulesConfig, err := ioutil.ReadFile(clusterRulesConfigPath)
|
clusterRulesConfig, err := ioutil.ReadFile(clusterRulesConfigPath)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
config := &[]rule{}
|
config := &[]Rule{}
|
||||||
json.Unmarshal(clusterRulesConfig, config)
|
json.Unmarshal(clusterRulesConfig, config)
|
||||||
if len(*config) > 0 {
|
if len(*config) > 0 {
|
||||||
clusterRoleRuleGroup = *config
|
ClusterRoleRuleGroup = *config
|
||||||
glog.Info("cluster rules config load success")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
clusterRoleRuleGroup = []rule{projects, users, roles, images,
|
ClusterRoleRuleGroup = []Rule{projects, users, roles, images,
|
||||||
volumes, storageclasses, nodes, appCatalog, apps, components, deployments, statefulsets, daemonsets, pods, services, routes}
|
volumes, storageclasses, nodes, appCatalog, apps, components, deployments, statefulsets, daemonsets, pods, services, routes}
|
||||||
|
|
||||||
roleRuleGroup = []rule{project, deployments, statefulsets, daemonsets, pods,
|
RoleRuleGroup = []Rule{project, deployments, statefulsets, daemonsets, pods,
|
||||||
services, routes, volumes}
|
services, routes, volumes}
|
||||||
|
|
||||||
components = rule{
|
components = Rule{
|
||||||
Name: "components",
|
Name: "components",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -95,9 +82,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
projects = rule{
|
projects = Rule{
|
||||||
Name: "projects",
|
Name: "projects",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -155,9 +142,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
project = rule{
|
project = Rule{
|
||||||
Name: "projects",
|
Name: "projects",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "members",
|
{Name: "members",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -196,9 +183,9 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
users = rule{
|
users = Rule{
|
||||||
Name: "users",
|
Name: "users",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -253,9 +240,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
roles = rule{
|
roles = Rule{
|
||||||
Name: "roles",
|
Name: "roles",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -296,9 +283,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes = rule{
|
nodes = Rule{
|
||||||
Name: "nodes",
|
Name: "nodes",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -329,9 +316,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
volumes = rule{
|
volumes = Rule{
|
||||||
Name: "volumes",
|
Name: "volumes",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -376,9 +363,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
storageclasses = rule{
|
storageclasses = Rule{
|
||||||
Name: "storageclasses",
|
Name: "storageclasses",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -418,9 +405,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
images = rule{
|
images = Rule{
|
||||||
Name: "images",
|
Name: "images",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -473,9 +460,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
appCatalog = rule{
|
appCatalog = Rule{
|
||||||
Name: "app_catalog",
|
Name: "app_catalog",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -515,9 +502,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
apps = rule{
|
apps = Rule{
|
||||||
Name: "apps",
|
Name: "apps",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -530,9 +517,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
statefulsets = rule{
|
statefulsets = Rule{
|
||||||
Name: "statefulsets",
|
Name: "statefulsets",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -591,9 +578,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
daemonsets = rule{
|
daemonsets = Rule{
|
||||||
Name: "daemonsets",
|
Name: "daemonsets",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -643,9 +630,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
services = rule{
|
services = Rule{
|
||||||
Name: "services",
|
Name: "services",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -691,9 +678,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
routes = rule{
|
routes = Rule{
|
||||||
Name: "routes",
|
Name: "routes",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -701,11 +688,6 @@ var (
|
|||||||
APIGroups: []string{"extensions"},
|
APIGroups: []string{"extensions"},
|
||||||
Resources: []string{"ingresses"},
|
Resources: []string{"ingresses"},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Verbs: []string{"list"},
|
|
||||||
APIGroups: []string{""},
|
|
||||||
Resources: []string{"namespaces"},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{Name: "create",
|
{Name: "create",
|
||||||
@@ -738,9 +720,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
deployments = rule{
|
deployments = Rule{
|
||||||
Name: "deployments",
|
Name: "deployments",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "view",
|
{Name: "view",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
@@ -801,9 +783,9 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pods = rule{
|
pods = Rule{
|
||||||
Name: "pods",
|
Name: "pods",
|
||||||
Actions: []action{
|
Actions: []Action{
|
||||||
{Name: "terminal",
|
{Name: "terminal",
|
||||||
Rules: []v1.PolicyRule{
|
Rules: []v1.PolicyRule{
|
||||||
{
|
{
|
||||||
161
pkg/models/iam/tools.go
Normal file
161
pkg/models/iam/tools.go
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2018 The KubeSphere Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
package iam
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/api/rbac/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetUserRules(username string) (map[string][]Rule, error) {
|
||||||
|
|
||||||
|
items := make(map[string][]Rule, 0)
|
||||||
|
userRoles, err := GetRoles(username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rulesMapping := make(map[string][]v1.PolicyRule, 0)
|
||||||
|
|
||||||
|
for _, role := range userRoles {
|
||||||
|
rules := rulesMapping[role.Namespace]
|
||||||
|
if rules == nil {
|
||||||
|
rules = make([]v1.PolicyRule, 0)
|
||||||
|
}
|
||||||
|
rules = append(rules, role.Rules...)
|
||||||
|
rulesMapping[role.Namespace] = rules
|
||||||
|
}
|
||||||
|
|
||||||
|
for namespace, policyRules := range rulesMapping {
|
||||||
|
rules := convertToRules(policyRules)
|
||||||
|
if len(rules) > 0 {
|
||||||
|
items[namespace] = rules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToRules(policyRules []v1.PolicyRule) []Rule {
|
||||||
|
rules := make([]Rule, 0)
|
||||||
|
|
||||||
|
for i := 0; i < (len(RoleRuleGroup)); i++ {
|
||||||
|
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||||
|
rule.Actions = make([]Action, 0)
|
||||||
|
for j := 0; j < (len(RoleRuleGroup[i].Actions)); j++ {
|
||||||
|
if actionValidate(policyRules, RoleRuleGroup[i].Actions[j]) {
|
||||||
|
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rule.Actions) > 0 {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserClusterRules(username string) ([]Rule, error) {
|
||||||
|
|
||||||
|
rules := make([]Rule, 0)
|
||||||
|
|
||||||
|
clusterRoles, err := GetClusterRoles(username)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterRules := make([]v1.PolicyRule, 0)
|
||||||
|
|
||||||
|
for _, role := range clusterRoles {
|
||||||
|
clusterRules = append(clusterRules, role.Rules...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < (len(ClusterRoleRuleGroup)); i++ {
|
||||||
|
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||||
|
rule.Actions = make([]Action, 0)
|
||||||
|
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||||
|
if actionValidate(clusterRules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||||
|
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rule.Actions) > 0 {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetClusterRoleRules(name string) ([]Rule, error) {
|
||||||
|
|
||||||
|
clusterRole, err := GetClusterRole(name)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := make([]Rule, 0)
|
||||||
|
|
||||||
|
for i := 0; i < len(ClusterRoleRuleGroup); i++ {
|
||||||
|
rule := Rule{Name: ClusterRoleRuleGroup[i].Name}
|
||||||
|
rule.Actions = make([]Action, 0)
|
||||||
|
for j := 0; j < (len(ClusterRoleRuleGroup[i].Actions)); j++ {
|
||||||
|
if actionValidate(clusterRole.Rules, ClusterRoleRuleGroup[i].Actions[j]) {
|
||||||
|
rule.Actions = append(rule.Actions, ClusterRoleRuleGroup[i].Actions[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rule.Actions) > 0 {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRoleRules(namespace string, name string) ([]Rule, error) {
|
||||||
|
role, err := GetRole(namespace, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := make([]Rule, 0)
|
||||||
|
for i := 0; i < len(RoleRuleGroup); i++ {
|
||||||
|
rule := Rule{Name: RoleRuleGroup[i].Name}
|
||||||
|
rule.Actions = make([]Action, 0)
|
||||||
|
for j := 0; j < len(RoleRuleGroup[i].Actions); j++ {
|
||||||
|
if actionValidate(role.Rules, RoleRuleGroup[i].Actions[j]) {
|
||||||
|
rule.Actions = append(rule.Actions, RoleRuleGroup[i].Actions[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(rule.Actions) > 0 {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func actionValidate(rules []v1.PolicyRule, action Action) bool {
|
||||||
|
for _, rule := range action.Rules {
|
||||||
|
if !ruleValidate(rules, rule) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -246,7 +246,7 @@ func CreateKubeConfig(user string) error {
|
|||||||
|
|
||||||
data := map[string]string{"config": string(config)}
|
data := map[string]string{"config": string(config)}
|
||||||
var configmap = v1.ConfigMap{TypeMeta: metav1.TypeMeta{Kind: "Configmap", APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{Name: user}, Data: data}
|
var configmap = v1.ConfigMap{TypeMeta: metav1.TypeMeta{Kind: "Configmap", APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{Name: user}, Data: data}
|
||||||
_, err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNameSpace).Create(&configmap)
|
_, err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Create(&configmap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorln(err)
|
glog.Errorln(err)
|
||||||
return err
|
return err
|
||||||
@@ -257,7 +257,7 @@ func CreateKubeConfig(user string) error {
|
|||||||
|
|
||||||
func GetKubeConfig(user string) (string, error) {
|
func GetKubeConfig(user string) (string, error) {
|
||||||
k8sClient := client.NewK8sClient()
|
k8sClient := client.NewK8sClient()
|
||||||
configmap, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNameSpace).Get(user, metav1.GetOptions{})
|
configmap, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorln(err)
|
glog.Errorln(err)
|
||||||
return "", err
|
return "", err
|
||||||
@@ -267,7 +267,7 @@ func GetKubeConfig(user string) (string, error) {
|
|||||||
|
|
||||||
func DelKubeConfig(user string) error {
|
func DelKubeConfig(user string) error {
|
||||||
k8sClient := client.NewK8sClient()
|
k8sClient := client.NewK8sClient()
|
||||||
err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNameSpace).Delete(user, &metav1.DeleteOptions{})
|
err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Delete(user, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Errorln(err)
|
glog.Errorln(err)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
"kubesphere.io/kubesphere/pkg/options"
|
"kubesphere.io/kubesphere/pkg/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
const namespace = constants.KubeSphereControlNameSpace
|
const namespace = constants.KubeSphereControlNamespace
|
||||||
|
|
||||||
type kubectlPodInfo struct {
|
type kubectlPodInfo struct {
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import (
|
|||||||
|
|
||||||
"kubesphere.io/kubesphere/pkg/client"
|
"kubesphere.io/kubesphere/pkg/client"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAllRouters() ([]coreV1.Service, error) {
|
func GetAllRouters() ([]coreV1.Service, error) {
|
||||||
@@ -71,37 +72,30 @@ func inArray(val interface{}, array interface{}) (exists bool) {
|
|||||||
func GetAllRoutersOfUser(username string) ([]coreV1.Service, error) {
|
func GetAllRoutersOfUser(username string) ([]coreV1.Service, error) {
|
||||||
|
|
||||||
routers := make([]coreV1.Service, 0)
|
routers := make([]coreV1.Service, 0)
|
||||||
clusterRoles, err := GetClusterRoles(username)
|
|
||||||
|
allNamespace, namespaces, err := iam.GetUserNamespaces(username, v1.PolicyRule{
|
||||||
|
Verbs: []string{"get", "list"},
|
||||||
|
APIGroups: []string{"extensions"},
|
||||||
|
Resources: []string{"ingresses"},
|
||||||
|
})
|
||||||
|
|
||||||
// return by cluster role
|
// return by cluster role
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
return routers, err
|
return routers, err
|
||||||
} else {
|
|
||||||
for _, clusterRole := range clusterRoles {
|
|
||||||
for _, rulePolicy := range clusterRole.Rules {
|
|
||||||
if (inArray(v1.VerbAll, rulePolicy.Verbs) || inArray("view", rulePolicy.Verbs)) &&
|
|
||||||
(inArray(v1.ResourceAll, rulePolicy.Resources) || inArray("namespaces", rulePolicy.Resources)) {
|
|
||||||
return GetAllRouters()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return by role
|
if allNamespace {
|
||||||
roles, err := GetRoles(username)
|
return GetAllRouters()
|
||||||
if err != nil {
|
}
|
||||||
glog.Error(err)
|
|
||||||
return routers, err
|
for _, namespace := range namespaces {
|
||||||
} else {
|
router, err := GetRouter(namespace)
|
||||||
for _, projectRole := range roles {
|
if err != nil {
|
||||||
router, err := GetRouter(projectRole.Namespace)
|
glog.Error(err)
|
||||||
if err != nil {
|
return routers, err
|
||||||
glog.Error(err)
|
} else if router != nil {
|
||||||
return routers, err
|
routers = append(routers, *router)
|
||||||
} else if router != nil {
|
|
||||||
routers = append(routers, *router)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ var (
|
|||||||
func PrintAndExitIfRequested() {
|
func PrintAndExitIfRequested() {
|
||||||
|
|
||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
fmt.Printf("Kubesphere %s\n", constants.APIVERSION)
|
fmt.Printf("Kubesphere %s\n", constants.APIVersion)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user