add role patch API

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-06-17 15:55:53 +08:00
parent 692271bb56
commit 56cf6d1028
4 changed files with 379 additions and 126 deletions

View File

@@ -821,7 +821,7 @@ func (h *iamHandler) CreateWorkspaceMembers(request *restful.Request, response *
}
}
response.WriteEntity(servererr.None)
response.WriteEntity(members)
}
func (h *iamHandler) RemoveWorkspaceMember(request *restful.Request, response *restful.Response) {
@@ -867,7 +867,7 @@ func (h *iamHandler) UpdateWorkspaceMember(request *restful.Request, response *r
return
}
response.WriteEntity(servererr.None)
response.WriteEntity(member)
}
func (h *iamHandler) CreateNamespaceMembers(request *restful.Request, response *restful.Response) {
@@ -899,7 +899,7 @@ func (h *iamHandler) CreateNamespaceMembers(request *restful.Request, response *
}
}
response.WriteEntity(servererr.None)
response.WriteEntity(members)
}
func (h *iamHandler) UpdateNamespaceMember(request *restful.Request, response *restful.Response) {
@@ -936,7 +936,7 @@ func (h *iamHandler) UpdateNamespaceMember(request *restful.Request, response *r
return
}
response.WriteEntity(servererr.None)
response.WriteEntity(member)
}
func (h *iamHandler) RemoveNamespaceMember(request *restful.Request, response *restful.Response) {
@@ -980,7 +980,7 @@ func (h *iamHandler) CreateClusterMembers(request *restful.Request, response *re
}
}
response.WriteEntity(servererr.None)
response.WriteEntity(members)
}
func (h *iamHandler) RemoveClusterMember(request *restful.Request, response *restful.Response) {
@@ -1024,7 +1024,7 @@ func (h *iamHandler) UpdateClusterMember(request *restful.Request, response *res
return
}
response.WriteEntity(servererr.None)
response.WriteEntity(member)
}
func (h *iamHandler) DescribeClusterMember(request *restful.Request, response *restful.Response) {
@@ -1095,6 +1095,105 @@ func (h *iamHandler) resolveNamespace(namespace string, devops string) (string,
return h.am.GetControlledNamespace(devops)
}
func (h *iamHandler) PatchWorkspaceRole(request *restful.Request, response *restful.Response) {
workspaceName := request.PathParameter("workspace")
workspaceRoleName := request.PathParameter("workspacerole")
var workspaceRole iamv1alpha2.WorkspaceRole
err := request.ReadEntity(&workspaceRole)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
workspaceRole.Name = workspaceRoleName
patched, err := h.am.PatchWorkspaceRole(workspaceName, &workspaceRole)
if err != nil {
handleError(request, response, err)
return
}
response.WriteEntity(patched)
}
func (h *iamHandler) PatchGlobalRole(request *restful.Request, response *restful.Response) {
globalRoleName := request.PathParameter("globalrole")
var globalRole iamv1alpha2.GlobalRole
err := request.ReadEntity(&globalRole)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
globalRole.Name = globalRoleName
patched, err := h.am.PatchGlobalRole(&globalRole)
if err != nil {
handleError(request, response, err)
return
}
response.WriteEntity(patched)
}
func (h *iamHandler) PatchNamespaceRole(request *restful.Request, response *restful.Response) {
roleName := request.PathParameter("role")
namespaceName, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
var role rbacv1.Role
err = request.ReadEntity(&role)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
role.Name = roleName
patched, err := h.am.PatchNamespaceRole(namespaceName, &role)
if err != nil {
handleError(request, response, err)
return
}
response.WriteEntity(patched)
}
func (h *iamHandler) PatchClusterRole(request *restful.Request, response *restful.Response) {
clusterRoleName := request.PathParameter("clusterrole")
var clusterRole rbacv1.ClusterRole
err := request.ReadEntity(&clusterRole)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
clusterRole.Name = clusterRoleName
patched, err := h.am.PatchClusterRole(&clusterRole)
if err != nil {
handleError(request, response, err)
return
}
response.WriteEntity(patched)
}
func handleError(request *restful.Request, response *restful.Response, err error) {
if errors.IsBadRequest(err) {
api.HandleBadRequest(response, request, err)

View File

@@ -47,16 +47,19 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
To(handler.CreateUser).
Doc("Create user in global scope.").
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Reads(iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/users/{user}").
To(handler.DeleteUser).
Doc("Delete user.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/users/{user}").
To(handler.UpdateUser).
Doc("Update user info.").
Reads(iamv1alpha2.User{}).
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/users/{user}").
@@ -67,7 +70,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/users").
To(handler.ListUsers).
Doc("List all users.").
Doc("List all users in global scope.").
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
@@ -76,30 +79,30 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
To(handler.CreateClusterMembers).
Doc("Add user to current cluster.").
Reads([]Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Returns(http.StatusOK, api.StatusOK, []Member{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/clustermembers/{clustermember}").
To(handler.RemoveClusterMember).
Doc("Delete user from cluster scope.").
Doc("Delete member in cluster scope.").
Param(ws.PathParameter("clustermember", "cluster member's username")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Param(ws.PathParameter("clustermember", "username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/clustermembers/{clustermember}").
To(handler.UpdateClusterMember).
Doc("Update user cluster role bind.").
Doc("Update cluster member role bind.").
Reads(Member{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Param(ws.PathParameter("clustermember", "username")).
Returns(http.StatusOK, api.StatusOK, Member{}).
Param(ws.PathParameter("clustermember", "cluster member's username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clustermembers/{clustermember}").
To(handler.DescribeClusterMember).
Doc("Retrieve user details in cluster.").
Param(ws.PathParameter("clustermember", "username")).
Doc("Retrieve member details in cluster.").
Param(ws.PathParameter("clustermember", "cluster member's username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clustermembers").
To(handler.ListClusterMembers).
Doc("List all users in cluster.").
Doc("List all members in cluster.").
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
@@ -107,105 +110,114 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
To(handler.ListWorkspaceMembers).
Doc("List all members in the specified workspace.").
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}").
To(handler.DescribeWorkspaceMember).
Doc("Retrieve workspace member details.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("workspacemember", "workspace member's username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.POST("/workspaces/{workspace}/workspacemembers").
To(handler.CreateWorkspaceMembers).
Doc("Batch add workspace members.").
Reads([]Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Returns(http.StatusOK, api.StatusOK, []Member{}).
Param(ws.PathParameter("workspace", "workspace name")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/workspaces/{workspace}/workspacemembers/{workspacemember}").
To(handler.UpdateWorkspaceMember).
Doc("Update member in workspace.").
Reads(Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Returns(http.StatusOK, api.StatusOK, Member{}).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("workspacemember", "workspace member's username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/workspacemembers/{workspacemember}").
To(handler.RemoveWorkspaceMember).
Doc("Remove member in workspace.").
Doc("Delete member in workspace scope.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("workspacemember", "workspace member's username")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/members").
To(handler.ListNamespaceMembers).
Doc("List all members in the specified namespace.").
Param(ws.PathParameter("namespace", "namespace")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/members/{member}").
To(handler.DescribeNamespaceMember).
Doc("Retrieve namespace member details.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("member", "namespace member's username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.POST("/namespaces/{namespace}/members").
To(handler.CreateNamespaceMembers).
Doc("Batch add namespace members.").
Reads([]Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Returns(http.StatusOK, api.StatusOK, []Member{}).
Param(ws.PathParameter("namespace", "namespace")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/namespaces/{namespace}/members/{member}").
To(handler.UpdateNamespaceMember).
Doc("Update member in namespace.").
Reads(Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Returns(http.StatusOK, api.StatusOK, Member{}).
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("member", "namespace member's username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/namespaces/{namespace}/members/{member}").
To(handler.RemoveNamespaceMember).
Doc("Remove member in namespace.").
Doc("Delete member in namespace scope.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Param(ws.PathParameter("member", "namespace member's username")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/members").
To(handler.ListNamespaceMembers).
Doc("List all members in the specified namespace.").
Param(ws.PathParameter("namespace", "namespace")).
Doc("List all members in the specified devops project.").
Param(ws.PathParameter("devops", "devops project name")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/members/{member}").
To(handler.DescribeNamespaceMember).
Doc("Retrieve namespace member details.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Doc("Retrieve devops project member details.").
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("member", "devops project member's username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.POST("/devops/{devops}/members").
To(handler.CreateNamespaceMembers).
Doc("Batch add namespace members.").
Doc("Batch add devops project members.").
Reads([]Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Param(ws.PathParameter("namespace", "namespace")).
Returns(http.StatusOK, api.StatusOK, []Member{}).
Param(ws.PathParameter("devops", "devops project name")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/devops/{devops}/members/{member}").
To(handler.UpdateNamespaceMember).
Doc("Update member in namespace.").
Doc("Update member in devops project.").
Reads(Member{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("member", "username")).
Returns(http.StatusOK, api.StatusOK, Member{}).
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("member", "devops project member's username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/devops/{devops}/members/{member}").
To(handler.RemoveNamespaceMember).
Doc("Remove member in namespace.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("member", "username")).
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("member", "devops project member's username")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
// globalroles
ws.Route(ws.POST("/globalroles").
To(handler.CreateGlobalRole).
Doc("Create global role.").
Doc("Create global role. Automatically aggregate policy rules according to annotation.").
Reads(iamv1alpha2.GlobalRole{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
@@ -217,7 +229,14 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/globalroles/{globalrole}").
To(handler.UpdateGlobalRole).
Doc("Update global role.").
Doc("Update global role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("globalrole", "global role name")).
Reads(iamv1alpha2.GlobalRole{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PATCH("/globalroles/{globalrole}").
To(handler.PatchGlobalRole).
Doc("Patch global role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("globalrole", "global role name")).
Reads(iamv1alpha2.GlobalRole{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
@@ -236,7 +255,7 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
// clusterroles
ws.Route(ws.POST("/clusterroles").
To(handler.CreateClusterRole).
Doc("Create cluster role.").
Doc("Create cluster role. Automatically aggregate policy rules according to annotation.").
Reads(rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
@@ -248,7 +267,14 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/clusterroles/{clusterrole}").
To(handler.UpdateClusterRole).
Doc("Update cluster role.").
Doc("Update cluster role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("clusterrole", "cluster role name")).
Reads(rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PATCH("/clusterroles/{clusterrole}").
To(handler.PatchClusterRole).
Doc("Patch cluster role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("clusterrole", "cluster role name")).
Reads(rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
@@ -267,38 +293,52 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
// workspaceroles
ws.Route(ws.POST("/workspaces/{workspace}/workspaceroles").
To(handler.CreateWorkspaceRole).
Doc("Create workspace role.").
Doc("Create workspace role. Automatically aggregate policy rules according to annotation.").
Reads(iamv1alpha2.WorkspaceRole{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}).
Param(ws.PathParameter("workspace", "workspace name")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/workspaceroles/{workspacerole}").
To(handler.DeleteWorkspaceRole).
Doc("Delete workspace role.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("workspacerole", "workspace role name")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PATCH("/workspaces/{workspace}/workspaceroles/{workspacerole}").
To(handler.PatchWorkspaceRole).
Doc("Patch workspace role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("workspacerole", "workspace role name")).
Reads(iamv1alpha2.WorkspaceRole{}).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/workspaces/{workspace}/workspaceroles/{workspacerole}").
To(handler.UpdateWorkspaceRole).
Doc("Update workspace role.").
Doc("Update workspace role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("workspacerole", "workspace role name")).
Reads(iamv1alpha2.WorkspaceRole{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/workspaceroles").
To(handler.ListWorkspaceRoles).
Doc("List all workspace roles.").
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.WorkspaceRole{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/workspaceroles/{workspacerole}").
To(handler.DescribeWorkspaceRole).
Doc("Retrieve workspace role details.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("workspacerole", "workspace role name")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
// roles
ws.Route(ws.POST("/namespaces/{namespace}/roles").
To(handler.CreateNamespaceRole).
Doc("Create role in the specified namespace.").
Doc("Create role in the specified namespace. Automatically aggregate policy rules according to annotation.").
Reads(rbacv1.Role{}).
Param(ws.PathParameter("namespace", "namespace")).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
@@ -312,11 +352,19 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/namespaces/{namespace}/roles/{role}").
To(handler.UpdateNamespaceRole).
Doc("Update namespace role.").
Doc("Update namespace role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("role", "role name")).
Reads(rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Reads(rbacv1.Role{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PATCH("/namespaces/{namespace}/roles/{role}").
To(handler.PatchNamespaceRole).
Doc("Patch namespace role.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("role", "role name")).
Reads(rbacv1.Role{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/roles").
To(handler.ListRoles).
@@ -329,78 +377,86 @@ func AddToContainer(container *restful.Container, im im.IdentityManagementInterf
Doc("Retrieve role details.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("role", "role name")).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
// roles
ws.Route(ws.POST("/devops/{devops}/roles").
To(handler.CreateNamespaceRole).
Doc("Create role in the specified devops project.").
Doc("Create role in the specified devops project. Automatically aggregate policy rules according to annotation.").
Reads(rbacv1.Role{}).
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("devops", "devops project name")).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/devops/{devops}/roles/{role}").
To(handler.DeleteNamespaceRole).
Doc("Delete role in the specified devops project.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("role", "role name")).
Returns(http.StatusOK, api.StatusOK, errors.None).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PUT("/devops/{devops}/roles/{role}").
To(handler.UpdateNamespaceRole).
Doc("Update devops project role.").
Param(ws.PathParameter("namespace", "namespace")).
Doc("Update devops project role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("role", "role name")).
Reads(rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Reads(rbacv1.Role{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.PATCH("/devops/{devops}/roles/{role}").
To(handler.PatchNamespaceRole).
Doc("Patch devops project role. Automatically aggregate policy rules according to annotation.").
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("role", "role name")).
Reads(rbacv1.Role{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/roles").
To(handler.ListRoles).
Doc("List all roles in the specified namespace.").
Param(ws.PathParameter("namespace", "namespace")).
Doc("List all roles in the specified devops project.").
Param(ws.PathParameter("devops", "devops project name")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/roles/{role}").
To(handler.DescribeNamespaceRole).
Doc("Retrieve role details.").
Param(ws.PathParameter("namespace", "namespace")).
Doc("Retrieve devops project role details.").
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("role", "role name")).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/users/{user}/globalroles").
To(handler.RetrieveMemberRoleTemplates).
Doc("Retrieve user's global role templates.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.GlobalRole{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clustermembers/{clustermember}/clusterroles").
To(handler.RetrieveMemberRoleTemplates).
Doc("Retrieve user's role templates in cluster.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Param(ws.PathParameter("clustermember", "cluster member's username")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.ClusterRole{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}/workspaceroles").
To(handler.RetrieveMemberRoleTemplates).
Doc("Retrieve member's role templates in workspace.").
Param(ws.PathParameter("workspace", "workspace")).
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}).
Param(ws.PathParameter("workspacemember", "workspace member's username")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.WorkspaceRole{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/members/{member}/roles").
To(handler.RetrieveMemberRoleTemplates).
Doc("Retrieve member's role templates in namespace.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Param(ws.PathParameter("member", "namespace member's username")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/members/{member}/roles").
To(handler.RetrieveMemberRoleTemplates).
Doc("Retrieve member's role templates in devops project.").
Param(ws.PathParameter("namespace", "namespace")).
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
Param(ws.PathParameter("devops", "devops project name")).
Param(ws.PathParameter("member", "devops project member's username")).
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
container.Add(ws)

View File

@@ -395,12 +395,7 @@ func (h *tenantHandler) PatchNamespace(request *restful.Request, response *restf
return
}
if namespaceName != namespace.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", namespace.Name, namespaceName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
namespace.Name = namespaceName
patched, err := h.tenant.PatchNamespace(workspaceName, &namespace)
@@ -432,12 +427,7 @@ func (h *tenantHandler) PatchWorkspace(request *restful.Request, response *restf
return
}
if workspaceName != workspace.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", workspace.Name, workspaceName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
workspace.Name = workspaceName
patched, err := h.tenant.PatchWorkspace(&workspace)

View File

@@ -22,6 +22,7 @@ import (
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
@@ -52,7 +53,9 @@ type AccessManagementInterface interface {
GetWorkspaceRole(workspace string, name string) (*iamv1alpha2.WorkspaceRole, error)
CreateGlobalRoleBinding(username string, globalRole string) error
CreateOrUpdateWorkspaceRole(workspace string, workspaceRole *iamv1alpha2.WorkspaceRole) (*iamv1alpha2.WorkspaceRole, error)
PatchWorkspaceRole(workspace string, workspaceRole *iamv1alpha2.WorkspaceRole) (*iamv1alpha2.WorkspaceRole, error)
CreateOrUpdateGlobalRole(globalRole *iamv1alpha2.GlobalRole) (*iamv1alpha2.GlobalRole, error)
PatchGlobalRole(globalRole *iamv1alpha2.GlobalRole) (*iamv1alpha2.GlobalRole, error)
DeleteWorkspaceRole(workspace string, name string) error
DeleteGlobalRole(name string) error
CreateOrUpdateClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
@@ -69,6 +72,8 @@ type AccessManagementInterface interface {
RemoveUserFromCluster(username string) error
GetControlledNamespace(devops string) (string, error)
GetControlledWorkspace(namespace string) (string, error)
PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error)
PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error)
}
type amOperator struct {
@@ -244,7 +249,6 @@ func (am *amOperator) ListClusterRoleBindings(username string) ([]*rbacv1.Cluste
}
result := make([]*rbacv1.ClusterRoleBinding, 0)
for _, obj := range roleBindings.Items {
roleBinding := obj.(*rbacv1.ClusterRoleBinding)
if contains(roleBinding.Subjects, username) {
@@ -334,16 +338,13 @@ func (am *amOperator) GetGlobalRole(globalRole string) (*iamv1alpha2.GlobalRole,
}
func (am *amOperator) CreateGlobalRoleBinding(username string, role string) error {
_, err := am.GetGlobalRole(role)
if err != nil {
klog.Error(err)
return err
}
roleBindings, err := am.ListGlobalRoleBindings(username)
if err != nil {
klog.Error(err)
return err
@@ -398,23 +399,18 @@ func (am *amOperator) CreateOrUpdateWorkspaceRole(workspace string, workspaceRol
var aggregateRoles []string
if err := json.Unmarshal([]byte(workspaceRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetWorkspaceRole("", roleName)
if err != nil {
klog.Error(err)
return nil, err
}
workspaceRole.Rules = append(workspaceRole.Rules, role.Rules...)
}
}
var created *iamv1alpha2.WorkspaceRole
var err error
if workspaceRole.ResourceVersion != "" {
created, err = am.ksclient.IamV1alpha2().WorkspaceRoles().Update(workspaceRole)
} else {
@@ -424,17 +420,155 @@ func (am *amOperator) CreateOrUpdateWorkspaceRole(workspace string, workspaceRol
return created, err
}
func (am *amOperator) PatchGlobalRole(globalRole *iamv1alpha2.GlobalRole) (*iamv1alpha2.GlobalRole, error) {
old, err := am.GetGlobalRole(globalRole.Name)
if err != nil {
klog.Error(err)
return nil, err
}
// rules cannot be override
globalRole.Rules = old.Rules
// aggregate roles if annotation has change
if aggregateRolesAnnotation := globalRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]; aggregateRolesAnnotation != "" {
globalRole.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(aggregateRolesAnnotation), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetGlobalRole(roleName)
if err != nil {
klog.Error(err)
return nil, err
}
globalRole.Rules = append(globalRole.Rules, role.Rules...)
}
}
}
data, err := json.Marshal(globalRole)
if err != nil {
return nil, err
}
return am.ksclient.IamV1alpha2().GlobalRoles().Patch(globalRole.Name, types.MergePatchType, data)
}
func (am *amOperator) PatchWorkspaceRole(workspace string, workspaceRole *iamv1alpha2.WorkspaceRole) (*iamv1alpha2.WorkspaceRole, error) {
old, err := am.GetWorkspaceRole(workspace, workspaceRole.Name)
if err != nil {
klog.Error(err)
return nil, err
}
// workspace label cannot be override
if workspaceRole.Labels[tenantv1alpha1.WorkspaceLabel] != "" {
workspaceRole.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
}
// rules cannot be override
workspaceRole.Rules = old.Rules
// aggregate roles if annotation has change
if aggregateRolesAnnotation := workspaceRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]; aggregateRolesAnnotation != "" {
workspaceRole.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(aggregateRolesAnnotation), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetWorkspaceRole("", roleName)
if err != nil {
klog.Error(err)
return nil, err
}
workspaceRole.Rules = append(workspaceRole.Rules, role.Rules...)
}
}
}
data, err := json.Marshal(workspaceRole)
if err != nil {
return nil, err
}
return am.ksclient.IamV1alpha2().WorkspaceRoles().Patch(workspaceRole.Name, types.MergePatchType, data)
}
func (am *amOperator) PatchNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error) {
old, err := am.GetNamespaceRole(namespace, role.Name)
if err != nil {
klog.Error(err)
return nil, err
}
// rules cannot be override
role.Rules = old.Rules
// aggregate roles if annotation has change
if aggregateRolesAnnotation := role.Annotations[iamv1alpha2.AggregationRolesAnnotation]; aggregateRolesAnnotation != "" {
role.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(aggregateRolesAnnotation), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetNamespaceRole(namespace, roleName)
if err != nil {
klog.Error(err)
return nil, err
}
role.Rules = append(role.Rules, role.Rules...)
}
}
}
data, err := json.Marshal(role)
if err != nil {
return nil, err
}
return am.k8sclient.RbacV1().Roles(namespace).Patch(role.Name, types.MergePatchType, data)
}
func (am *amOperator) PatchClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error) {
old, err := am.GetClusterRole(clusterRole.Name)
if err != nil {
klog.Error(err)
return nil, err
}
// rules cannot be override
clusterRole.Rules = old.Rules
// aggregate roles if annotation has change
if aggregateRolesAnnotation := clusterRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]; aggregateRolesAnnotation != "" {
clusterRole.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(aggregateRolesAnnotation), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetClusterRole(roleName)
if err != nil {
klog.Error(err)
return nil, err
}
role.Rules = append(role.Rules, role.Rules...)
}
}
}
data, err := json.Marshal(clusterRole)
if err != nil {
return nil, err
}
return am.k8sclient.RbacV1().ClusterRoles().Patch(clusterRole.Name, types.MergePatchType, data)
}
func (am *amOperator) CreateWorkspaceRoleBinding(username string, workspace string, role string) error {
_, err := am.GetWorkspaceRole(workspace, role)
if err != nil {
klog.Error(err)
return err
}
roleBindings, err := am.ListWorkspaceRoleBindings(username, workspace)
if err != nil {
klog.Error(err)
return err
@@ -482,9 +616,7 @@ func (am *amOperator) CreateWorkspaceRoleBinding(username string, workspace stri
}
func (am *amOperator) CreateClusterRoleBinding(username string, role string) error {
_, err := am.GetClusterRole(role)
if err != nil {
klog.Error(err)
return err
@@ -540,14 +672,12 @@ func (am *amOperator) CreateClusterRoleBinding(username string, role string) err
func (am *amOperator) CreateNamespaceRoleBinding(username string, namespace string, role string) error {
_, err := am.GetNamespaceRole(namespace, role)
if err != nil {
klog.Error(err)
return err
}
roleBindings, err := am.ListRoleBindings(username, namespace)
if err != nil {
klog.Error(err)
return err
@@ -596,7 +726,6 @@ func (am *amOperator) CreateNamespaceRoleBinding(username string, namespace stri
func (am *amOperator) RemoveUserFromWorkspace(username string, workspace string) error {
roleBindings, err := am.ListWorkspaceRoleBindings(username, workspace)
if err != nil {
klog.Error(err)
return err
@@ -619,7 +748,6 @@ func (am *amOperator) RemoveUserFromWorkspace(username string, workspace string)
func (am *amOperator) RemoveUserFromNamespace(username string, namespace string) error {
roleBindings, err := am.ListRoleBindings(username, namespace)
if err != nil {
klog.Error(err)
return err
@@ -640,9 +768,7 @@ func (am *amOperator) RemoveUserFromNamespace(username string, namespace string)
}
func (am *amOperator) RemoveUserFromCluster(username string) error {
roleBindings, err := am.ListClusterRoleBindings(username)
if err != nil {
klog.Error(err)
return err
@@ -663,28 +789,22 @@ func (am *amOperator) RemoveUserFromCluster(username string) error {
}
func (am *amOperator) CreateOrUpdateGlobalRole(globalRole *iamv1alpha2.GlobalRole) (*iamv1alpha2.GlobalRole, error) {
globalRole.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(globalRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetGlobalRole(roleName)
if err != nil {
klog.Error(err)
return nil, err
}
globalRole.Rules = append(globalRole.Rules, role.Rules...)
}
}
var created *iamv1alpha2.GlobalRole
var err error
if globalRole.ResourceVersion != "" {
created, err = am.ksclient.IamV1alpha2().GlobalRoles().Update(globalRole)
} else {
@@ -695,21 +815,15 @@ func (am *amOperator) CreateOrUpdateGlobalRole(globalRole *iamv1alpha2.GlobalRol
}
func (am *amOperator) CreateOrUpdateClusterRole(clusterRole *rbacv1.ClusterRole) (*rbacv1.ClusterRole, error) {
clusterRole.Rules = make([]rbacv1.PolicyRule, 0)
var aggregateRoles []string
if err := json.Unmarshal([]byte(clusterRole.Annotations[iamv1alpha2.AggregationRolesAnnotation]), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetClusterRole(roleName)
if err != nil {
klog.Error(err)
return nil, err
}
clusterRole.Rules = append(clusterRole.Rules, role.Rules...)
}
}
@@ -720,30 +834,24 @@ func (am *amOperator) CreateOrUpdateClusterRole(clusterRole *rbacv1.ClusterRole)
} else {
created, err = am.k8sclient.RbacV1().ClusterRoles().Create(clusterRole)
}
return created, err
}
func (am *amOperator) CreateOrUpdateNamespaceRole(namespace string, role *rbacv1.Role) (*rbacv1.Role, error) {
role.Rules = make([]rbacv1.PolicyRule, 0)
role.Namespace = namespace
var aggregateRoles []string
if err := json.Unmarshal([]byte(role.Annotations[iamv1alpha2.AggregationRolesAnnotation]), &aggregateRoles); err == nil {
for _, roleName := range aggregateRoles {
role, err := am.GetNamespaceRole(namespace, roleName)
if err != nil {
klog.Error(err)
return nil, err
}
role.Rules = append(role.Rules, role.Rules...)
}
}
var created *rbacv1.Role
var err error
if role.ResourceVersion != "" {