提交 a908757c 编写于 作者: H hongming

fix bug: rolebinding cannot delete

上级 49d40f48
......@@ -55,7 +55,7 @@ func RoleHandler(req *restful.Request, resp *restful.Response) {
workspaceName := req.PathParameter("name")
roleName := req.PathParameter("role")
if !slice.ContainsString(workspaces.WorkSpaceRoles, roleName, nil) {
if !slice.ContainsString(constants.WorkSpaceRoles, roleName, nil) {
resp.WriteHeaderAndEntity(http.StatusNotFound, constants.MessageResponse{Message: fmt.Sprintf("role %s not found", roleName)})
return
}
......
......@@ -44,6 +44,10 @@ const (
AccountAPIServerEnv = "ACCOUNT_API_SERVER"
DevopsProxyTokenEnv = "DEVOPS_PROXY_TOKEN"
OpenPitrixProxyTokenEnv = "OPENPITRIX_PROXY_TOKEN"
WorkspaceLabelKey = "kubesphere.io/workspace"
WorkspaceAdmin = "workspace-admin"
WorkspaceRegular = "workspace-regular"
WorkspaceViewer = "workspace-viewer"
)
var (
......@@ -51,6 +55,7 @@ var (
AccountAPIServer = "ks-account.kubesphere-system.svc"
DevopsProxyToken = ""
OpenPitrixProxyToken = ""
WorkSpaceRoles = []string{WorkspaceAdmin, WorkspaceRegular, WorkspaceViewer}
)
func init() {
......
......@@ -22,6 +22,8 @@ import (
"fmt"
"regexp"
"strings"
"github.com/golang/glog"
"github.com/pkg/errors"
rbac "k8s.io/api/rbac/v1"
......@@ -29,6 +31,8 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
"kubesphere.io/kubesphere/pkg/constants"
)
func (ctl *ClusterRoleBindingCtl) Name() string {
......@@ -43,14 +47,14 @@ func (ctl *ClusterRoleBindingCtl) sync(stopChan chan struct{}) {
func (ctl *ClusterRoleBindingCtl) total() int {
list, err := ctl.lister.List(labels.Everything())
if err != nil {
glog.Errorf("count %s falied, reason:%s", err, ctl.Name())
glog.Errorf("count %s failed, reason:%s", ctl.Name(), err)
return 0
}
return len(list)
}
func (ctl *ClusterRoleBindingCtl) handleWorkspaceRoleChange(clusterRole *rbac.ClusterRoleBinding) {
if groups := regexp.MustCompile(`^system:(\S+):(admin|operator|viewer)$`).FindStringSubmatch(clusterRole.Name); len(groups) == 3 {
if groups := regexp.MustCompile(fmt.Sprintf(`^system:(\S+):(%s)$`, strings.Join(constants.WorkSpaceRoles, "|"))).FindStringSubmatch(clusterRole.Name); len(groups) == 3 {
workspace := groups[1]
go ctl.restNamespaceRoleBinding(workspace)
}
......
......@@ -46,7 +46,7 @@ import (
const (
provider = "kubernetes"
admin = "admin"
editor = "operator"
operator = "operator"
viewer = "viewer"
kubectlNamespace = constants.KubeSphereControlNamespace
kubectlConfigKey = "config"
......@@ -133,13 +133,10 @@ func (ctl *NamespaceCtl) createOpRuntime(namespace string) ([]byte, error) {
return makeHttpRequest("POST", url, string(body))
}
func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error {
func (ctl *NamespaceCtl) updateSystemRoleBindings(namespace *v1.Namespace) error {
workspace := ""
creator := ""
if namespace.Annotations != nil {
creator = namespace.Annotations[creatorAnnotateKey]
}
if namespace.Labels != nil {
workspace = namespace.Labels[workspaceLabelKey]
}
......@@ -159,12 +156,8 @@ func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error
adminBinding.Subjects = make([]rbac.Subject, 0)
if creator != "" {
adminBinding.Subjects = append(adminBinding.Subjects, rbac.Subject{Name: creator, Kind: rbac.UserKind})
}
if workspace != "" {
workspaceAdmin, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:admin", workspace), metaV1.GetOptions{})
workspaceAdmin, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, constants.WorkspaceAdmin), metaV1.GetOptions{})
if err != nil {
return err
}
......@@ -197,7 +190,7 @@ func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error
viewerBinding.Subjects = make([]rbac.Subject, 0)
if workspace != "" {
workspaceViewer, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:viewer", workspace), metaV1.GetOptions{})
workspaceViewer, err := ctl.K8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, constants.WorkspaceViewer), metaV1.GetOptions{})
if err != nil {
return err
}
......@@ -217,24 +210,64 @@ func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error
return nil
}
func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: adminRules}
editorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: editor, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: editorRules}
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: ns, Annotations: map[string]string{"creator": "system"}}, Rules: viewerRules}
func (ctl *NamespaceCtl) createDefaultRoleBinding(namespace *v1.Namespace) error {
creator := ""
if namespace.Annotations != nil {
creator = namespace.Annotations[creatorAnnotateKey]
}
// create once
if creator != "" {
creatorBindingName := fmt.Sprintf("%s-admin", creator)
creatorBinding, err := ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Get(creatorBindingName, metaV1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
creatorBinding = new(rbac.RoleBinding)
creatorBinding.Name = creatorBindingName
creatorBinding.Namespace = namespace.Name
creatorBinding.RoleRef = rbac.RoleRef{Kind: "Role", Name: admin}
} else {
return err
}
}
creatorBinding.Subjects = []rbac.Subject{{Kind: rbac.UserKind, Name: creator}}
if creatorBinding.ResourceVersion == "" {
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Create(creatorBinding)
} else {
_, err = ctl.K8sClient.RbacV1().RoleBindings(namespace.Name).Update(creatorBinding)
}
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
if err != nil {
return err
}
}
return nil
}
func (ctl *NamespaceCtl) CreateDefaultRoleAndRoleBinding(namespace *v1.Namespace) error {
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: adminRules}
operatorRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: operator, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: editorRules}
viewerRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: viewer, Namespace: namespace.Name, Annotations: map[string]string{creatorAnnotateKey: "system"}}, Rules: viewerRules}
_, err := ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(adminRole)
if err != nil && !errors.IsAlreadyExists(err) {
return err
} else if err == nil {
if err := ctl.createDefaultRoleBinding(namespace); err != nil {
glog.Warning("default role binding create failed", namespace.Name)
}
}
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(editorRole)
_, err = ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(operatorRole)
if err != nil && !errors.IsAlreadyExists(err) {
return err
}
_, err = ctl.K8sClient.RbacV1().Roles(ns).Create(viewerRole)
_, err = ctl.K8sClient.RbacV1().Roles(namespace.Name).Create(viewerRole)
if err != nil && !errors.IsAlreadyExists(err) {
return err
......@@ -254,27 +287,22 @@ func (ctl *NamespaceCtl) createRoleAndRuntime(namespace *v1.Namespace) {
componentsNamespaces := []string{constants.KubeSystemNamespace, constants.OpenPitrixNamespace, constants.IstioNamespace, constants.KubeSphereNamespace}
if runtime == "" && !slice.ContainsString(componentsNamespaces, namespace.Name, nil) {
glog.Infoln("create runtime:", namespace.Name)
_, runtimeCreateError := ctl.createOpRuntime(namespace.Name)
if runtimeCreateError != nil {
glog.Error("runtime create error:", runtimeCreateError)
}
}
if initTime == "" {
err := ctl.createDefaultRole(namespace.Name)
glog.Infoln("create default role:", namespace.Name)
err := ctl.CreateDefaultRoleAndRoleBinding(namespace)
if err == nil {
err = ctl.createDefaultRoleBinding(namespace)
glog.Infoln("create default role binding:", namespace.Name)
err = ctl.updateSystemRoleBindings(namespace)
if err != nil {
glog.Error("default role binding create error:", err)
glog.Error("role binding update error:", err)
}
} else {
glog.Error("default role create error:", err)
}
if err == nil {
pathJson := fmt.Sprintf(`{"metadata":{"annotations":{"%s":"%s"}}}`, initTimeAnnotateKey, time.Now().UTC().Format("2006-01-02T15:04:05Z"))
_, err = ctl.K8sClient.CoreV1().Namespaces().Patch(namespace.Name, "application/strategic-merge-patch+json", []byte(pathJson))
......
......@@ -35,12 +35,6 @@ import (
ksErr "kubesphere.io/kubesphere/pkg/util/errors"
)
const (
WorkspaceKey = "kubesphere.io/workspace"
)
var WorkSpaceRoles = []string{"admin", "operator", "viewer"}
func UnBindDevopsProject(workspace string, devops string) error {
db := client.NewSharedDBClient()
defer db.Close()
......@@ -283,7 +277,7 @@ func DeleteNamespace(workspace string, namespaceName string) error {
return err
}
if namespace.Labels != nil && namespace.Labels["kubesphere.io/workspace"] == workspace {
deletePolicy := meta_v1.DeletePropagationBackground
deletePolicy := meta_v1.DeletePropagationForeground
return client.NewK8sClient().CoreV1().Namespaces().Delete(namespaceName, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
} else {
return errors.New("resource not found")
......@@ -347,7 +341,7 @@ func workspaceRoleRelease(workspace string) error {
k8sClient := client.NewK8sClient()
deletePolicy := meta_v1.DeletePropagationForeground
for _, role := range WorkSpaceRoles {
for _, role := range constants.WorkSpaceRoles {
err := k8sClient.RbacV1().ClusterRoles().Delete(fmt.Sprintf("system:%s:%s", workspace, role), &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
if err != nil && !apierrors.IsNotFound(err) {
......@@ -355,7 +349,7 @@ func workspaceRoleRelease(workspace string) error {
}
}
for _, role := range WorkSpaceRoles {
for _, role := range constants.WorkSpaceRoles {
err := k8sClient.RbacV1().ClusterRoleBindings().Delete(fmt.Sprintf("system:%s:%s", workspace, role), &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
if err != nil && !apierrors.IsNotFound(err) {
......@@ -516,7 +510,7 @@ func ListWorkspaceByUser(username string, keyword string) ([]*Workspace, error)
} else {
workspaceNames := make([]string, 0)
for _, clusterRole := range clusterRoles {
if groups := regexp.MustCompile(`^system:(\S+):(admin|operator|viewer)$`).FindStringSubmatch(clusterRole.Name); len(groups) == 3 {
if groups := regexp.MustCompile(fmt.Sprintf(`^system:(\S+):(%s)$`, strings.Join(constants.WorkSpaceRoles, "|"))).FindStringSubmatch(clusterRole.Name); len(groups) == 3 {
if !slice.ContainsString(workspaceNames, groups[1], nil) {
workspaceNames = append(workspaceNames, groups[1])
}
......@@ -721,12 +715,18 @@ func CreateNamespace(namespace *core.Namespace) (*core.Namespace, error) {
return nil, err
}
if ctl, ok := controllers.ResourceControllers.Controllers[controllers.Namespaces]; ok {
if nsCtl, ok := ctl.(*controllers.NamespaceCtl); ok {
nsCtl.CreateDefaultRoleAndRoleBinding(ns)
}
}
return ns, nil
}
func Invite(workspaceName string, users []UserInvite) error {
for _, user := range users {
if !slice.ContainsString(WorkSpaceRoles, user.Role, nil) {
if !slice.ContainsString(constants.WorkSpaceRoles, user.Role, nil) {
return fmt.Errorf("role %s not exist", user.Role)
}
}
......@@ -807,7 +807,7 @@ func Roles(workspace *Workspace) ([]*v1.ClusterRole, error) {
k8sClient := client.NewK8sClient()
for _, name := range WorkSpaceRoles {
for _, name := range constants.WorkSpaceRoles {
role, err := k8sClient.RbacV1().ClusterRoles().Get(fmt.Sprintf("system:%s:%s", workspace.Name, name), meta_v1.GetOptions{})
if err != nil {
......@@ -859,7 +859,7 @@ func WorkspaceRoleInit(workspace *Workspace) error {
k8sClient := client.NewK8sClient()
admin := new(v1.ClusterRole)
admin.Name = fmt.Sprintf("system:%s:admin", workspace.Name)
admin.Name = fmt.Sprintf("system:%s:%s", workspace.Name, constants.WorkspaceAdmin)
admin.Kind = iam.ClusterRoleKind
admin.Rules = []v1.PolicyRule{
{
......@@ -899,10 +899,10 @@ func WorkspaceRoleInit(workspace *Workspace) error {
admin.Labels = map[string]string{"creator": "system"}
operator := new(v1.ClusterRole)
operator.Name = fmt.Sprintf("system:%s:operator", workspace.Name)
operator.Kind = iam.ClusterRoleKind
operator.Rules = []v1.PolicyRule{
regular := new(v1.ClusterRole)
regular.Name = fmt.Sprintf("system:%s:%s", workspace.Name, constants.WorkspaceRegular)
regular.Kind = iam.ClusterRoleKind
regular.Rules = []v1.PolicyRule{
{
Verbs: []string{"get"},
APIGroups: []string{"kubesphere.io"},
......@@ -948,10 +948,10 @@ func WorkspaceRoleInit(workspace *Workspace) error {
},
}
operator.Labels = map[string]string{"creator": "system"}
regular.Labels = map[string]string{"creator": "system"}
viewer := new(v1.ClusterRole)
viewer.Name = fmt.Sprintf("system:%s:viewer", workspace.Name)
viewer.Name = fmt.Sprintf("system:%s:%s", workspace.Name, constants.WorkspaceViewer)
viewer.Kind = iam.ClusterRoleKind
viewer.Rules = []v1.PolicyRule{
{
......@@ -1011,7 +1011,7 @@ func WorkspaceRoleInit(workspace *Workspace) error {
}
}
_, err = k8sClient.RbacV1().ClusterRoles().Create(operator)
_, err = k8sClient.RbacV1().ClusterRoles().Create(regular)
if err != nil {
if !apierrors.IsAlreadyExists(err) {
log.Println("cluster role create failed", viewer.Name, err)
......@@ -1019,14 +1019,14 @@ func WorkspaceRoleInit(workspace *Workspace) error {
}
}
operatorRoleBinding := new(v1.ClusterRoleBinding)
operatorRoleBinding.Name = operator.Name
operatorRoleBinding.RoleRef = v1.RoleRef{Kind: "ClusterRole", Name: operator.Name}
operatorRoleBinding.Subjects = make([]v1.Subject, 0)
_, err = k8sClient.RbacV1().ClusterRoleBindings().Create(operatorRoleBinding)
regularRoleBinding := new(v1.ClusterRoleBinding)
regularRoleBinding.Name = regular.Name
regularRoleBinding.RoleRef = v1.RoleRef{Kind: "ClusterRole", Name: regular.Name}
regularRoleBinding.Subjects = make([]v1.Subject, 0)
_, err = k8sClient.RbacV1().ClusterRoleBindings().Create(regularRoleBinding)
if err != nil {
if !apierrors.IsAlreadyExists(err) {
log.Println("cluster rolebinding create failed", operatorRoleBinding.Name, err)
log.Println("cluster rolebinding create failed", regularRoleBinding.Name, err)
return err
}
}
......@@ -1057,7 +1057,7 @@ func WorkspaceRoleInit(workspace *Workspace) error {
func unbindWorkspaceRole(workspace string, users []string) error {
k8sClient := client.NewK8sClient()
for _, name := range WorkSpaceRoles {
for _, name := range constants.WorkSpaceRoles {
roleBinding, err := k8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, name), meta_v1.GetOptions{})
if err != nil {
......@@ -1137,7 +1137,7 @@ func CreateWorkspaceRoleBinding(workspace *Workspace, username string, role stri
k8sClient := client.NewK8sClient()
for _, roleName := range WorkSpaceRoles {
for _, roleName := range constants.WorkSpaceRoles {
roleBinding, err := k8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace.Name, roleName), meta_v1.GetOptions{})
if err != nil {
......@@ -1215,7 +1215,7 @@ func GetOrgMembers(workspace string) ([]string, error) {
}
func GetOrgRoles(name string) ([]string, error) {
return []string{"admin", "operator", "user"}, nil
return constants.WorkSpaceRoles, nil
}
func WorkspaceNamespaces(workspaceName string) ([]string, error) {
......@@ -1348,7 +1348,7 @@ func GetAllOrgAndProjList() (map[string][]string, map[string]string, error) {
var namespaceWorkspaceMap = make(map[string]string)
for _, item := range nsList.Items {
ws, exist := item.Labels[WorkspaceKey]
ws, exist := item.Labels[constants.WorkspaceLabelKey]
ns := item.Name
if exist {
if nsArray, exist := workspaceNamespaceMap[ws]; exist {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册