From dd963c0be46e2b2ffb83ba4e90c8dc990717c26b Mon Sep 17 00:00:00 2001 From: hongming Date: Tue, 16 Apr 2019 15:31:37 +0800 Subject: [PATCH] fix: ks-account abnormal restart Signed-off-by: hongming --- cmd/ks-iam/app/server.go | 4 +- .../caddy-plugin/authenticate/authenticate.go | 1 - .../authentication/authentication.go | 4 + pkg/apiserver/iam/auth.go | 2 + pkg/apiserver/iam/im.go | 22 ++- pkg/apiserver/tenant/tenant.go | 101 ++++++++-- .../clusterrolebinding_controller.go | 8 +- .../namespace/namespace_controller.go | 13 +- .../workspace/workspace_controller.go | 9 +- pkg/models/iam/am.go | 176 +++++++++++------ pkg/models/iam/im.go | 178 +++++------------- pkg/models/iam/policy/policy.go | 5 - pkg/models/kubeconfig/kubeconfig.go | 39 ++-- pkg/models/kubectl/kubectl.go | 47 +++-- pkg/models/metrics/namespaces.go | 2 +- pkg/models/nodes/nodes.go | 6 +- pkg/models/resources/clusterroles.go | 10 +- pkg/models/resources/configmaps.go | 2 +- pkg/models/resources/cronjobs.go | 4 +- pkg/models/resources/daemonsets.go | 2 +- pkg/models/resources/deployments.go | 2 +- pkg/models/resources/ingresses.go | 2 +- pkg/models/resources/jobs.go | 4 +- pkg/models/resources/namespaces.go | 2 +- pkg/models/resources/nodes.go | 2 +- .../resources/persistentvolumeclaims.go | 2 +- pkg/models/resources/pods.go | 14 +- pkg/models/resources/resources.go | 15 +- pkg/models/resources/roles.go | 2 +- pkg/models/resources/s2ibuilder.go | 2 +- pkg/models/resources/s2ibuildertemplate.go | 2 +- pkg/models/resources/s2irun.go | 2 +- pkg/models/resources/secrets.go | 2 +- pkg/models/resources/services.go | 2 +- pkg/models/resources/statefulsets.go | 2 +- pkg/models/resources/storageclasses.go | 2 +- pkg/models/resources/workspaces.go | 2 +- pkg/models/types.go | 6 +- pkg/models/workspaces/workspaces.go | 3 +- pkg/simple/client/ldap/ldapclient.go | 3 + 40 files changed, 394 insertions(+), 314 deletions(-) diff --git a/cmd/ks-iam/app/server.go b/cmd/ks-iam/app/server.go index 29d7deab..050eee43 100644 --- a/cmd/ks-iam/app/server.go +++ b/cmd/ks-iam/app/server.go @@ -67,6 +67,8 @@ func Run(s *options.ServerRunOptions) error { return err } + waitForResourceSync() + err = iam.Init(s.AdminEmail, s.AdminPassword, expireTime) jwtutil.Setup(s.JWTSecret) @@ -74,8 +76,6 @@ func Run(s *options.ServerRunOptions) error { return err } - waitForResourceSync() - container := runtime.Container container.Filter(filter.Logging) diff --git a/pkg/apigateway/caddy-plugin/authenticate/authenticate.go b/pkg/apigateway/caddy-plugin/authenticate/authenticate.go index 696b26bc..985759de 100644 --- a/pkg/apigateway/caddy-plugin/authenticate/authenticate.go +++ b/pkg/apigateway/caddy-plugin/authenticate/authenticate.go @@ -72,7 +72,6 @@ func (h Auth) ServeHTTP(resp http.ResponseWriter, req *http.Request) (int, error token, err := h.Validate(uToken) if err != nil { - log.Println(uToken) return h.HandleUnauthorized(resp, err), nil } diff --git a/pkg/apigateway/caddy-plugin/authentication/authentication.go b/pkg/apigateway/caddy-plugin/authentication/authentication.go index 3270106d..6b279920 100644 --- a/pkg/apigateway/caddy-plugin/authentication/authentication.go +++ b/pkg/apigateway/caddy-plugin/authentication/authentication.go @@ -24,6 +24,7 @@ import ( "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/request" "kubesphere.io/kubesphere/pkg/utils/k8sutil" + "log" "net/http" "strings" @@ -82,6 +83,7 @@ func (c Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, func handleForbidden(w http.ResponseWriter, err error) int { message := fmt.Sprintf("Forbidden,%s", err.Error()) w.Header().Add("WWW-Authenticate", message) + log.Println(message) return http.StatusForbidden } @@ -94,6 +96,7 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) { permitted, err := clusterRoleValidate(attrs) if err != nil { + log.Println("lister error", err) return false, err } @@ -105,6 +108,7 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) { permitted, err = roleValidate(attrs) if err != nil { + log.Println("lister error", err) return false, err } diff --git a/pkg/apiserver/iam/auth.go b/pkg/apiserver/iam/auth.go index 00064f64..2d463f17 100644 --- a/pkg/apiserver/iam/auth.go +++ b/pkg/apiserver/iam/auth.go @@ -20,6 +20,7 @@ package iam import ( "github.com/dgrijalva/jwt-go" "github.com/emicklei/go-restful" + "github.com/golang/glog" "kubesphere.io/kubesphere/pkg/utils/iputil" "kubesphere.io/kubesphere/pkg/utils/jwtutil" "net/http" @@ -97,6 +98,7 @@ func TokenReviewHandler(req *restful.Request, resp *restful.Response) { token, err := jwtutil.ValidateToken(uToken) if err != nil { + glog.Errorln("token review failed", uToken, err) failed := TokenReview{APIVersion: APIVersion, Kind: KindTokenReview, Status: &Status{ diff --git a/pkg/apiserver/iam/im.go b/pkg/apiserver/iam/im.go index 8caacea3..aca828a5 100644 --- a/pkg/apiserver/iam/im.go +++ b/pkg/apiserver/iam/im.go @@ -26,7 +26,7 @@ import ( "github.com/emicklei/go-restful" "github.com/go-ldap/ldap" - + rbacv1 "k8s.io/api/rbac/v1" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/errors" "kubesphere.io/kubesphere/pkg/models" @@ -126,7 +126,14 @@ func UpdateUser(req *restful.Request, resp *restful.Response) { // change password by self if usernameInHeader == user.Username && user.Password != "" { - _, err = iam.Login(usernameInHeader, user.CurrentPassword, "") + isUserManager, err := isUserManager(usernameInHeader) + if err != nil { + resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err)) + return + } + if !isUserManager { + _, err = iam.Login(usernameInHeader, user.CurrentPassword, "") + } if err != nil { resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("incorrect current password"))) return @@ -143,6 +150,17 @@ func UpdateUser(req *restful.Request, resp *restful.Response) { resp.WriteAsJson(result) } +func isUserManager(username string) (bool, error) { + rules, err := iam.GetUserClusterRules(username) + if err != nil { + return false, err + } + if iam.RulesMatchesRequired(rules, rbacv1.PolicyRule{Verbs: []string{"update"}, Resources: []string{"users"}, APIGroups: []string{"iam.kubesphere.io"}}) { + return true, nil + } + return false, nil +} + func UserLoginLog(req *restful.Request, resp *restful.Response) { username := req.PathParameter("name") logs, err := iam.LoginLog(username) diff --git a/pkg/apiserver/tenant/tenant.go b/pkg/apiserver/tenant/tenant.go index 1d3860d0..050cc57e 100644 --- a/pkg/apiserver/tenant/tenant.go +++ b/pkg/apiserver/tenant/tenant.go @@ -18,7 +18,6 @@ package tenant import ( - "fmt" "github.com/emicklei/go-restful" "github.com/golang/glog" "k8s.io/api/core/v1" @@ -31,11 +30,14 @@ import ( "kubesphere.io/kubesphere/pkg/errors" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models/iam" + "kubesphere.io/kubesphere/pkg/models/metrics" "kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/models/tenant" "kubesphere.io/kubesphere/pkg/models/workspaces" "kubesphere.io/kubesphere/pkg/params" + "kubesphere.io/kubesphere/pkg/simple/client/elasticsearch" "kubesphere.io/kubesphere/pkg/simple/client/kubesphere" + "kubesphere.io/kubesphere/pkg/utils/sliceutil" "net/http" "strings" ) @@ -123,6 +125,22 @@ func ListNamespaces(req *restful.Request, resp *restful.Response) { return } + namespaces := make([]*v1.Namespace, 0) + + for _, item := range result.Items { + namespaces = append(namespaces, item.(*v1.Namespace).DeepCopy()) + } + + namespaces = metrics.GetNamespacesWithMetrics(namespaces) + + items := make([]interface{}, 0) + + for _, item := range namespaces { + items = append(items, item) + } + + result.Items = items + resp.WriteAsJson(result) } @@ -298,37 +316,84 @@ func LogQuery(req *restful.Request, resp *restful.Response) { username := req.HeaderParameter(constants.UserNameHeader) - mapping, err := iam.GetUserWorkspaceRoleMap(username) - if err != nil { - resp.WriteError(http.StatusInternalServerError, err) - glog.Errorln(err) - return - } - - workspaces := make([]string, 0) - for workspaceName, role := range mapping { - if role == fmt.Sprintf("workspace:%s:admin", workspaceName) { - workspaces = append(workspaces, workspaceName) - } - } - // regenerate the request for log query newUrl := net.FormatURL("http", "127.0.0.1", 80, "/kapis/logging.kubesphere.io/v1alpha2/cluster") values := req.Request.URL.Query() - rules, err := iam.GetUserClusterRules(username) + clusterRules, err := iam.GetUserClusterRules(username) if err != nil { resp.WriteError(http.StatusInternalServerError, err) glog.Errorln(err) return } - if !iam.RulesMatchesRequired(rules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}}) { - values.Set("workspaces", strings.Join(workspaces, ",")) + hasClusterLogAccess := iam.RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}}) + // if the user is not a cluster admin + if !hasClusterLogAccess { + queryNamespaces := strings.Split(req.QueryParameter("namespaces"), ",") + // then the user can only view logs of namespaces he belongs to + namespaces := make([]string, 0) + roles, err := iam.GetUserRoles("", username) + if err != nil { + resp.WriteError(http.StatusInternalServerError, err) + glog.Errorln(err) + } + for _, role := range roles { + if !sliceutil.HasString(namespaces, role.Namespace) && iam.RulesMatchesRequired(role.Rules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}}) { + namespaces = append(namespaces, role.Namespace) + } + } + + // if the user belongs to no namespace + // then no log visible + if len(namespaces) == 0 { + res := esclient.QueryResult{Status: http.StatusOK} + resp.WriteAsJson(res) + return + } else if len(queryNamespaces) == 1 && queryNamespaces[0] == "" { + values.Set("namespaces", strings.Join(namespaces, ",")) + } else { + inter := intersection(queryNamespaces, namespaces) + if len(inter) == 0 { + res := esclient.QueryResult{Status: http.StatusOK} + resp.WriteAsJson(res) + return + } + values.Set("namespaces", strings.Join(inter, ",")) + } } + newUrl.RawQuery = values.Encode() // forward the request to logging model newHttpRequest, _ := http.NewRequest(http.MethodGet, newUrl.String(), nil) logging.LoggingQueryCluster(restful.NewRequest(newHttpRequest), resp) } + +func intersection(s1, s2 []string) (inter []string) { + hash := make(map[string]bool) + for _, e := range s1 { + hash[e] = true + } + for _, e := range s2 { + // If elements present in the hashmap then append intersection list. + if hash[e] { + inter = append(inter, e) + } + } + //Remove dups from slice. + inter = removeDups(inter) + return +} + +//Remove dups from slice. +func removeDups(elements []string) (nodups []string) { + encountered := make(map[string]bool) + for _, element := range elements { + if !encountered[element] { + nodups = append(nodups, element) + encountered[element] = true + } + } + return +} diff --git a/pkg/controller/clusterrolebinding/clusterrolebinding_controller.go b/pkg/controller/clusterrolebinding/clusterrolebinding_controller.go index e720599d..1ce0cc06 100644 --- a/pkg/controller/clusterrolebinding/clusterrolebinding_controller.go +++ b/pkg/controller/clusterrolebinding/clusterrolebinding_controller.go @@ -142,9 +142,11 @@ func (r *ReconcileClusterRoleBinding) updateRoleBindings(clusterRoleBinding *rba log.Info("Creating default role binding", "namespace", namespace.Name, "name", adminBinding.Name) err = r.Create(context.TODO(), adminBinding) if err != nil { - return err + log.Error(err, "default role binding create failed", "namespace", namespace.Name, "name", adminBinding.Name) } + return err } else if err != nil { + log.Error(err, "default role binding not found", "namespace", namespace.Name, "name", adminBinding.Name) return err } @@ -182,9 +184,7 @@ func (r *ReconcileClusterRoleBinding) updateRoleBindings(clusterRoleBinding *rba if errors.IsNotFound(err) { log.Info("Creating default role binding", "namespace", namespace.Name, "name", viewerBinding.Name) err = r.Create(context.TODO(), viewerBinding) - if err != nil { - return err - } + return err } else if err != nil { return err } diff --git a/pkg/controller/namespace/namespace_controller.go b/pkg/controller/namespace/namespace_controller.go index 2661e548..45b21cb7 100644 --- a/pkg/controller/namespace/namespace_controller.go +++ b/pkg/controller/namespace/namespace_controller.go @@ -232,6 +232,7 @@ func (r *ReconcileNamespace) checkAndCreateRoleBindings(namespace *corev1.Namesp if err != nil { return err } + found = adminBinding } else if err != nil { return err } @@ -276,6 +277,7 @@ func (r *ReconcileNamespace) checkAndCreateRoleBindings(namespace *corev1.Namesp if err != nil { return err } + found = viewerBinding } else if err != nil { return err } @@ -309,7 +311,8 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace) } cm := &corev1.ConfigMap{} - err := r.Get(context.TODO(), types.NamespacedName{Namespace: constants.KubeSphereControlNamespace, Name: constants.AdminUserName}, cm) + configName := fmt.Sprintf("kubeconfig-%s", constants.AdminUserName) + err := r.Get(context.TODO(), types.NamespacedName{Namespace: constants.KubeSphereControlNamespace, Name: configName}, cm) if err != nil { return err @@ -353,12 +356,8 @@ func (r *ReconcileNamespace) checkAndBindWorkspace(namespace *corev1.Namespace) if err != nil { if errors.IsNotFound(err) { - log.Error(err, "namespace", namespace.Name) - delete(namespace.Labels, constants.WorkspaceLabelKey) - err = r.Update(context.TODO(), namespace) - if err != nil { - return err - } + log.Error(err, fmt.Sprintf("namespace %s bind workspace %s but not found", namespace.Name, workspaceName)) + return nil } return err } diff --git a/pkg/controller/workspace/workspace_controller.go b/pkg/controller/workspace/workspace_controller.go index a897214e..dc059835 100644 --- a/pkg/controller/workspace/workspace_controller.go +++ b/pkg/controller/workspace/workspace_controller.go @@ -188,9 +188,10 @@ func (r *ReconcileWorkspace) createWorkspaceAdmin(instance *tenantv1alpha1.Works } // Update the found object and write the result back if there are any changes - if !reflect.DeepEqual(admin.Rules, found.Rules) || !reflect.DeepEqual(admin.Labels, found.Labels) { + if !reflect.DeepEqual(admin.Rules, found.Rules) || !reflect.DeepEqual(admin.Labels, found.Labels) || !reflect.DeepEqual(admin.Annotations, found.Annotations) { found.Rules = admin.Rules found.Labels = admin.Labels + found.Annotations = admin.Annotations log.Info("Updating workspace role", "workspace", instance.Name, "name", admin.Name) err = r.Update(context.TODO(), found) if err != nil { @@ -226,9 +227,10 @@ func (r *ReconcileWorkspace) createWorkspaceRegular(instance *tenantv1alpha1.Wor } // Update the found object and write the result back if there are any changes - if !reflect.DeepEqual(regular.Rules, found.Rules) || !reflect.DeepEqual(regular.Labels, found.Labels) { + if !reflect.DeepEqual(regular.Rules, found.Rules) || !reflect.DeepEqual(regular.Labels, found.Labels) || !reflect.DeepEqual(regular.Annotations, found.Annotations) { found.Rules = regular.Rules found.Labels = regular.Labels + found.Annotations = regular.Annotations log.Info("Updating workspace role", "workspace", instance.Name, "name", regular.Name) err = r.Update(context.TODO(), found) if err != nil { @@ -264,9 +266,10 @@ func (r *ReconcileWorkspace) createWorkspaceViewer(instance *tenantv1alpha1.Work } // Update the found object and write the result back if there are any changes - if !reflect.DeepEqual(viewer.Rules, found.Rules) || !reflect.DeepEqual(viewer.Labels, found.Labels) { + if !reflect.DeepEqual(viewer.Rules, found.Rules) || !reflect.DeepEqual(viewer.Labels, found.Labels) || !reflect.DeepEqual(viewer.Annotations, found.Annotations) { found.Rules = viewer.Rules found.Labels = viewer.Labels + found.Annotations = viewer.Annotations log.Info("Updating workspace role", "workspace", instance.Name, "name", viewer.Name) err = r.Update(context.TODO(), found) if err != nil { diff --git a/pkg/models/iam/am.go b/pkg/models/iam/am.go index 22750edf..ab2a895b 100644 --- a/pkg/models/iam/am.go +++ b/pkg/models/iam/am.go @@ -19,10 +19,19 @@ package iam import ( "fmt" + "github.com/go-ldap/ldap" "github.com/golang/glog" + rbacv1 "k8s.io/api/rbac/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" + "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" + "kubesphere.io/kubesphere/pkg/models" + "kubesphere.io/kubesphere/pkg/models/iam/policy" + "kubesphere.io/kubesphere/pkg/models/kubeconfig" + "kubesphere.io/kubesphere/pkg/models/kubectl" "kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/params" "kubesphere.io/kubesphere/pkg/simple/client/k8s" @@ -31,22 +40,19 @@ import ( "kubesphere.io/kubesphere/pkg/utils/sliceutil" "sort" "strings" - - "github.com/go-ldap/ldap" - "k8s.io/api/rbac/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "kubesphere.io/kubesphere/pkg/constants" - "kubesphere.io/kubesphere/pkg/models" - "kubesphere.io/kubesphere/pkg/models/iam/policy" ) -const ClusterRoleKind = "ClusterRole" +const ( + ClusterRoleKind = "ClusterRole" + NamespaceAdminRoleBindName = "admin" + NamespaceViewerRoleBindName = "viewer" +) func GetUserDevopsSimpleRules(username, projectId string) ([]models.SimpleRule, error) { role, err := kubesphere.Client().GetUserDevopsRole(username, projectId) if err != nil { + glog.Errorln("get user devops role", username, projectId, err) return nil, err } @@ -98,17 +104,18 @@ func GetDevopsRoleSimpleRules(role string) []models.SimpleRule { } // Get user roles in namespace -func GetUserRoles(namespace, username string) ([]*v1.Role, error) { +func GetUserRoles(namespace, username string) ([]*rbacv1.Role, error) { clusterRoleLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister() roleBindingLister := informers.SharedInformerFactory().Rbac().V1().RoleBindings().Lister() roleLister := informers.SharedInformerFactory().Rbac().V1().Roles().Lister() roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything()) if err != nil { + glog.Errorln("get role bindings", namespace, err) return nil, err } - roles := make([]*v1.Role, 0) + roles := make([]*rbacv1.Role, 0) for _, roleBinding := range roleBindings { if k8sutil.ContainsUser(roleBinding.Subjects, username) { @@ -119,10 +126,11 @@ func GetUserRoles(namespace, username string) ([]*v1.Role, error) { glog.Warningf("cluster role %s not found but bind user %s in namespace %s", roleBinding.RoleRef.Name, username, namespace) continue } else { + glog.Errorln("get cluster role", roleBinding.RoleRef.Name, err) return nil, err } } - role := v1.Role{} + role := rbacv1.Role{} role.TypeMeta = clusterRole.TypeMeta role.ObjectMeta = clusterRole.ObjectMeta role.Rules = clusterRole.Rules @@ -133,9 +141,10 @@ func GetUserRoles(namespace, username string) ([]*v1.Role, error) { if err != nil { if apierrors.IsNotFound(err) { - glog.Warningf("role %s not found but bind user %s in namespace %s", roleBinding.RoleRef.Name, username, namespace) + glog.Warningf("namespace %s role %s not found, but bind user %s", namespace, roleBinding.RoleRef.Name, username) continue } else { + glog.Errorln("get role", roleBinding.Namespace, roleBinding.RoleRef.Name, err) return nil, err } } @@ -147,17 +156,18 @@ func GetUserRoles(namespace, username string) ([]*v1.Role, error) { return roles, nil } -func GetUserClusterRoles(username string) (*v1.ClusterRole, []*v1.ClusterRole, error) { +func GetUserClusterRoles(username string) (*rbacv1.ClusterRole, []*rbacv1.ClusterRole, error) { clusterRoleLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister() clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything()) if err != nil { + glog.Errorln("get cluster role bindings", err) return nil, nil, err } - clusterRoles := make([]*v1.ClusterRole, 0) - userFacingClusterRole := &v1.ClusterRole{} + clusterRoles := make([]*rbacv1.ClusterRole, 0) + userFacingClusterRole := &rbacv1.ClusterRole{} for _, clusterRoleBinding := range clusterRoleBindings { if k8sutil.ContainsUser(clusterRoleBinding.Subjects, username) { clusterRole, err := clusterRoleLister.Get(clusterRoleBinding.RoleRef.Name) @@ -166,6 +176,7 @@ func GetUserClusterRoles(username string) (*v1.ClusterRole, []*v1.ClusterRole, e glog.Warningf("cluster role %s not found but bind user %s", clusterRoleBinding.RoleRef.Name, username) continue } else { + glog.Errorln("get cluster role", clusterRoleBinding.RoleRef.Name, err) return nil, nil, err } } @@ -179,7 +190,7 @@ func GetUserClusterRoles(username string) (*v1.ClusterRole, []*v1.ClusterRole, e return userFacingClusterRole, clusterRoles, nil } -func GetUserClusterRole(username string) (*v1.ClusterRole, error) { +func GetUserClusterRole(username string) (*rbacv1.ClusterRole, error) { userFacingClusterRole, _, err := GetUserClusterRoles(username) if err != nil { return nil, err @@ -187,14 +198,14 @@ func GetUserClusterRole(username string) (*v1.ClusterRole, error) { return userFacingClusterRole, nil } -func GetUserClusterRules(username string) ([]v1.PolicyRule, error) { +func GetUserClusterRules(username string) ([]rbacv1.PolicyRule, error) { _, clusterRoles, err := GetUserClusterRoles(username) if err != nil { return nil, err } - rules := make([]v1.PolicyRule, 0) + rules := make([]rbacv1.PolicyRule, 0) for _, clusterRole := range clusterRoles { rules = append(rules, clusterRole.Rules...) } @@ -202,14 +213,14 @@ func GetUserClusterRules(username string) ([]v1.PolicyRule, error) { return rules, nil } -func GetUserRules(namespace, username string) ([]v1.PolicyRule, error) { +func GetUserRules(namespace, username string) ([]rbacv1.PolicyRule, error) { roles, err := GetUserRoles(namespace, username) if err != nil { return nil, err } - rules := make([]v1.PolicyRule, 0) + rules := make([]rbacv1.PolicyRule, 0) for _, role := range roles { rules = append(rules, role.Rules...) } @@ -217,15 +228,16 @@ func GetUserRules(namespace, username string) ([]v1.PolicyRule, error) { return rules, nil } -func GetWorkspaceRoleBindings(workspace string) ([]*v1.ClusterRoleBinding, error) { +func GetWorkspaceRoleBindings(workspace string) ([]*rbacv1.ClusterRoleBinding, error) { clusterRoleBindings, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister().List(labels.Everything()) if err != nil { + glog.Errorln("get cluster role bindings", err) return nil, err } - result := make([]*v1.ClusterRoleBinding, 0) + result := make([]*rbacv1.ClusterRoleBinding, 0) for _, roleBinding := range clusterRoleBindings { if k8sutil.IsControlledBy(roleBinding.OwnerReferences, "Workspace", workspace) { @@ -236,7 +248,7 @@ func GetWorkspaceRoleBindings(workspace string) ([]*v1.ClusterRoleBinding, error return result, nil } -func GetWorkspaceRole(workspace, role string) (*v1.ClusterRole, error) { +func GetWorkspaceRole(workspace, role string) (*rbacv1.ClusterRole, error) { if !sliceutil.HasString(constants.WorkSpaceRoles, role) { return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "workspace role"}, role) } @@ -249,6 +261,7 @@ func GetUserWorkspaceRoleMap(username string) (map[string]string, error) { clusterRoleBindings, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister().List(labels.Everything()) if err != nil { + glog.Errorln("get cluster role bindings", err) return nil, err } @@ -264,7 +277,7 @@ func GetUserWorkspaceRoleMap(username string) (map[string]string, error) { return result, nil } -func GetUserWorkspaceRole(workspace, username string) (*v1.ClusterRole, error) { +func GetUserWorkspaceRole(workspace, username string) (*rbacv1.ClusterRole, error) { workspaceRoleMap, err := GetUserWorkspaceRoleMap(username) if err != nil { @@ -278,15 +291,16 @@ func GetUserWorkspaceRole(workspace, username string) (*v1.ClusterRole, error) { return nil, apierrors.NewNotFound(schema.GroupResource{Resource: "workspace user"}, username) } -func GetRoleBindings(namespace string, roleName string) ([]*v1.RoleBinding, error) { +func GetRoleBindings(namespace string, roleName string) ([]*rbacv1.RoleBinding, error) { roleBindingLister := informers.SharedInformerFactory().Rbac().V1().RoleBindings().Lister() roleBindings, err := roleBindingLister.RoleBindings(namespace).List(labels.Everything()) if err != nil { + glog.Errorln("get role bindings", namespace, err) return nil, err } - items := make([]*v1.RoleBinding, 0) + items := make([]*rbacv1.RoleBinding, 0) for _, roleBinding := range roleBindings { if roleName == "" { @@ -299,15 +313,16 @@ func GetRoleBindings(namespace string, roleName string) ([]*v1.RoleBinding, erro return items, nil } -func GetClusterRoleBindings(clusterRoleName string) ([]*v1.ClusterRoleBinding, error) { +func GetClusterRoleBindings(clusterRoleName string) ([]*rbacv1.ClusterRoleBinding, error) { clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() roleBindings, err := clusterRoleBindingLister.List(labels.Everything()) if err != nil { + glog.Errorln("get cluster role bindings", err) return nil, err } - items := make([]*v1.ClusterRoleBinding, 0) + items := make([]*rbacv1.ClusterRoleBinding, 0) for _, roleBinding := range roleBindings { if roleBinding.RoleRef.Name == clusterRoleName { @@ -328,12 +343,13 @@ func ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions, users := make([]*models.User, 0) for _, roleBinding := range roleBindings { for _, subject := range roleBinding.Subjects { - if subject.Kind == v1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { + if subject.Kind == rbacv1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { user, err := GetUserInfo(subject.Name) if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) { continue } if err != nil { + glog.Errorln("get user info", subject.Name, err) return nil, err } users = append(users, user) @@ -351,7 +367,7 @@ func ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions, switch orderBy { default: fallthrough - case "name": + case resources.Name: return strings.Compare(users[i].Username, users[j].Username) <= 0 } }) @@ -378,7 +394,7 @@ func RoleUsers(namespace string, roleName string) ([]*models.User, error) { users := make([]*models.User, 0) for _, roleBinding := range roleBindings { for _, subject := range roleBinding.Subjects { - if subject.Kind == v1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { + if subject.Kind == rbacv1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { user, err := GetUserInfo(subject.Name) if err != nil { @@ -402,8 +418,8 @@ func ListRoles(namespace string, conditions *params.Conditions, orderBy string, } func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { - conditions.Match["ownerName"] = workspace - conditions.Match["ownerKind"] = "Workspace" + conditions.Match[resources.OwnerName] = workspace + conditions.Match[resources.OwnerKind] = "Workspace" result, err := resources.ListResources("", resources.ClusterRoles, conditions, orderBy, reverse, limit, offset) if err != nil { @@ -411,7 +427,7 @@ func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy } for i, item := range result.Items { - if role, ok := item.(*v1.ClusterRole); ok { + if role, ok := item.(*rbacv1.ClusterRole); ok { role = role.DeepCopy() role.Name = role.Annotations[constants.DisplayNameAnnotationKey] result.Items[i] = role @@ -425,6 +441,11 @@ func ListClusterRoles(conditions *params.Conditions, orderBy string, reverse boo } func NamespaceUsers(namespaceName string) ([]*models.User, error) { + namespace, err := informers.SharedInformerFactory().Core().V1().Namespaces().Lister().Get(namespaceName) + if err != nil { + glog.Errorln("get namespace", namespaceName, err) + return nil, err + } roleBindings, err := GetRoleBindings(namespaceName, "") if err != nil { @@ -435,11 +456,16 @@ func NamespaceUsers(namespaceName string) ([]*models.User, error) { for _, roleBinding := range roleBindings { // controlled by ks-controller-manager - if roleBinding.Name == "admin" || roleBinding.Name == "viewer" { + if roleBinding.Name == NamespaceViewerRoleBindName { continue } for _, subject := range roleBinding.Subjects { - if subject.Kind == v1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { + if subject.Kind == rbacv1.UserKind && !k8sutil.ContainsUser(users, subject.Name) { + + // show creator + if roleBinding.Name == NamespaceAdminRoleBindName && subject.Name != namespace.Annotations[constants.CreatorLabelAnnotationKey] { + continue + } user, err := GetUserInfo(subject.Name) @@ -466,6 +492,7 @@ func GetUserWorkspaceSimpleRules(workspace, username string) ([]models.SimpleRul if err != nil { return nil, err } + if workspacesManager, err := policy.GetClusterAction("workspaces", "edit"); err == nil { if rulesMatchesAction(clusterRules, workspacesManager) { return GetWorkspaceRoleSimpleRules(workspace, constants.WorkspaceAdmin), nil @@ -475,6 +502,9 @@ func GetUserWorkspaceSimpleRules(workspace, username string) ([]models.SimpleRul workspaceRole, err := GetUserWorkspaceRole(workspace, username) if err != nil { + if apierrors.IsNotFound(err) { + return []models.SimpleRule{}, nil + } return nil, err } return GetWorkspaceRoleSimpleRules(workspace, workspaceRole.Annotations[constants.DisplayNameAnnotationKey]), nil @@ -523,6 +553,7 @@ func GetClusterRoleSimpleRules(clusterRoleName string) ([]models.SimpleRule, err clusterRole, err := clusterRoleLister.Get(clusterRoleName) if err != nil { + glog.Errorln("get cluster role", clusterRoleName, clusterRoleName) return nil, err } @@ -558,13 +589,14 @@ func GetRoleSimpleRules(namespace string, roleName string) ([]models.SimpleRule, role, err := roleLister.Roles(namespace).Get(roleName) if err != nil { + glog.Errorln("get role", namespace, roleName, err) return nil, err } return getSimpleRule(role.Rules), nil } -func getClusterSimpleRule(policyRules []v1.PolicyRule) []models.SimpleRule { +func getClusterSimpleRule(policyRules []rbacv1.PolicyRule) []models.SimpleRule { rules := make([]models.SimpleRule, 0) for i := 0; i < len(policy.ClusterRoleRuleMapping); i++ { @@ -582,7 +614,7 @@ func getClusterSimpleRule(policyRules []v1.PolicyRule) []models.SimpleRule { return rules } -func getSimpleRule(policyRules []v1.PolicyRule) []models.SimpleRule { +func getSimpleRule(policyRules []rbacv1.PolicyRule) []models.SimpleRule { simpleRules := make([]models.SimpleRule, 0) for i := 0; i < len(policy.RoleRuleMapping); i++ { rule := models.SimpleRule{Name: policy.RoleRuleMapping[i].Name} @@ -605,46 +637,76 @@ func CreateClusterRoleBinding(username string, clusterRoleName string) error { _, err := clusterRoleLister.Get(clusterRoleName) if err != nil { + glog.Errorln("get cluster role", clusterRoleName, err) return err } - clusterRoleBinding := &v1.ClusterRoleBinding{} + clusterRoleBinding := &rbacv1.ClusterRoleBinding{} clusterRoleBinding.Name = username - clusterRoleBinding.RoleRef = v1.RoleRef{Name: clusterRoleName, Kind: ClusterRoleKind} - clusterRoleBinding.Subjects = []v1.Subject{{Kind: v1.UserKind, Name: username}} + clusterRoleBinding.RoleRef = rbacv1.RoleRef{Name: clusterRoleName, Kind: ClusterRoleKind} + clusterRoleBinding.Subjects = []rbacv1.Subject{{Kind: rbacv1.UserKind, Name: username}} clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() found, err := clusterRoleBindingLister.Get(username) if apierrors.IsNotFound(err) { _, err = k8s.Client().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding) - return err + if err != nil { + glog.Errorln("create cluster role binding", err) + return err + } + if clusterRoleName == constants.ClusterAdmin { + if err := kubeconfig.CreateKubeConfig(username); err != nil { + glog.Errorln("create user kubeconfig failed", username, err) + } + if err := kubectl.CreateKubectlDeploy(username); err != nil { + glog.Errorln("create user terminal pod failed", username, err) + } + } + return nil } else if err != nil { return err } // cluster role changed - if found.RoleRef.Name != clusterRoleBinding.RoleRef.Name { + if found.RoleRef.Name != clusterRoleName { deletePolicy := metav1.DeletePropagationForeground - deleteOption := &metav1.DeleteOptions{PropagationPolicy: &deletePolicy} - err := k8s.Client().RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, deleteOption) + gracePeriodSeconds := int64(0) + deleteOption := &metav1.DeleteOptions{PropagationPolicy: &deletePolicy, GracePeriodSeconds: &gracePeriodSeconds} + err = k8s.Client().RbacV1().ClusterRoleBindings().Delete(found.Name, deleteOption) if err != nil { + glog.Errorln("delete cluster role binding", err) return err } + if found.RoleRef.Name == constants.ClusterAdmin { + if err := kubeconfig.DelKubeConfig(username); err != nil { + glog.Error("delete user kubeconfig failed", username, err) + } + if err := kubectl.DelKubectlDeploy(username); err != nil { + glog.Error("delete user terminal pod failed", username, err) + } + } _, err = k8s.Client().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding) - return err + if err != nil { + glog.Errorln("create cluster role binding", err) + return err + } + return nil } if !k8sutil.ContainsUser(found.Subjects, username) { found.Subjects = clusterRoleBinding.Subjects _, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(found) - return err + if err != nil { + glog.Errorln("update cluster role binding", err) + return err + } } return nil } -func RulesMatchesRequired(rules []v1.PolicyRule, required v1.PolicyRule) bool { +func RulesMatchesRequired(rules []rbacv1.PolicyRule, required rbacv1.PolicyRule) bool { for _, rule := range rules { if ruleMatchesRequired(rule, required) { return true @@ -653,7 +715,7 @@ func RulesMatchesRequired(rules []v1.PolicyRule, required v1.PolicyRule) bool { return false } -func rulesMatchesAction(rules []v1.PolicyRule, action models.Action) bool { +func rulesMatchesAction(rules []rbacv1.PolicyRule, action models.Action) bool { for _, required := range action.Rules { if !RulesMatchesRequired(rules, required) { @@ -664,7 +726,7 @@ func rulesMatchesAction(rules []v1.PolicyRule, action models.Action) bool { return true } -func ruleMatchesRequired(rule v1.PolicyRule, required v1.PolicyRule) bool { +func ruleMatchesRequired(rule rbacv1.PolicyRule, required rbacv1.PolicyRule) bool { if len(required.NonResourceURLs) == 0 { for _, apiGroup := range required.APIGroups { @@ -707,13 +769,13 @@ func ruleMatchesRequired(rule v1.PolicyRule, required v1.PolicyRule) bool { return true } -func ruleMatchesResources(rule v1.PolicyRule, apiGroup string, resource string, subresource string, resourceName string) bool { +func ruleMatchesResources(rule rbacv1.PolicyRule, apiGroup string, resource string, subresource string, resourceName string) bool { if resource == "" { return false } - if !hasString(rule.APIGroups, apiGroup) && !hasString(rule.APIGroups, v1.ResourceAll) { + if !hasString(rule.APIGroups, apiGroup) && !hasString(rule.APIGroups, rbacv1.ResourceAll) { return false } @@ -730,7 +792,7 @@ func ruleMatchesResources(rule v1.PolicyRule, apiGroup string, resource string, for _, res := range rule.Resources { // match "*" - if res == v1.ResourceAll || res == combinedResource { + if res == rbacv1.ResourceAll || res == combinedResource { return true } @@ -747,9 +809,9 @@ func ruleMatchesResources(rule v1.PolicyRule, apiGroup string, resource string, return false } -func ruleMatchesRequest(rule v1.PolicyRule, apiGroup string, nonResourceURL string, resource string, subresource string, resourceName string, verb string) bool { +func ruleMatchesRequest(rule rbacv1.PolicyRule, apiGroup string, nonResourceURL string, resource string, subresource string, resourceName string, verb string) bool { - if !hasString(rule.Verbs, verb) && !hasString(rule.Verbs, v1.VerbAll) { + if !hasString(rule.Verbs, verb) && !hasString(rule.Verbs, rbacv1.VerbAll) { return false } @@ -760,7 +822,7 @@ func ruleMatchesRequest(rule v1.PolicyRule, apiGroup string, nonResourceURL stri } } -func ruleMatchesNonResource(rule v1.PolicyRule, nonResourceURL string) bool { +func ruleMatchesNonResource(rule rbacv1.PolicyRule, nonResourceURL string) bool { if nonResourceURL == "" { return false diff --git a/pkg/models/iam/im.go b/pkg/models/iam/im.go index 3a5aa41e..2d9f7c7f 100644 --- a/pkg/models/iam/im.go +++ b/pkg/models/iam/im.go @@ -18,8 +18,10 @@ package iam import ( + "encoding/json" "errors" "fmt" + "io/ioutil" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/params" @@ -51,6 +53,10 @@ var ( tokenExpireTime time.Duration ) +const ( + userInitFile = "/etc/ks-iam/users.json" +) + func Init(email, password string, t time.Duration) error { adminEmail = email adminPassword = password @@ -67,12 +73,18 @@ func Init(email, password string, t time.Duration) error { err = checkAndCreateDefaultUser(conn) if err != nil { + glog.Errorln("create default users", err) return err } err = checkAndCreateDefaultGroup(conn) - return err + if err != nil { + glog.Errorln("create default groups", err) + return err + } + + return nil } func checkAndCreateDefaultGroup(conn ldap.Client) error { @@ -124,10 +136,19 @@ func checkAndCreateDefaultUser(conn ldap.Client) error { return fmt.Errorf("iam database init failed: %s\n", err) } - if users == nil || len(users.Entries) == 0 { - _, err := CreateUser(&models.User{Username: constants.AdminUserName, Email: adminEmail, Password: adminPassword, Description: "Administrator account that was always created by default."}) - if err != nil { - return fmt.Errorf("admin create failed: %s\n", err) + data, err := ioutil.ReadFile(userInitFile) + var initUsers []models.User + if err == nil { + json.Unmarshal(data, &initUsers) + } + initUsers = append(initUsers, models.User{Username: constants.AdminUserName, Email: adminEmail, Password: adminPassword, Description: "Administrator account that was always created by default.", ClusterRole: constants.ClusterAdmin}) + + if users == nil || len(users.Entries) < len(initUsers) { + for _, user := range initUsers { + _, err = CreateUser(&user) + if err != nil && !ldap.IsErrorWithCode(err, ldap.LDAPResultEntryAlreadyExists) { + return fmt.Errorf("user %s init failed: %s\n", user.Username, err) + } } } @@ -192,6 +213,7 @@ func Login(username string, password string, ip string) (*models.Token, error) { err = conn.Bind(dn, password) if err != nil { + glog.Errorln("auth error", username, err) return nil, err } @@ -228,55 +250,6 @@ func LoginLog(username string) ([]string, error) { return data, nil } -func ListUsersByName(names []string) (*models.PageableResponse, error) { - users := make([]*models.User, 0) - - for _, name := range names { - if !k8sutil.ContainsUser(users, name) { - user, err := GetUserInfo(name) - if err != nil { - if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) { - continue - } - return nil, err - } - users = append(users, user) - } - } - - items := make([]interface{}, 0) - - for _, u := range users { - items = append(items, u) - } - - return &models.PageableResponse{Items: items, TotalCount: len(items)}, nil -} - -func ListUserByEmail(email []string) (*models.PageableResponse, error) { - users := make([]*models.User, 0) - for _, mail := range email { - user, err := GetUserInfoByEmail(mail) - if err != nil { - if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) { - continue - } - return nil, err - } - if !k8sutil.ContainsUser(users, user.Username) { - users = append(users, user) - } - } - - items := make([]interface{}, 0) - - for _, u := range users { - items = append(items, u) - } - - return &models.PageableResponse{Items: items, TotalCount: len(items)}, nil -} - func ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { conn, err := ldapclient.Client() @@ -325,6 +298,7 @@ func ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limi response, err := conn.Search(userSearchRequest) if err != nil { + glog.Errorln("search user", err) return nil, err } @@ -396,55 +370,15 @@ func DescribeUser(username string) (*models.User, error) { groups, err := GetUserGroups(username) - if err != nil { - return nil, err + if err == nil { + user.Groups = groups } - user.Groups = groups user.AvatarUrl = getAvatar(username) return user, nil } -func GetUserInfoByEmail(mail string) (*models.User, error) { - conn, err := ldapclient.Client() - - if err != nil { - return nil, err - } - - userSearchRequest := ldap.NewSearchRequest( - ldapclient.UserSearchBase, - ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, - fmt.Sprintf("(&(objectClass=inetOrgPerson)(mail=%s))", mail), - []string{"uid", "description", "preferredLanguage", "createTimestamp"}, - nil, - ) - - result, err := conn.Search(userSearchRequest) - - if err != nil { - return nil, err - } - - if len(result.Entries) != 1 { - return nil, ldap.NewError(ldap.LDAPResultNoSuchObject, fmt.Errorf("user %s does not exist", mail)) - } - - username := result.Entries[0].GetAttributeValue("uid") - description := result.Entries[0].GetAttributeValue("description") - lang := result.Entries[0].GetAttributeValue("preferredLanguage") - createTimestamp, _ := time.Parse("20060102150405Z", result.Entries[0].GetAttributeValue("createTimestamp")) - user := &models.User{Username: username, Email: mail, Description: description, Lang: lang, CreateTime: createTimestamp} - user.LastLoginTime = getLastLoginTime(username) - clusterRole, err := GetUserClusterRole(user.Username) - if err != nil { - return nil, err - } - user.ClusterRole = clusterRole.Name - return user, nil -} - // Get user info only included email description & lang func GetUserInfo(username string) (*models.User, error) { @@ -465,6 +399,7 @@ func GetUserInfo(username string) (*models.User, error) { result, err := conn.Search(userSearchRequest) if err != nil { + glog.Errorln("search user", err) return nil, err } @@ -567,6 +502,7 @@ func DeleteUser(username string) error { err = conn.Del(deleteRequest) if err != nil { + glog.Errorln("delete user", err) return err } @@ -673,14 +609,11 @@ func UserCreateCheck(check string) (exist bool, err error) { result, err := conn.Search(userSearchRequest) if err != nil { + glog.Errorln("search user", err) return false, err } - if len(result.Entries) > 0 { - return true, nil - } else { - return false, nil - } + return len(result.Entries) > 0, nil } func CreateUser(user *models.User) (*models.User, error) { @@ -708,6 +641,7 @@ func CreateUser(user *models.User) (*models.User, error) { result, err := conn.Search(userSearchRequest) if err != nil { + glog.Errorln("search user", err) return nil, err } @@ -718,6 +652,7 @@ func CreateUser(user *models.User) (*models.User, error) { maxUid, err := getMaxUid(conn) if err != nil { + glog.Errorln("get max uid", err) return nil, err } @@ -743,6 +678,7 @@ func CreateUser(user *models.User) (*models.User, error) { err = conn.Add(userCreateRequest) if err != nil { + glog.Errorln("create user", err) return nil, err } @@ -754,6 +690,7 @@ func CreateUser(user *models.User) (*models.User, error) { err := CreateClusterRoleBinding(user.Username, user.ClusterRole) if err != nil { + glog.Errorln("create cluster role binding filed", err) return nil, err } } @@ -864,6 +801,7 @@ func UpdateUser(user *models.User) (*models.User, error) { err = CreateClusterRoleBinding(user.Username, user.ClusterRole) if err != nil { + glog.Errorln("create cluster role binding filed", err) return nil, err } @@ -884,6 +822,7 @@ func DeleteGroup(path string) error { err = conn.Del(groupDeleteRequest) if err != nil { + glog.Errorln("delete user group", err) return err } @@ -903,6 +842,7 @@ func CreateGroup(group *models.Group) (*models.Group, error) { maxGid, err := getMaxGid(conn) if err != nil { + glog.Errorln("get max gid", err) return nil, err } @@ -930,6 +870,7 @@ func CreateGroup(group *models.Group) (*models.Group, error) { err = conn.Add(groupCreateRequest) if err != nil { + glog.Errorln("create group", err) return nil, err } @@ -976,45 +917,13 @@ func UpdateGroup(group *models.Group) (*models.Group, error) { err = conn.Modify(groupUpdateRequest) if err != nil { + glog.Errorln("update group", err) return nil, err } return group, nil } -func CountChild(path string) (int, error) { - // bind root DN - conn, err := ldapclient.Client() - if err != nil { - return 0, err - } - defer conn.Close() - - var groupSearchRequest *ldap.SearchRequest - if path == "" { - groupSearchRequest = ldap.NewSearchRequest(ldapclient.GroupSearchBase, - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - "(&(objectClass=posixGroup))", - []string{"cn", "gidNumber", "memberUid", "description"}, - nil) - } else { - searchBase, cn := splitPath(path) - groupSearchRequest = ldap.NewSearchRequest(fmt.Sprintf("cn=%s,%s", cn, searchBase), - ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false, - "(&(objectClass=posixGroup))", - []string{"cn", "gidNumber", "memberUid", "description"}, - nil) - } - - result, err := conn.Search(groupSearchRequest) - - if err != nil { - return 0, err - } - - return len(result.Entries), nil -} - func ChildList(path string) ([]models.Group, error) { // bind root DN @@ -1105,6 +1014,7 @@ func DescribeGroup(path string) (*models.Group, error) { result, err := conn.Search(groupSearchRequest) if err != nil { + glog.Errorln("search group", err) return nil, err } diff --git a/pkg/models/iam/policy/policy.go b/pkg/models/iam/policy/policy.go index 0843ac94..ef6cd7d8 100644 --- a/pkg/models/iam/policy/policy.go +++ b/pkg/models/iam/policy/policy.go @@ -101,11 +101,6 @@ var ( APIGroups: []string{"rbac.authorization.k8s.io"}, Resources: []string{"rolebindings", "roles"}, }, - { - Verbs: []string{"*"}, - APIGroups: []string{"jenkins.kubesphere.io", "devops.kubesphere.io"}, - Resources: []string{"*"}, - }, }, }, }, diff --git a/pkg/models/kubeconfig/kubeconfig.go b/pkg/models/kubeconfig/kubeconfig.go index 64a6e16b..cef159e2 100644 --- a/pkg/models/kubeconfig/kubeconfig.go +++ b/pkg/models/kubeconfig/kubeconfig.go @@ -26,6 +26,7 @@ import ( "crypto/x509/pkix" "encoding/base64" "encoding/pem" + "fmt" "io/ioutil" "kubesphere.io/kubesphere/pkg/simple/client/k8s" "math/big" @@ -208,7 +209,7 @@ func generateCaAndKey(user, caPath, keyPath string) (string, string, error) { return base64Cert, base64Key, nil } -func createKubeConfig(userName string) (string, error) { +func createKubeConfig(username string) (string, error) { tmpKubeConfig := kubeConfig{ApiVersion: "v1", Kind: "Config"} serverCa, err := ioutil.ReadFile(caPath) if err != nil { @@ -220,17 +221,17 @@ func createKubeConfig(userName string) (string, error) { tmpCluster := cluster{Cluster: tmpClusterInfo, Name: clusterName} tmpKubeConfig.Clusters = append(tmpKubeConfig.Clusters, tmpCluster) - contextName := userName + "@" + clusterName - tmpContext := contextObject{Context: contextInfo{User: userName, Cluster: clusterName, NameSpace: defaultNamespace}, Name: contextName} + contextName := username + "@" + clusterName + tmpContext := contextObject{Context: contextInfo{User: username, Cluster: clusterName, NameSpace: defaultNamespace}, Name: contextName} tmpKubeConfig.Contexts = append(tmpKubeConfig.Contexts, tmpContext) - cert, key, err := generateCaAndKey(userName, caPath, keyPath) + cert, key, err := generateCaAndKey(username, caPath, keyPath) if err != nil { return "", err } - tmpUser := user{User: userInfo{CaData: cert, KeyData: key}, Name: userName} + tmpUser := user{User: userInfo{CaData: cert, KeyData: key}, Name: username} tmpKubeConfig.Users = append(tmpKubeConfig.Users, tmpUser) tmpKubeConfig.CurrentContext = contextName @@ -242,23 +243,23 @@ func createKubeConfig(userName string) (string, error) { return string(config), nil } -func CreateKubeConfig(user string) error { +func CreateKubeConfig(username string) error { k8sClient := k8s.Client() - - _, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{}) + configName := fmt.Sprintf("kubeconfig-%s", username) + _, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metaV1.GetOptions{}) if errors.IsNotFound(err) { - config, err := createKubeConfig(user) + config, err := createKubeConfig(username) if err != nil { glog.Errorln(err) return err } data := map[string]string{"config": string(config)} - configMap := v1.ConfigMap{TypeMeta: metaV1.TypeMeta{Kind: "Configmap", APIVersion: "v1"}, ObjectMeta: metaV1.ObjectMeta{Name: user}, Data: data} + configMap := v1.ConfigMap{TypeMeta: metaV1.TypeMeta{Kind: "Configmap", APIVersion: "v1"}, ObjectMeta: metaV1.ObjectMeta{Name: configName}, Data: data} _, err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Create(&configMap) if err != nil && !errors.IsAlreadyExists(err) { - glog.Errorf("create user %s's kubeConfig failed, reason: %v", user, err) + glog.Errorf("create username %s's kubeConfig failed, reason: %v", username, err) return err } } @@ -267,27 +268,29 @@ func CreateKubeConfig(user string) error { } -func GetKubeConfig(user string) (string, error) { +func GetKubeConfig(username string) (string, error) { k8sClient := k8s.Client() - configMap, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{}) + configName := fmt.Sprintf("kubeconfig-%s", username) + configMap, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metaV1.GetOptions{}) if err != nil { - glog.Errorf("cannot get user %s's kubeConfig, reason: %v", user, err) + glog.Errorf("cannot get username %s's kubeConfig, reason: %v", username, err) return "", err } return configMap.Data[kubectlConfigKey], nil } -func DelKubeConfig(user string) error { +func DelKubeConfig(username string) error { k8sClient := k8s.Client() - _, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{}) + configName := fmt.Sprintf("kubeconfig-%s", username) + _, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(configName, metaV1.GetOptions{}) if errors.IsNotFound(err) { return nil } deletePolicy := metaV1.DeletePropagationBackground - err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Delete(user, &metaV1.DeleteOptions{PropagationPolicy: &deletePolicy}) + err = k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Delete(configName, &metaV1.DeleteOptions{PropagationPolicy: &deletePolicy}) if err != nil { - glog.Errorf("delete user %s's kubeConfig failed, reason: %v", user, err) + glog.Errorf("delete username %s's kubeConfig failed, reason: %v", username, err) return err } return nil diff --git a/pkg/models/kubectl/kubectl.go b/pkg/models/kubectl/kubectl.go index d20f9c08..b3cc00a6 100644 --- a/pkg/models/kubectl/kubectl.go +++ b/pkg/models/kubectl/kubectl.go @@ -23,9 +23,10 @@ import ( "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/simple/client/k8s" "math/rand" + "os" "github.com/golang/glog" - "k8s.io/api/apps/v1beta2" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -39,9 +40,18 @@ const ( namespace = constants.KubeSphereControlNamespace ) +var DefaultImage = "kubesphere/kubectl:advanced-1.0.0" + +func init() { + if env := os.Getenv("KUBECTL_IMAGE"); env != "" { + DefaultImage = env + } +} + func GetKubectlPod(username string) (models.PodInfo, error) { k8sClient := k8s.Client() - deploy, err := k8sClient.AppsV1beta2().Deployments(namespace).Get(username, metav1.GetOptions{}) + deployName := fmt.Sprintf("kubectl-%s", username) + deploy, err := k8sClient.AppsV1().Deployments(namespace).Get(deployName, metav1.GetOptions{}) if err != nil { glog.Errorln(err) return models.PodInfo{}, err @@ -86,33 +96,35 @@ func selectCorrectPod(namespace string, pods []v1.Pod) (kubectlPod v1.Pod, err e return kubectlPodList[random], nil } -func CreateKubectlDeploy(user string) error { +func CreateKubectlDeploy(username string) error { k8sClient := k8s.Client() - _, err := k8sClient.AppsV1().Deployments(namespace).Get(user, metav1.GetOptions{}) + deployName := fmt.Sprintf("kubectl-%s", username) + configName := fmt.Sprintf("kubeconfig-%s", username) + _, err := k8sClient.AppsV1().Deployments(namespace).Get(deployName, metav1.GetOptions{}) if err == nil { return nil } replica := int32(1) - selector := metav1.LabelSelector{MatchLabels: map[string]string{"user": user}} - config := v1.ConfigMapVolumeSource{Items: []v1.KeyToPath{{Key: "config", Path: "config"}}, LocalObjectReference: v1.LocalObjectReference{Name: user}} - deployment := v1beta2.Deployment{ + selector := metav1.LabelSelector{MatchLabels: map[string]string{"username": username}} + config := v1.ConfigMapVolumeSource{Items: []v1.KeyToPath{{Key: "config", Path: "config"}}, LocalObjectReference: v1.LocalObjectReference{Name: configName}} + deployment := appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: user, + Name: deployName, }, - Spec: v1beta2.DeploymentSpec{ + Spec: appsv1.DeploymentSpec{ Replicas: &replica, Selector: &selector, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ - "user": user, + "username": username, }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ {Name: "kubectl", - Image: "", + Image: DefaultImage, VolumeMounts: []v1.VolumeMount{{Name: "kubeconfig", MountPath: "/root/.kube"}}, }, }, @@ -122,28 +134,29 @@ func CreateKubectlDeploy(user string) error { }, } - _, err = k8sClient.AppsV1beta2().Deployments(namespace).Create(&deployment) + _, err = k8sClient.AppsV1().Deployments(namespace).Create(&deployment) return err } -func DelKubectlDeploy(user string) error { +func DelKubectlDeploy(username string) error { k8sClient := k8s.Client() - _, err := k8sClient.AppsV1beta2().Deployments(namespace).Get(user, metav1.GetOptions{}) + deployName := fmt.Sprintf("kubectl-%s", username) + _, err := k8sClient.AppsV1().Deployments(namespace).Get(deployName, metav1.GetOptions{}) if errors.IsNotFound(err) { return nil } if err != nil { - err := fmt.Errorf("delete user %s failed, reason:%v", user, err) + err := fmt.Errorf("delete username %s failed, reason:%v", username, err) return err } deletePolicy := metav1.DeletePropagationBackground - err = k8sClient.AppsV1beta2().Deployments(namespace).Delete(user, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) + err = k8sClient.AppsV1().Deployments(namespace).Delete(deployName, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy}) if err != nil { - err := fmt.Errorf("delete user %s failed, reason:%v", user, err) + err := fmt.Errorf("delete username %s failed, reason:%v", username, err) return err } diff --git a/pkg/models/metrics/namespaces.go b/pkg/models/metrics/namespaces.go index 06abbddb..3db24b02 100644 --- a/pkg/models/metrics/namespaces.go +++ b/pkg/models/metrics/namespaces.go @@ -47,7 +47,7 @@ func GetNamespacesWithMetrics(namespaces []*v1.Namespace) []*v1.Namespace { for _, data := range result.Data.Result { metricDescMap, ok := data["metric"].(map[string]interface{}) if ok { - if ns, exist := metricDescMap["namespace"]; exist { + if ns, exist := metricDescMap["resource_name"]; exist { timeAndValue, ok := data["value"].([]interface{}) if ok && len(timeAndValue) == 2 { for i := 0; i < len(namespaces); i++ { diff --git a/pkg/models/nodes/nodes.go b/pkg/models/nodes/nodes.go index ef512997..fdf0d6bc 100644 --- a/pkg/models/nodes/nodes.go +++ b/pkg/models/nodes/nodes.go @@ -25,7 +25,7 @@ import ( "time" "github.com/golang/glog" - "k8s.io/api/apps/v1beta2" + appsv1 "k8s.io/api/apps/v1" "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -78,7 +78,7 @@ func drainEviction(nodename string, donech chan bool, errch chan error) { errch <- err } options.FieldSelector = "" - daemonsetList, err := k8sclient.AppsV1beta2().DaemonSets("").List(options) + daemonsetList, err := k8sclient.AppsV1().DaemonSets("").List(options) if err != nil { @@ -142,7 +142,7 @@ func isMirrorPod(pod *v1.Pod) bool { return ok } -func containDaemonset(pod v1.Pod, daemonsetList v1beta2.DaemonSetList) bool { +func containDaemonset(pod v1.Pod, daemonsetList appsv1.DaemonSetList) bool { flag := false for _, daemonset := range daemonsetList.Items { diff --git a/pkg/models/resources/clusterroles.go b/pkg/models/resources/clusterroles.go index f37de1f2..9bd2fbfb 100644 --- a/pkg/models/resources/clusterroles.go +++ b/pkg/models/resources/clusterroles.go @@ -41,11 +41,11 @@ func (*clusterRoleSearcher) get(namespace, name string) (interface{}, error) { func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool { for k, v := range match { switch k { - case ownerKind: + case OwnerKind: fallthrough - case ownerName: - kind := match[ownerKind] - name := match[ownerName] + case OwnerName: + kind := match[OwnerKind] + name := match[OwnerName] if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) { return false } @@ -81,7 +81,7 @@ func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRol if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/configmaps.go b/pkg/models/resources/configmaps.go index 4e4ed71d..c59b1720 100644 --- a/pkg/models/resources/configmaps.go +++ b/pkg/models/resources/configmaps.go @@ -66,7 +66,7 @@ func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) boo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/cronjobs.go b/pkg/models/resources/cronjobs.go index fe90ad3e..df75876b 100644 --- a/pkg/models/resources/cronjobs.go +++ b/pkg/models/resources/cronjobs.go @@ -78,7 +78,7 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } @@ -103,7 +103,7 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool { switch orderBy { - case lastScheduleTime: + case LastScheduleTime: if a.Status.LastScheduleTime == nil { return true } diff --git a/pkg/models/resources/daemonsets.go b/pkg/models/resources/daemonsets.go index b4e256f9..782bb750 100644 --- a/pkg/models/resources/daemonsets.go +++ b/pkg/models/resources/daemonsets.go @@ -80,7 +80,7 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/deployments.go b/pkg/models/resources/deployments.go index 97fbc8dc..3492fb8f 100644 --- a/pkg/models/resources/deployments.go +++ b/pkg/models/resources/deployments.go @@ -84,7 +84,7 @@ func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) b if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/ingresses.go b/pkg/models/resources/ingresses.go index 3d7967bc..b81cedee 100644 --- a/pkg/models/resources/ingresses.go +++ b/pkg/models/resources/ingresses.go @@ -67,7 +67,7 @@ func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress) if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/jobs.go b/pkg/models/resources/jobs.go index d22b0a57..a8e60e8b 100644 --- a/pkg/models/resources/jobs.go +++ b/pkg/models/resources/jobs.go @@ -86,7 +86,7 @@ func (*jobSearcher) fuzzy(fuzzy map[string]string, item *batchv1.Job) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } @@ -126,7 +126,7 @@ func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool { switch orderBy { case CreateTime: return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) - case updateTime: + case UpdateTime: return jobUpdateTime(a).Before(jobUpdateTime(b)) case Name: fallthrough diff --git a/pkg/models/resources/namespaces.go b/pkg/models/resources/namespaces.go index 9aa5a6dc..d34aa01b 100644 --- a/pkg/models/resources/namespaces.go +++ b/pkg/models/resources/namespaces.go @@ -66,7 +66,7 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/nodes.go b/pkg/models/resources/nodes.go index 530a442f..6daa02c6 100644 --- a/pkg/models/resources/nodes.go +++ b/pkg/models/resources/nodes.go @@ -66,7 +66,7 @@ func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/persistentvolumeclaims.go b/pkg/models/resources/persistentvolumeclaims.go index c50e1d35..307dfc7b 100644 --- a/pkg/models/resources/persistentvolumeclaims.go +++ b/pkg/models/resources/persistentvolumeclaims.go @@ -66,7 +66,7 @@ func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.Pe if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/pods.go b/pkg/models/resources/pods.go index 33ada22f..95cdefa2 100644 --- a/pkg/models/resources/pods.go +++ b/pkg/models/resources/pods.go @@ -18,7 +18,7 @@ package resources import ( - v12 "k8s.io/api/apps/v1" + appsv1 "k8s.io/api/apps/v1" "kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/params" @@ -63,7 +63,7 @@ func podBelongTo(item *v1.Pod, kind string, name string) bool { return false } -func replicaSetBelongToDeployment(replicaSet *v12.ReplicaSet, deploymentName string) bool { +func replicaSetBelongToDeployment(replicaSet *appsv1.ReplicaSet, deploymentName string) bool { for _, owner := range replicaSet.OwnerReferences { if owner.Kind == "Deployment" && owner.Name == deploymentName { return true @@ -150,11 +150,11 @@ func podBelongToService(item *v1.Pod, serviceName string) bool { func (*podSearcher) match(match map[string]string, item *v1.Pod) bool { for k, v := range match { switch k { - case ownerKind: + case OwnerKind: fallthrough - case ownerName: - kind := match[ownerKind] - name := match[ownerName] + case OwnerName: + kind := match[OwnerKind] + name := match[OwnerName] if !podBelongTo(item, kind, name) { return false } @@ -196,7 +196,7 @@ func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/resources.go b/pkg/models/resources/resources.go index 5a64e3af..c469d8d2 100644 --- a/pkg/models/resources/resources.go +++ b/pkg/models/resources/resources.go @@ -19,6 +19,7 @@ package resources import ( "fmt" + "github.com/golang/glog" "kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/params" "kubesphere.io/kubesphere/pkg/utils/sliceutil" @@ -56,12 +57,12 @@ var ( const ( Name = "name" - label = "label" - ownerKind = "ownerKind" - ownerName = "ownerName" + Label = "label" + OwnerKind = "ownerKind" + OwnerName = "ownerName" CreateTime = "createTime" - updateTime = "updateTime" - lastScheduleTime = "lastScheduleTime" + UpdateTime = "updateTime" + LastScheduleTime = "lastScheduleTime" chart = "chart" release = "release" annotation = "annotation" @@ -106,6 +107,7 @@ func GetResource(namespace, resource, name string) (interface{}, error) { if searcher, ok := resources[resource]; ok { resource, err := searcher.get(namespace, name) if err != nil { + glog.Errorln("get resource", namespace, resource, name, err) return nil, err } return resource, nil @@ -120,16 +122,19 @@ func ListResources(namespace, resource string, conditions *params.Conditions, or // none namespace resource if namespace != "" && sliceutil.HasString(clusterResources, resource) { + glog.Errorln("resources not found", resource) return nil, fmt.Errorf("not found") } if searcher, ok := resources[resource]; ok { result, err = searcher.search(namespace, conditions, orderBy, reverse) } else { + glog.Errorln("resources not found", resource) return nil, fmt.Errorf("not found") } if err != nil { + glog.Errorln("resources search", err) return nil, err } diff --git a/pkg/models/resources/roles.go b/pkg/models/resources/roles.go index 1fbc8f2a..2787c50f 100644 --- a/pkg/models/resources/roles.go +++ b/pkg/models/resources/roles.go @@ -66,7 +66,7 @@ func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/s2ibuilder.go b/pkg/models/resources/s2ibuilder.go index b67be7e5..5f72f550 100644 --- a/pkg/models/resources/s2ibuilder.go +++ b/pkg/models/resources/s2ibuilder.go @@ -66,7 +66,7 @@ func (*s2iBuilderSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iBuil if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/s2ibuildertemplate.go b/pkg/models/resources/s2ibuildertemplate.go index 9479f9cf..9d156cd4 100644 --- a/pkg/models/resources/s2ibuildertemplate.go +++ b/pkg/models/resources/s2ibuildertemplate.go @@ -66,7 +66,7 @@ func (*s2iBuilderTemplateSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1 if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/s2irun.go b/pkg/models/resources/s2irun.go index b00244de..7c8b52e3 100644 --- a/pkg/models/resources/s2irun.go +++ b/pkg/models/resources/s2irun.go @@ -73,7 +73,7 @@ func (*s2iRunSearcher) fuzzy(fuzzy map[string]string, item *v1alpha1.S2iRun) boo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/secrets.go b/pkg/models/resources/secrets.go index 883119bb..7fbd5871 100644 --- a/pkg/models/resources/secrets.go +++ b/pkg/models/resources/secrets.go @@ -70,7 +70,7 @@ func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/services.go b/pkg/models/resources/services.go index 0b38d2e0..f231c33c 100644 --- a/pkg/models/resources/services.go +++ b/pkg/models/resources/services.go @@ -66,7 +66,7 @@ func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/statefulsets.go b/pkg/models/resources/statefulsets.go index 474d8ca5..09a244b8 100644 --- a/pkg/models/resources/statefulsets.go +++ b/pkg/models/resources/statefulsets.go @@ -83,7 +83,7 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet) if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/storageclasses.go b/pkg/models/resources/storageclasses.go index 7f11b9d2..1ba6df52 100644 --- a/pkg/models/resources/storageclasses.go +++ b/pkg/models/resources/storageclasses.go @@ -66,7 +66,7 @@ func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageCl if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/resources/workspaces.go b/pkg/models/resources/workspaces.go index 63ed46ea..b5919ca3 100644 --- a/pkg/models/resources/workspaces.go +++ b/pkg/models/resources/workspaces.go @@ -66,7 +66,7 @@ func (*workspaceSearcher) fuzzy(fuzzy map[string]string, item *tenantv1alpha1.Wo if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { return false } - case label: + case Label: if !searchFuzzy(item.Labels, "", v) { return false } diff --git a/pkg/models/types.go b/pkg/models/types.go index fd5a49cd..a717462a 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -18,7 +18,7 @@ package models import ( - v12 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" "time" "k8s.io/api/rbac/v1" @@ -117,6 +117,6 @@ type Token struct { } type ResourceQuota struct { - Namespace string `json:"namespace"` - Data v12.ResourceQuotaStatus `json:"data"` + Namespace string `json:"namespace"` + Data corev1.ResourceQuotaStatus `json:"data"` } diff --git a/pkg/models/workspaces/workspaces.go b/pkg/models/workspaces/workspaces.go index 750af1fb..89305def 100644 --- a/pkg/models/workspaces/workspaces.go +++ b/pkg/models/workspaces/workspaces.go @@ -144,11 +144,10 @@ func CreateWorkspaceRoleBinding(workspace, username string, role string) error { roleBindingName := fmt.Sprintf("workspace:%s:%s", workspace, strings.TrimPrefix(role, "workspace-")) workspaceRoleBinding, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister().Get(roleBindingName) - workspaceRoleBinding = workspaceRoleBinding.DeepCopy() if err != nil { return err } - + workspaceRoleBinding = workspaceRoleBinding.DeepCopy() if !k8sutil.ContainsUser(workspaceRoleBinding.Subjects, username) { workspaceRoleBinding.Subjects = append(workspaceRoleBinding.Subjects, v1.Subject{APIGroup: "rbac.authorization.k8s.io", Kind: "User", Name: username}) _, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(workspaceRoleBinding) diff --git a/pkg/simple/client/ldap/ldapclient.go b/pkg/simple/client/ldap/ldapclient.go index e2cba094..9c47a89b 100644 --- a/pkg/simple/client/ldap/ldapclient.go +++ b/pkg/simple/client/ldap/ldapclient.go @@ -20,6 +20,7 @@ package ldap import ( "flag" "github.com/go-ldap/ldap" + "github.com/golang/glog" "log" "sync" ) @@ -67,6 +68,7 @@ func Client() (ldap.Client, error) { conn, err := ldapClientPool().Get() if err != nil { + glog.Errorln("get ldap connection from pool", err) return nil, err } @@ -74,6 +76,7 @@ func Client() (ldap.Client, error) { if err != nil { conn.Close() + glog.Errorln("bind manager dn", err) return nil, err } -- GitLab