未验证 提交 eaf8cc40 编写于 作者: K KubeSphere CI Bot 提交者: GitHub

Merge pull request #3217 from RolandMa1986/feat-groupapi

add group api
...@@ -18,6 +18,10 @@ package loginrecord ...@@ -18,6 +18,10 @@ package loginrecord
import ( import (
"fmt" "fmt"
"reflect"
"testing"
"time"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
...@@ -29,9 +33,6 @@ import ( ...@@ -29,9 +33,6 @@ import (
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2" iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake" "kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"reflect"
"testing"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
...@@ -228,6 +229,12 @@ func checkAction(expected, actual core.Action, t *testing.T) { ...@@ -228,6 +229,12 @@ func checkAction(expected, actual core.Action, t *testing.T) {
func filterInformerActions(actions []core.Action) []core.Action { func filterInformerActions(actions []core.Action) []core.Action {
var ret []core.Action var ret []core.Action
for _, action := range actions { for _, action := range actions {
if len(action.GetNamespace()) == 0 &&
(action.Matches("list", "users") ||
action.Matches("watch", "users") ||
action.Matches("get", "users")) {
continue
}
ret = append(ret, action) ret = append(ret, action)
} }
......
...@@ -18,10 +18,11 @@ package v1alpha2 ...@@ -18,10 +18,11 @@ package v1alpha2
import ( import (
"fmt" "fmt"
"strings"
authuser "k8s.io/apiserver/pkg/authentication/user" authuser "k8s.io/apiserver/pkg/authentication/user"
"kubesphere.io/kubesphere/pkg/apiserver/request" "kubesphere.io/kubesphere/pkg/apiserver/request"
"kubesphere.io/kubesphere/pkg/models/auth" "kubesphere.io/kubesphere/pkg/models/auth"
"strings"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
...@@ -1344,9 +1345,8 @@ func (h *iamHandler) PatchGroup(request *restful.Request, response *restful.Resp ...@@ -1344,9 +1345,8 @@ func (h *iamHandler) PatchGroup(request *restful.Request, response *restful.Resp
func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restful.Response) { func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace") workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group")
queryParam := query.ParseQueryParameter(request) queryParam := query.ParseQueryParameter(request)
result, err := h.group.ListGroupBindings(workspaceName, groupName, queryParam) result, err := h.group.ListGroupBindings(workspaceName, queryParam)
if err != nil { if err != nil {
api.HandleError(response, request, err) api.HandleError(response, request, err)
return return
...@@ -1357,20 +1357,8 @@ func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restf ...@@ -1357,20 +1357,8 @@ func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restf
func (h *iamHandler) ListGroupRoleBindings(request *restful.Request, response *restful.Response) { func (h *iamHandler) ListGroupRoleBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace") workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group") queryParam := query.ParseQueryParameter(request)
result, err := h.am.ListGroupRoleBindings(workspaceName, groupName) result, err := h.am.ListGroupRoleBindings(workspaceName, queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) ListGroupDevOpsRoleBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group")
result, err := h.am.ListGroupDevOpsRoleBindings(workspaceName, groupName)
if err != nil { if err != nil {
api.HandleInternalError(response, request, err) api.HandleInternalError(response, request, err)
return return
...@@ -1416,8 +1404,8 @@ func (h *iamHandler) DeleteRoleBinding(request *restful.Request, response *restf ...@@ -1416,8 +1404,8 @@ func (h *iamHandler) DeleteRoleBinding(request *restful.Request, response *restf
func (h *iamHandler) ListGroupWorkspaceRoleBindings(request *restful.Request, response *restful.Response) { func (h *iamHandler) ListGroupWorkspaceRoleBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace") workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group") queryParam := query.ParseQueryParameter(request)
result, err := h.am.ListGroupWorkspaceRoleBindings(workspaceName, groupName) result, err := h.am.ListGroupWorkspaceRoleBindings(workspaceName, queryParam)
if err != nil { if err != nil {
api.HandleInternalError(response, request, err) api.HandleInternalError(response, request, err)
return return
......
...@@ -17,9 +17,10 @@ limitations under the License. ...@@ -17,9 +17,10 @@ limitations under the License.
package v1alpha2 package v1alpha2
import ( import (
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"net/http" "net/http"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi" restfulspec "github.com/emicklei/go-restful-openapi"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
...@@ -518,7 +519,15 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf ...@@ -518,7 +519,15 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}). Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/groupbindings"). ws.Route(ws.PATCH("/workspaces/{workspace}/groups/{group}/").
To(handler.PatchGroup).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("Patch Group").
Reads(iamv1alpha2.Group{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groupbindings").
To(handler.ListGroupBindings). To(handler.ListGroupBindings).
Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")). Param(ws.PathParameter("group", "group name")).
...@@ -526,7 +535,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf ...@@ -526,7 +535,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Returns(http.StatusOK, api.StatusOK, api.ListResult{}). Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/rolebindings"). ws.Route(ws.GET("/workspaces/{workspace}/rolebindings").
To(handler.ListGroupRoleBindings). To(handler.ListGroupRoleBindings).
Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")). Param(ws.PathParameter("group", "group name")).
...@@ -534,7 +543,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf ...@@ -534,7 +543,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Returns(http.StatusOK, api.StatusOK, api.ListResult{}). Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/workspacerolebindings"). ws.Route(ws.GET("/workspaces/{workspace}/workspacerolebindings").
To(handler.ListGroupWorkspaceRoleBindings). To(handler.ListGroupWorkspaceRoleBindings).
Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")). Param(ws.PathParameter("group", "group name")).
...@@ -542,14 +551,6 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf ...@@ -542,14 +551,6 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Returns(http.StatusOK, api.StatusOK, api.ListResult{}). Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/devopsrolebindings").
To(handler.ListGroupDevOpsRoleBindings).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")).
Doc("Retrieve group's rolebindings of all devops projects in the workspace.").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/groupbindings/{groupbinding}"). ws.Route(ws.DELETE("/workspaces/{workspace}/groupbindings/{groupbinding}").
To(handler.DeleteGroupBinding). To(handler.DeleteGroupBinding).
Param(ws.PathParameter("workspace", "workspace name")). Param(ws.PathParameter("workspace", "workspace name")).
......
...@@ -18,6 +18,7 @@ package am ...@@ -18,6 +18,7 @@ package am
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
...@@ -85,11 +86,10 @@ type AccessManagementInterface interface { ...@@ -85,11 +86,10 @@ type AccessManagementInterface interface {
GetDevOpsControlledWorkspace(devops string) (string, error) GetDevOpsControlledWorkspace(devops string) (string, error)
PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error) PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error) PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) ListGroupRoleBindings(workspace string, query *query.Query) ([]*rbacv1.RoleBinding, error)
ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error)
CreateRoleBinding(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) CreateRoleBinding(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
DeleteRoleBinding(namespace, name string) error DeleteRoleBinding(namespace, name string) error
ListGroupWorkspaceRoleBindings(group string, workspace string) ([]*iamv1alpha2.WorkspaceRoleBinding, error) ListGroupWorkspaceRoleBindings(workspace string, query *query.Query) (*api.ListResult, error)
CreateWorkspaceRoleBinding(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error) CreateWorkspaceRoleBinding(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error)
DeleteWorkspaceRoleBinding(workspaceName, name string) error DeleteWorkspaceRoleBinding(workspaceName, name string) error
} }
...@@ -1017,24 +1017,17 @@ func (am *amOperator) GetNamespaceControlledWorkspace(namespace string) (string, ...@@ -1017,24 +1017,17 @@ func (am *amOperator) GetNamespaceControlledWorkspace(namespace string) (string,
return ns.Labels[tenantv1alpha1.WorkspaceLabel], nil return ns.Labels[tenantv1alpha1.WorkspaceLabel], nil
} }
func (am *amOperator) ListGroupWorkspaceRoleBindings(workspace, group string) ([]*iamv1alpha2.WorkspaceRoleBinding, error) { func (am *amOperator) ListGroupWorkspaceRoleBindings(workspace string, query *query.Query) (*api.ListResult, error) {
queryParam := query.New()
queryParam.LabelSelector = labels.FormatLabels(map[string]string{tenantv1alpha1.WorkspaceLabel: workspace}) lableSelector, err := labels.ConvertSelectorToLabelsMap(query.LabelSelector)
roleBindings, err := am.workspaceRoleBindingGetter.List("", queryParam)
if err != nil { if err != nil {
klog.Error(err)
return nil, err return nil, err
} }
// workspace resources must be filtered by workspace
result := make([]*iamv1alpha2.WorkspaceRoleBinding, 0) wsSelector := labels.Set{tenantv1alpha1.WorkspaceLabel: workspace}
for _, obj := range roleBindings.Items { query.LabelSelector = labels.Merge(lableSelector, wsSelector).String()
roleBinding := obj.(*iamv1alpha2.WorkspaceRoleBinding) return am.workspaceRoleBindingGetter.List("", query)
inSpecifiedWorkspace := workspace == "" || roleBinding.Labels[tenantv1alpha1.WorkspaceLabel] == workspace
if containsGroup(roleBinding.Subjects, group) && inSpecifiedWorkspace {
result = append(result, roleBinding)
}
}
return result, nil
} }
func (am *amOperator) CreateWorkspaceRoleBinding(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error) { func (am *amOperator) CreateWorkspaceRoleBinding(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error) {
...@@ -1071,14 +1064,14 @@ func (am *amOperator) DeleteWorkspaceRoleBinding(workspaceName, name string) err ...@@ -1071,14 +1064,14 @@ func (am *amOperator) DeleteWorkspaceRoleBinding(workspaceName, name string) err
return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Delete(name, metav1.NewDeleteOptions(0)) return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Delete(name, metav1.NewDeleteOptions(0))
} }
func (am *amOperator) ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) { func (am *amOperator) ListGroupRoleBindings(workspace string, query *query.Query) ([]*rbacv1.RoleBinding, error) {
namespaces, err := am.namespaceLister.List(labels.SelectorFromSet(labels.Set{tenantv1alpha1.WorkspaceLabel: workspace})) namespaces, err := am.namespaceLister.List(labels.SelectorFromSet(labels.Set{tenantv1alpha1.WorkspaceLabel: workspace}))
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := make([]*rbacv1.RoleBinding, 0) result := make([]*rbacv1.RoleBinding, 0)
for _, namespace := range namespaces { for _, namespace := range namespaces {
roleBindings, err := am.roleBindingGetter.List(namespace.Name, query.New()) roleBindings, err := am.roleBindingGetter.List(namespace.Name, query)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
...@@ -1086,31 +1079,22 @@ func (am *amOperator) ListGroupRoleBindings(workspace, group string) ([]*rbacv1. ...@@ -1086,31 +1079,22 @@ func (am *amOperator) ListGroupRoleBindings(workspace, group string) ([]*rbacv1.
for _, obj := range roleBindings.Items { for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding) roleBinding := obj.(*rbacv1.RoleBinding)
if containsGroup(roleBinding.Subjects, group) { result = append(result, roleBinding)
result = append(result, roleBinding)
}
} }
} }
return result, nil
}
func (am *amOperator) ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) {
devOpsProjects, err := am.devopsProjectLister.List(labels.SelectorFromSet(labels.Set{tenantv1alpha1.WorkspaceLabel: workspace})) devOpsProjects, err := am.devopsProjectLister.List(labels.SelectorFromSet(labels.Set{tenantv1alpha1.WorkspaceLabel: workspace}))
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := make([]*rbacv1.RoleBinding, 0)
for _, devOpsProject := range devOpsProjects { for _, devOpsProject := range devOpsProjects {
roleBindings, err := am.roleBindingGetter.List(devOpsProject.Name, query.New()) roleBindings, err := am.roleBindingGetter.List(devOpsProject.Name, query)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
for _, obj := range roleBindings.Items { for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding) roleBinding := obj.(*rbacv1.RoleBinding)
if containsGroup(roleBinding.Subjects, group) { result = append(result, roleBinding)
result = append(result, roleBinding)
}
} }
} }
return result, nil return result, nil
...@@ -1147,12 +1131,3 @@ func (am *amOperator) CreateRoleBinding(namespace string, roleBinding *rbacv1.Ro ...@@ -1147,12 +1131,3 @@ func (am *amOperator) CreateRoleBinding(namespace string, roleBinding *rbacv1.Ro
func (am *amOperator) DeleteRoleBinding(namespace, name string) error { func (am *amOperator) DeleteRoleBinding(namespace, name string) error {
return am.k8sclient.RbacV1().RoleBindings(namespace).Delete(name, metav1.NewDeleteOptions(0)) return am.k8sclient.RbacV1().RoleBindings(namespace).Delete(name, metav1.NewDeleteOptions(0))
} }
func containsGroup(subjects []rbacv1.Subject, group string) bool {
for _, subject := range subjects {
if subject.Kind == rbacv1.GroupKind && subject.Name == group {
return true
}
}
return false
}
...@@ -23,6 +23,7 @@ import ( ...@@ -23,6 +23,7 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
...@@ -45,7 +46,7 @@ type GroupOperator interface { ...@@ -45,7 +46,7 @@ type GroupOperator interface {
PatchGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error) PatchGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error)
DeleteGroupBinding(workspace, name string) error DeleteGroupBinding(workspace, name string) error
CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error) CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error)
ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error) ListGroupBindings(workspace string, queryParam *query.Query) (*api.ListResult, error)
} }
type groupOperator struct { type groupOperator struct {
...@@ -200,14 +201,18 @@ func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string ...@@ -200,14 +201,18 @@ func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string
return t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding) return t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding)
} }
func (t *groupOperator) ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error) { func (t *groupOperator) ListGroupBindings(workspace string, query *query.Query) (*api.ListResult, error) {
if group != "" && workspace != "" { lableSelector, err := labels.ConvertSelectorToLabelsMap(query.LabelSelector)
// filter by group if err != nil {
queryParam.Filters[query.FieldLabel] = query.Value(fmt.Sprintf("%s=%s", iamv1alpha2.GroupReferenceLabel, group)) klog.Error(err)
return nil, err
} }
// workspace resources must be filtered by workspace
wsSelector := labels.Set{tenantv1alpha1.WorkspaceLabel: workspace}
query.LabelSelector = labels.Merge(lableSelector, wsSelector).String()
result, err := t.resourceGetter.List("groupbindings", "", queryParam) result, err := t.resourceGetter.List("groupbindings", "", query)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册