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

Merge pull request #3127 from RolandMa1986/feat-group-rolebinding

add rolebinding api
......@@ -167,7 +167,7 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo
api.HandleInternalError(response, request, err)
return
}
templateRoles := make(map[string]*rbacv1.Role)
templateRoles := make(map[string]*iamv1alpha2.WorkspaceRole)
for _, role := range workspaceRoles {
// merge template Role
result, err := h.am.ListWorkspaceRoles(&query.Query{
......@@ -183,12 +183,12 @@ func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, respo
}
for _, obj := range result.Items {
templateRole := obj.(*rbacv1.Role)
templateRole := obj.(*iamv1alpha2.WorkspaceRole)
templateRoles[templateRole.Name] = templateRole
}
}
results := make([]*rbacv1.Role, 0, len(templateRoles))
results := make([]*iamv1alpha2.WorkspaceRole, 0, len(templateRoles))
for _, value := range templateRoles {
results = append(results, value)
}
......@@ -904,7 +904,7 @@ func (h *iamHandler) CreateWorkspaceMembers(request *restful.Request, response *
}
for _, member := range members {
err := h.am.CreateWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
err := h.am.CreateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
......@@ -948,7 +948,7 @@ func (h *iamHandler) UpdateWorkspaceMember(request *restful.Request, response *r
return
}
err = h.am.CreateWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
err = h.am.CreateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
......@@ -1494,12 +1494,131 @@ func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restf
response.WriteEntity(result)
}
func (h *iamHandler) ListGroupsRoleBinding(request *restful.Request, response *restful.Response) {
//todo
func (h *iamHandler) ListGroupRoleBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group")
result, err := h.am.ListGroupRoleBindings(workspaceName, groupName)
if err != nil {
klog.Error(err)
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 {
klog.Error(err)
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) CreateRoleBinding(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
var roleBindings []rbacv1.RoleBinding
err := request.ReadEntity(&roleBindings)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
results := []rbacv1.RoleBinding{}
for _, item := range roleBindings {
r, err := h.am.CreateRoleBinding(namespace, &item)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
results = append(results, *r)
}
response.WriteEntity(results)
}
func (h *iamHandler) DeleteRoleBinding(request *restful.Request, response *restful.Response) {
name := request.PathParameter("rolebinding")
namespace := request.PathParameter("namespace")
err := h.am.DeleteRoleBinding(namespace, name)
if err != nil {
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) ListGroupWorkspaceRoleBindings(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
groupName := request.PathParameter("group")
result, err := h.am.ListGroupWorkspaceRoleBindings(workspaceName, groupName)
if err != nil {
klog.Error(err)
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) CreateWorkspaceRoleBinding(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
var roleBindings []iamv1alpha2.WorkspaceRoleBinding
err := request.ReadEntity(&roleBindings)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
results := []iamv1alpha2.WorkspaceRoleBinding{}
for _, item := range roleBindings {
r, err := h.am.CreateWorkspaceRoleBinding(workspaceName, &item)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
results = append(results, *r)
}
response.WriteEntity(results)
}
func (h *iamHandler) ListGroupsWorkspaceRoleBinding(request *restful.Request, response *restful.Response) {
//todo
func (h *iamHandler) DeleteWorkspaceRoleBinding(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
name := request.PathParameter("rolebinding")
err := h.am.DeleteWorkspaceRoleBinding(workspaceName, name)
if err != nil {
if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
return
}
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) CreateGroupBinding(request *restful.Request, response *restful.Response) {
......@@ -1514,16 +1633,19 @@ func (h *iamHandler) CreateGroupBinding(request *restful.Request, response *rest
return
}
results := []iamv1alpha2.GroupBinding{}
for _, item := range members {
err := h.group.CreateGroupBinding(workspace, item.GroupName, item.UserName)
b, err := h.group.CreateGroupBinding(workspace, item.GroupName, item.UserName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
results = append(results, *b)
}
response.WriteEntity(members)
response.WriteEntity(results)
}
func (h *iamHandler) DeleteGroupBinding(request *restful.Request, response *restful.Response) {
......
......@@ -22,6 +22,7 @@ import (
"github.com/emicklei/go-restful"
restfulspec "github.com/emicklei/go-restful-openapi"
rbacv1 "k8s.io/api/rbac/v1"
v1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/api/iam"
......@@ -527,21 +528,29 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/rolebindings").
To(handler.ListGroupsRoleBinding).
To(handler.ListGroupRoleBindings).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")).
Doc("Retrieve group's rolebindings of all projects in the workspace.").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/workspacerolebinding").
To(handler.ListGroupsWorkspaceRoleBinding).
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}/workspacerolebindings").
To(handler.ListGroupWorkspaceRoleBindings).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("group", "group name")).
Doc("Retrieve group's workspacerolebindings of the workspace.").
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
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}").
To(handler.DeleteGroupBinding).
Param(ws.PathParameter("workspace", "workspace name")).
......@@ -558,6 +567,41 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GroupBinding{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
// namespace rolebinding
ws.Route(ws.POST("/namespaces/{namespace}/rolebindings").
To(handler.CreateRoleBinding).
Doc("Create rolebinding in the specified namespace.").
Reads([]v1.RoleBinding{}).
Param(ws.PathParameter("namespace", "namespace")).
Returns(http.StatusOK, api.StatusOK, []v1.RoleBinding{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
ws.Route(ws.DELETE("/namespace/{namespace}/rolebindings/{rolebinding}").
To(handler.DeleteRoleBinding).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("namespace", "groupbinding name")).
Param(ws.PathParameter("rolebinding", "groupbinding name")).
Doc("Delete rolebinding under namespace.").
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
// workspace rolebinding
ws.Route(ws.POST("/workspaces/{workspace}/workspacerolebindings").
To(handler.CreateWorkspaceRoleBinding).
Param(ws.PathParameter("workspace", "workspace name")).
Reads([]iamv1alpha2.WorkspaceRoleBinding{}).
Doc("Create group's workspacerolebindings of the workspace.").
Returns(http.StatusOK, api.StatusOK, []iamv1alpha2.WorkspaceRoleBinding{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/workspacerolebindings/{rolebinding}").
To(handler.DeleteWorkspaceRoleBinding).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("rolebinding", "groupbinding name")).
Doc("Delete workspacerolebinding.").
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
container.Add(ws)
return nil
}
......@@ -66,7 +66,7 @@ type AccessManagementInterface interface {
GetNamespaceRole(namespace string, name string) (*rbacv1.Role, error)
CreateOrUpdateNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
DeleteNamespaceRole(namespace string, name string) error
CreateWorkspaceRoleBinding(username string, workspace string, role string) error
CreateUserWorkspaceRoleBinding(username string, workspace string, role string) error
RemoveUserFromWorkspace(username string, workspace string) error
CreateNamespaceRoleBinding(username string, namespace string, role string) error
RemoveUserFromNamespace(username string, namespace string) error
......@@ -77,6 +77,13 @@ type AccessManagementInterface interface {
GetDevOpsControlledWorkspace(devops string) (string, error)
PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error)
ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error)
CreateRoleBinding(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
DeleteRoleBinding(namespace, name string) error
ListGroupWorkspaceRoleBindings(group string, workspace string) ([]*iamv1alpha2.WorkspaceRoleBinding, error)
CreateWorkspaceRoleBinding(workspace string, roleBinding *iamv1alpha2.WorkspaceRoleBinding) (*iamv1alpha2.WorkspaceRoleBinding, error)
DeleteWorkspaceRoleBinding(workspaceName, name string) error
}
type amOperator struct {
......@@ -568,7 +575,7 @@ func (am *amOperator) PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1
return am.k8sclient.RbacV1().ClusterRoles().Patch(clusterRole.Name, types.MergePatchType, data)
}
func (am *amOperator) CreateWorkspaceRoleBinding(username string, workspace string, role string) error {
func (am *amOperator) CreateUserWorkspaceRoleBinding(username string, workspace string, role string) error {
_, err := am.GetWorkspaceRole(workspace, role)
if err != nil {
klog.Error(err)
......@@ -998,3 +1005,155 @@ func (am *amOperator) GetNamespaceControlledWorkspace(namespace string) (string,
ns := obj.(*corev1.Namespace)
return ns.Labels[tenantv1alpha1.WorkspaceLabel], nil
}
func (am *amOperator) ListGroupWorkspaceRoleBindings(workspace, group string) ([]*iamv1alpha2.WorkspaceRoleBinding, error) {
q := workspaceQuery(workspace)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralWorkspaceRoleBinding, "", q)
if err != nil {
return nil, err
}
result := make([]*iamv1alpha2.WorkspaceRoleBinding, 0)
for _, obj := range roleBindings.Items {
roleBinding := obj.(*iamv1alpha2.WorkspaceRoleBinding)
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) {
_, err := am.GetWorkspaceRole(workspace, roleBinding.RoleRef.Name)
if err != nil {
klog.Error(err)
return nil, err
}
if len(roleBinding.Subjects) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralUser), "")
return nil, err
}
roleBinding.GenerateName = fmt.Sprintf("%s-%s-", roleBinding.Subjects[0].Name, roleBinding.RoleRef.Name)
if roleBinding.Labels == nil {
roleBinding.Labels = map[string]string{}
}
if roleBinding.Subjects[0].Kind == rbacv1.GroupKind {
roleBinding.Labels[iamv1alpha2.GroupReferenceLabel] = roleBinding.RoleRef.Name
} else if roleBinding.Subjects[0].Kind == rbacv1.UserKind {
roleBinding.Labels[iamv1alpha2.UserReferenceLabel] = roleBinding.RoleRef.Name
}
roleBinding.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Create(roleBinding)
}
func (am *amOperator) DeleteWorkspaceRoleBinding(workspaceName, name string) error {
return am.ksclient.IamV1alpha2().WorkspaceRoleBindings().Delete(name, metav1.NewDeleteOptions(0))
}
func (am *amOperator) ListGroupRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) {
q := workspaceQuery(workspace)
namespaces, err := am.resourceGetter.List("namespaces", "", q)
if err != nil {
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, ns := range namespaces.Items {
namespace := ns.(*corev1.Namespace)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralRoleBinding, namespace.Name, query.New())
if err != nil {
klog.Error(err)
return nil, err
}
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding)
if containsgroup(roleBinding.Subjects, group) {
result = append(result, roleBinding)
}
}
}
return result, nil
}
func (am *amOperator) ListGroupDevOpsRoleBindings(workspace, group string) ([]*rbacv1.RoleBinding, error) {
q := workspaceQuery(workspace)
namespaces, err := am.resourceGetter.List(devopsv1alpha3.ResourcePluralDevOpsProject, "", q)
if err != nil {
return nil, err
}
result := make([]*rbacv1.RoleBinding, 0)
for _, ns := range namespaces.Items {
namespace := ns.(*devopsv1alpha3.DevOpsProject)
roleBindings, err := am.resourceGetter.List(iamv1alpha2.ResourcesPluralRoleBinding, namespace.Name, query.New())
if err != nil {
klog.Error(err)
return nil, err
}
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.RoleBinding)
if containsgroup(roleBinding.Subjects, group) {
result = append(result, roleBinding)
}
}
}
return result, nil
}
func (am *amOperator) CreateRoleBinding(namespace string, roleBinding *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
_, err := am.GetNamespaceRole(namespace, roleBinding.RoleRef.Name)
if err != nil {
klog.Error(err)
return nil, err
}
if len(roleBinding.Subjects) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesPluralUser), "")
return nil, err
}
roleBinding.GenerateName = fmt.Sprintf("%s-%s-", roleBinding.Subjects[0].Name, roleBinding.RoleRef.Name)
if roleBinding.Labels == nil {
roleBinding.Labels = map[string]string{}
}
if roleBinding.Subjects[0].Kind == rbacv1.GroupKind {
roleBinding.Labels[iamv1alpha2.GroupReferenceLabel] = roleBinding.Subjects[0].Name
} else if roleBinding.Subjects[0].Kind == rbacv1.UserKind {
roleBinding.Labels[iamv1alpha2.UserReferenceLabel] = roleBinding.Subjects[0].Name
}
return am.k8sclient.RbacV1().RoleBindings(namespace).Create(roleBinding)
}
func (am *amOperator) DeleteRoleBinding(namespace, name string) error {
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
}
func workspaceQuery(workspace string) *query.Query {
q := query.New()
q.Filters[query.FieldLabel] = query.Value(fmt.Sprintf("%s=%s", tenantv1alpha1.WorkspaceLabel, workspace))
return q
}
......@@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
......@@ -43,7 +44,7 @@ type GroupOperator interface {
UpdateGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error)
PatchGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error)
DeleteGroupBinding(workspace, name string) error
CreateGroupBinding(workspace, groupName, userName string) error
CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error)
ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error)
}
......@@ -77,8 +78,43 @@ func (t *groupOperator) ListGroups(workspace string, queryParam *query.Query) (*
}
// CreateGroup adds a workspace label to group which indicates group is under the workspace
func (t *groupOperator) CreateGroup(workspace string, namespace *iamv1alpha2.Group) (*iamv1alpha2.Group, error) {
return t.ksclient.IamV1alpha2().Groups().Create(labelGroupWithWorkspaceName(namespace, workspace))
func (t *groupOperator) CreateGroup(workspace string, group *iamv1alpha2.Group) (*iamv1alpha2.Group, error) {
if group.GenerateName == "" {
err := errors.NewInvalid(iamv1alpha2.SchemeGroupVersion.WithKind(iamv1alpha2.ResourcePluralGroup).GroupKind(),
"", []*field.Error{field.Required(field.NewPath("metadata.generateName"), "generateName is required")})
klog.Error(err)
return nil, err
}
// generateName is used as displayName
// ensure generateName is unique in workspace scope
if unique, err := t.isGenerateNameUnique(workspace, group.GenerateName); err != nil {
return nil, err
} else if !unique {
err = errors.NewConflict(iamv1alpha2.Resource(iamv1alpha2.ResourcePluralGroup),
group.GenerateName, fmt.Errorf("a group named %s already exists in the workspace", group.GenerateName))
klog.Error(err)
return nil, err
}
return t.ksclient.IamV1alpha2().Groups().Create(labelGroupWithWorkspaceName(group, workspace))
}
func (t *groupOperator) isGenerateNameUnique(workspace, generateName string) (bool, error) {
result, err := t.ListGroups(workspace, query.New())
if err != nil {
klog.Error(err)
return false, err
}
for _, obj := range result.Items {
g := obj.(*iamv1alpha2.Group)
if g.GenerateName == generateName {
return false, err
}
}
return true, nil
}
func (t *groupOperator) DescribeGroup(workspace, group string) (*iamv1alpha2.Group, error) {
......@@ -142,11 +178,11 @@ func (t *groupOperator) DeleteGroupBinding(workspace, name string) error {
return t.ksclient.IamV1alpha2().GroupBindings().Delete(name, metav1.NewDeleteOptions(0))
}
func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string) error {
func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string) (*iamv1alpha2.GroupBinding, error) {
groupBinding := iamv1alpha2.GroupBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s", groupName, userName),
GenerateName: fmt.Sprintf("%s-%s-", groupName, userName),
Labels: map[string]string{
iamv1alpha2.UserReferenceLabel: userName,
iamv1alpha2.GroupReferenceLabel: groupName,
......@@ -161,11 +197,7 @@ func (t *groupOperator) CreateGroupBinding(workspace, groupName, userName string
},
}
if _, err := t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding); err != nil {
return err
}
return nil
return t.ksclient.IamV1alpha2().GroupBindings().Create(&groupBinding)
}
func (t *groupOperator) ListGroupBindings(workspace, group string, queryParam *query.Query) (*api.ListResult, error) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册