feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> * feat: kubesphere 4.0 Signed-off-by: ci-bot <ci-bot@kubesphere.io> --------- Signed-off-by: ci-bot <ci-bot@kubesphere.io> Co-authored-by: ks-ci-bot <ks-ci-bot@example.com> Co-authored-by: joyceliu <joyceliu@yunify.com>
This commit is contained in:
committed by
GitHub
parent
b5015ec7b9
commit
447a51f08b
File diff suppressed because it is too large
Load Diff
@@ -1,643 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha2
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
v1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
iamv1alpha2 "kubesphere.io/api/iam/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/group"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
GroupName = "iam.kubesphere.io"
|
||||
)
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(container *restful.Container, im im.IdentityManagementInterface, am am.AccessManagementInterface, group group.GroupOperator, authorizer authorizer.Authorizer) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
handler := newIAMHandler(im, am, group, authorizer)
|
||||
|
||||
// users
|
||||
ws.Route(ws.POST("/users").
|
||||
To(handler.CreateUser).
|
||||
Doc("Create a global user account.").
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Reads(iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
ws.Route(ws.DELETE("/users/{user}").
|
||||
To(handler.DeleteUser).
|
||||
Doc("Delete the specified user.").
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
ws.Route(ws.PUT("/users/{user}").
|
||||
To(handler.UpdateUser).
|
||||
Doc("Update user profile.").
|
||||
Reads(iamv1alpha2.User{}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
ws.Route(ws.PUT("/users/{user}/password").
|
||||
To(handler.ModifyPassword).
|
||||
Doc("Reset password of the specified user.").
|
||||
Reads(PasswordReset{}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
ws.Route(ws.GET("/users/{user}").
|
||||
To(handler.DescribeUser).
|
||||
Doc("Retrieve user details.").
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
ws.Route(ws.GET("/users").
|
||||
To(handler.ListUsers).
|
||||
Doc("List all users.").
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserTag}))
|
||||
|
||||
ws.Route(ws.GET("/users/{user}/loginrecords").
|
||||
To(handler.ListUserLoginRecords).
|
||||
Param(ws.PathParameter("user", "username of the user")).
|
||||
Doc("List login records of the specified user.").
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.LoginRecord{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourceTag}))
|
||||
|
||||
// clustermembers
|
||||
ws.Route(ws.POST("/clustermembers").
|
||||
To(handler.CreateClusterMembers).
|
||||
Doc("Add members to current cluster in bulk.").
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterMemberTag}))
|
||||
ws.Route(ws.DELETE("/clustermembers/{clustermember}").
|
||||
To(handler.RemoveClusterMember).
|
||||
Doc("Delete a member from current cluster.").
|
||||
Param(ws.PathParameter("clustermember", "cluster member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterMemberTag}))
|
||||
ws.Route(ws.PUT("/clustermembers/{clustermember}").
|
||||
To(handler.UpdateClusterMember).
|
||||
Doc("Update the cluster role bind of the member.").
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, Member{}).
|
||||
Param(ws.PathParameter("clustermember", "cluster member's username")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterMemberTag}))
|
||||
ws.Route(ws.GET("/clustermembers/{clustermember}").
|
||||
To(handler.DescribeClusterMember).
|
||||
Doc("Retrieve the cluster role of the specified member.").
|
||||
Param(ws.PathParameter("clustermember", "cluster member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterMemberTag}))
|
||||
ws.Route(ws.GET("/clustermembers").
|
||||
To(handler.ListClusterMembers).
|
||||
Doc("List all members in cluster.").
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.User{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterMemberTag}))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers").
|
||||
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.WorkspaceMemberTag}))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(handler.DescribeWorkspaceMember).
|
||||
Doc("Retrieve the workspace role of the specified member.").
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("workspacemember", "workspace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceMemberTag}))
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/workspacemembers").
|
||||
To(handler.CreateWorkspaceMembers).
|
||||
Doc("Add members to current cluster in bulk.").
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceMemberTag}))
|
||||
ws.Route(ws.PUT("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(handler.UpdateWorkspaceMember).
|
||||
Doc("Update the workspace role bind of the member.").
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, Member{}).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("workspacemember", "workspace member's username")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceMemberTag}))
|
||||
ws.Route(ws.DELETE("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(handler.RemoveWorkspaceMember).
|
||||
Doc("Delete a member from the workspace.").
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("workspacemember", "workspace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceMemberTag}))
|
||||
|
||||
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.NamespaceMemberTag}))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/members/{member}").
|
||||
To(handler.DescribeNamespaceMember).
|
||||
Doc("Retrieve the role of the specified member.").
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Param(ws.PathParameter("member", "namespace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.User{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceMemberTag}))
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/members").
|
||||
To(handler.CreateNamespaceMembers).
|
||||
Doc("Add members to the namespace in bulk.").
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}).
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceMemberTag}))
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/members/{member}").
|
||||
To(handler.UpdateNamespaceMember).
|
||||
Doc("Update the role bind of the member.").
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, Member{}).
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Param(ws.PathParameter("member", "namespace member's username")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceMemberTag}))
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/members/{member}").
|
||||
To(handler.RemoveNamespaceMember).
|
||||
Doc("Delete a member from the namespace.").
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Param(ws.PathParameter("member", "namespace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceMemberTag}))
|
||||
|
||||
ws.Route(ws.GET("/devops/{devops}/members").
|
||||
To(handler.ListNamespaceMembers).
|
||||
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.DevOpsProjectMemberTag}))
|
||||
ws.Route(ws.GET("/devops/{devops}/members/{member}").
|
||||
To(handler.DescribeNamespaceMember).
|
||||
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.DevOpsProjectMemberTag}))
|
||||
ws.Route(ws.POST("/devops/{devops}/members").
|
||||
To(handler.CreateNamespaceMembers).
|
||||
Doc("Add members to the DevOps project in bulk.").
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}).
|
||||
Param(ws.PathParameter("devops", "devops project name")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectMemberTag}))
|
||||
ws.Route(ws.PUT("/devops/{devops}/members/{member}").
|
||||
To(handler.UpdateNamespaceMember).
|
||||
Doc("Update the role bind of the member.").
|
||||
Reads(Member{}).
|
||||
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.DevOpsProjectMemberTag}))
|
||||
ws.Route(ws.DELETE("/devops/{devops}/members/{member}").
|
||||
To(handler.RemoveNamespaceMember).
|
||||
Doc("Delete a member from the DevOps project.").
|
||||
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.DevOpsProjectMemberTag}))
|
||||
|
||||
// globalroles
|
||||
ws.Route(ws.POST("/globalroles").
|
||||
To(handler.CreateGlobalRole).
|
||||
Doc("Create global role.").
|
||||
Deprecate().
|
||||
Reads(iamv1alpha2.GlobalRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.DELETE("/globalroles/{globalrole}").
|
||||
To(handler.DeleteGlobalRole).
|
||||
Doc("Delete global role.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("globalrole", "global role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.PUT("/globalroles/{globalrole}").
|
||||
To(handler.UpdateGlobalRole).
|
||||
Doc("Update global role.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("globalrole", "global role name")).
|
||||
Reads(iamv1alpha2.GlobalRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.PATCH("/globalroles/{globalrole}").
|
||||
To(handler.PatchGlobalRole).
|
||||
Deprecate().
|
||||
Doc("Patch global role.").
|
||||
Param(ws.PathParameter("globalrole", "global role name")).
|
||||
Reads(iamv1alpha2.GlobalRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.GET("/globalroles").
|
||||
To(handler.ListGlobalRoles).
|
||||
Doc("List all global roles.").
|
||||
Deprecate().
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.GlobalRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.GET("/globalroles/{globalrole}").
|
||||
To(handler.DescribeGlobalRole).
|
||||
Param(ws.PathParameter("globalrole", "global role name")).
|
||||
Doc("Retrieve global role details.").
|
||||
Deprecate().
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.GlobalRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
|
||||
// clusterroles
|
||||
ws.Route(ws.POST("/clusterroles").
|
||||
To(handler.CreateClusterRole).
|
||||
Doc("Create cluster role.").
|
||||
Deprecate().
|
||||
Reads(rbacv1.ClusterRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
ws.Route(ws.DELETE("/clusterroles/{clusterrole}").
|
||||
To(handler.DeleteClusterRole).
|
||||
Doc("Delete cluster role.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("clusterrole", "cluster role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
ws.Route(ws.PUT("/clusterroles/{clusterrole}").
|
||||
To(handler.UpdateClusterRole).
|
||||
Doc("Update cluster role.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("clusterrole", "cluster role name")).
|
||||
Reads(rbacv1.ClusterRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
ws.Route(ws.PATCH("/clusterroles/{clusterrole}").
|
||||
To(handler.PatchClusterRole).
|
||||
Doc("Patch cluster role.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("clusterrole", "cluster role name")).
|
||||
Reads(rbacv1.ClusterRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
ws.Route(ws.GET("/clusterroles").
|
||||
To(handler.ListClusterRoles).
|
||||
Doc("List all cluster roles.").
|
||||
Deprecate().
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.ClusterRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
ws.Route(ws.GET("/clusterroles/{clusterrole}").
|
||||
To(handler.DescribeClusterRole).
|
||||
Param(ws.PathParameter("clusterrole", "cluster role name")).
|
||||
Doc("Retrieve cluster role details.").
|
||||
Deprecate().
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
|
||||
// workspaceroles
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/workspaceroles").
|
||||
To(handler.CreateWorkspaceRole).
|
||||
Doc("Create workspace role.").
|
||||
Deprecate().
|
||||
Reads(iamv1alpha2.WorkspaceRole{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.WorkspaceRole{}).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceRoleTag}))
|
||||
ws.Route(ws.DELETE("/workspaces/{workspace}/workspaceroles/{workspacerole}").
|
||||
To(handler.DeleteWorkspaceRole).
|
||||
Doc("Delete workspace role.").
|
||||
Deprecate().
|
||||
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.WorkspaceRoleTag}))
|
||||
ws.Route(ws.PATCH("/workspaces/{workspace}/workspaceroles/{workspacerole}").
|
||||
To(handler.PatchWorkspaceRole).
|
||||
Doc("Patch workspace role.").
|
||||
Deprecate().
|
||||
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.WorkspaceRoleTag}))
|
||||
ws.Route(ws.PUT("/workspaces/{workspace}/workspaceroles/{workspacerole}").
|
||||
To(handler.UpdateWorkspaceRole).
|
||||
Doc("Update workspace role.").
|
||||
Deprecate().
|
||||
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.WorkspaceRoleTag}))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspaceroles").
|
||||
To(handler.ListWorkspaceRoles).
|
||||
Doc("List all workspace roles.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.WorkspaceRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceRoleTag}))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspaceroles/{workspacerole}").
|
||||
To(handler.DescribeWorkspaceRole).
|
||||
Doc("Retrieve workspace role details.").
|
||||
Deprecate().
|
||||
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.WorkspaceRoleTag}))
|
||||
|
||||
// roles
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/roles").
|
||||
To(handler.CreateNamespaceRole).
|
||||
Doc("Create role in the specified namespace.").
|
||||
Deprecate().
|
||||
Reads(rbacv1.Role{}).
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/roles/{role}").
|
||||
To(handler.DeleteNamespaceRole).
|
||||
Doc("Delete role in the specified namespace.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Param(ws.PathParameter("role", "role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/roles/{role}").
|
||||
To(handler.UpdateNamespaceRole).
|
||||
Doc("Update namespace role.").
|
||||
Deprecate().
|
||||
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.NamespaceRoleTag}))
|
||||
ws.Route(ws.PATCH("/namespaces/{namespace}/roles/{role}").
|
||||
To(handler.PatchNamespaceRole).
|
||||
Doc("Patch namespace role.").
|
||||
Deprecate().
|
||||
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.NamespaceRoleTag}))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/roles").
|
||||
To(handler.ListRoles).
|
||||
Doc("List all roles in the specified namespace.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/roles/{role}").
|
||||
To(handler.DescribeNamespaceRole).
|
||||
Doc("Retrieve role details.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("namespace", "namespace")).
|
||||
Param(ws.PathParameter("role", "role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
|
||||
|
||||
// roles
|
||||
ws.Route(ws.POST("/devops/{devops}/roles").
|
||||
To(handler.CreateNamespaceRole).
|
||||
Doc("Create role in the specified devops project.").
|
||||
Deprecate().
|
||||
Reads(rbacv1.Role{}).
|
||||
Param(ws.PathParameter("devops", "devops project name")).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectRoleTag}))
|
||||
ws.Route(ws.DELETE("/devops/{devops}/roles/{role}").
|
||||
To(handler.DeleteNamespaceRole).
|
||||
Doc("Delete role in the specified devops project.").
|
||||
Deprecate().
|
||||
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.DevOpsProjectRoleTag}))
|
||||
ws.Route(ws.PUT("/devops/{devops}/roles/{role}").
|
||||
To(handler.UpdateNamespaceRole).
|
||||
Doc("Update devops project role.").
|
||||
Deprecate().
|
||||
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.DevOpsProjectRoleTag}))
|
||||
ws.Route(ws.PATCH("/devops/{devops}/roles/{role}").
|
||||
To(handler.PatchNamespaceRole).
|
||||
Doc("Patch devops project role.").
|
||||
Deprecate().
|
||||
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.DevOpsProjectRoleTag}))
|
||||
ws.Route(ws.GET("/devops/{devops}/roles").
|
||||
To(handler.ListRoles).
|
||||
Doc("List all roles in the specified devops project.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("devops", "devops project name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectRoleTag}))
|
||||
ws.Route(ws.GET("/devops/{devops}/roles/{role}").
|
||||
To(handler.DescribeNamespaceRole).
|
||||
Doc("Retrieve devops project role details.").
|
||||
Deprecate().
|
||||
Param(ws.PathParameter("devops", "devops project name")).
|
||||
Param(ws.PathParameter("role", "role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, rbacv1.Role{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.DevOpsProjectRoleTag}))
|
||||
|
||||
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, api.ListResult{Items: []interface{}{iamv1alpha2.GlobalRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GlobalRoleTag}))
|
||||
ws.Route(ws.GET("/clustermembers/{clustermember}/clusterroles").
|
||||
To(handler.RetrieveMemberRoleTemplates).
|
||||
Doc("Retrieve user's role templates in cluster.").
|
||||
Param(ws.PathParameter("clustermember", "cluster member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.ClusterRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterRoleTag}))
|
||||
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("workspacemember", "workspace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{iamv1alpha2.WorkspaceRole{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.WorkspaceRoleTag}))
|
||||
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("member", "namespace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []interface{}{rbacv1.Role{}}}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceRoleTag}))
|
||||
ws.Route(ws.GET("/devops/{devops}/members/{member}/roles").
|
||||
To(handler.RetrieveMemberRoleTemplates).
|
||||
Doc("Retrieve member's role templates in devops project.").
|
||||
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.DevOpsProjectRoleTag}))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/groups").
|
||||
To(handler.ListWorkspaceGroups).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
|
||||
Doc("List groups of the specified workspace.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/groups/{group}").
|
||||
To(handler.DescribeGroup).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("group", "group name")).
|
||||
Doc("Retrieve group details.").
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.DELETE("/workspaces/{workspace}/groups/{group}").
|
||||
To(handler.DeleteGroup).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("group", "group name")).
|
||||
Doc("Delete group.").
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/groups").
|
||||
To(handler.CreateGroup).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Doc("Create Group").
|
||||
Reads(iamv1alpha2.Group{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.PUT("/workspaces/{workspace}/groups/{group}/").
|
||||
To(handler.UpdateGroup).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("group", "group name")).
|
||||
Doc("Update Group").
|
||||
Reads(iamv1alpha2.Group{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.Group{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
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).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("group", "group name")).
|
||||
Doc("Retrieve group's members in the workspace.").
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{}).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/rolebindings").
|
||||
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}/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.DELETE("/workspaces/{workspace}/groupbindings/{groupbinding}").
|
||||
To(handler.DeleteGroupBinding).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Param(ws.PathParameter("groupbinding", "groupbinding name")).
|
||||
Doc("Delete GroupBinding to remove user from the group.").
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/groupbindings").
|
||||
To(handler.CreateGroupBinding).
|
||||
Param(ws.PathParameter("workspace", "workspace name")).
|
||||
Doc("Create GroupBinding to add a user to the group").
|
||||
Reads([]GroupMember{}).
|
||||
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.").
|
||||
Deprecate().
|
||||
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("/namespaces/{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.").
|
||||
Deprecate().
|
||||
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.").
|
||||
Deprecate().
|
||||
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.").
|
||||
Deprecate().
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None).
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{constants.GroupTag}))
|
||||
|
||||
container.Add(ws)
|
||||
return nil
|
||||
}
|
||||
870
pkg/kapis/iam/v1beta1/handler.go
Normal file
870
pkg/kapis/iam/v1beta1/handler.go
Normal file
@@ -0,0 +1,870 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/rbac"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/rest"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
authuser "k8s.io/apiserver/pkg/authentication/user"
|
||||
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
apirequest "kubesphere.io/kubesphere/pkg/apiserver/request"
|
||||
"kubesphere.io/kubesphere/pkg/models/auth"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/am"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
||||
resv1beta1 "kubesphere.io/kubesphere/pkg/models/resources/v1beta1"
|
||||
servererr "kubesphere.io/kubesphere/pkg/server/errors"
|
||||
)
|
||||
|
||||
type Member struct {
|
||||
Username string `json:"username"`
|
||||
RoleRef string `json:"roleRef"`
|
||||
}
|
||||
|
||||
type GroupMember struct {
|
||||
UserName string `json:"userName"`
|
||||
GroupName string `json:"groupName"`
|
||||
}
|
||||
|
||||
type PasswordReset struct {
|
||||
CurrentPassword string `json:"currentPassword"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type TOTOAuthKeyBind struct {
|
||||
AuthKey string `json:"authKey"`
|
||||
OTP string `json:"otp"`
|
||||
}
|
||||
|
||||
type TOTPAuthKey struct {
|
||||
AuthKey string `json:"authKey"`
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
im im.IdentityManagementInterface
|
||||
am am.AccessManagementInterface
|
||||
authorizer authorizer.Authorizer
|
||||
}
|
||||
|
||||
func NewHandler(im im.IdentityManagementInterface, am am.AccessManagementInterface) rest.Handler {
|
||||
return &handler{im: im, am: am, authorizer: rbac.NewRBACAuthorizer(am)}
|
||||
}
|
||||
|
||||
func NewFakeHandler() rest.Handler {
|
||||
return &handler{}
|
||||
}
|
||||
|
||||
func (h *handler) DescribeUser(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
user, err := h.im.DescribeUser(username)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
api.HandleNotFound(response, request, err)
|
||||
return
|
||||
}
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(user)
|
||||
}
|
||||
|
||||
func (h *handler) ListUsers(request *restful.Request, response *restful.Response) {
|
||||
globalRole := request.QueryParameter("globalrole")
|
||||
if globalRole != "" {
|
||||
result, err := h.listUserByGlobalRole(globalRole)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(result)
|
||||
return
|
||||
}
|
||||
queryParam := query.ParseQueryParameter(request)
|
||||
result, err := h.im.ListUsers(queryParam)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) listUserByGlobalRole(roleName string) (*api.ListResult, error) {
|
||||
result := &api.ListResult{Items: make([]runtime.Object, 0)}
|
||||
bindings, err := h.am.ListGlobalRoleBindings("", roleName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, binding := range bindings {
|
||||
for _, subject := range binding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
user, err := h.im.DescribeUser(subject.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Items = append(result.Items, user)
|
||||
result.TotalItems += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (h *handler) CreateUser(req *restful.Request, resp *restful.Response) {
|
||||
var user iamv1beta1.User
|
||||
err := req.ReadEntity(&user)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(resp, req, err)
|
||||
return
|
||||
}
|
||||
operator, ok := apirequest.UserFrom(req.Request.Context())
|
||||
if ok && operator.GetName() == iamv1beta1.PreRegistrationUser {
|
||||
extra := operator.GetExtra()
|
||||
// The token used for registration must contain additional information
|
||||
if len(extra[iamv1beta1.ExtraIdentityProvider]) != 1 || len(extra[iamv1beta1.ExtraUID]) != 1 {
|
||||
err = errors.NewBadRequest("invalid registration token")
|
||||
api.HandleBadRequest(resp, req, err)
|
||||
return
|
||||
}
|
||||
if user.Labels == nil {
|
||||
user.Labels = make(map[string]string)
|
||||
}
|
||||
user.Labels[iamv1beta1.IdentifyProviderLabel] = extra[iamv1beta1.ExtraIdentityProvider][0]
|
||||
user.Labels[iamv1beta1.OriginUIDLabel] = extra[iamv1beta1.ExtraUID][0]
|
||||
delete(user.Annotations, iamv1beta1.GlobalRoleAnnotation)
|
||||
}
|
||||
|
||||
globalRole := user.Annotations[iamv1beta1.GlobalRoleAnnotation]
|
||||
if globalRole != "" {
|
||||
if _, err = h.am.GetGlobalRole(globalRole); err != nil {
|
||||
api.HandleError(resp, req, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
created, err := h.im.CreateUser(&user)
|
||||
if err != nil {
|
||||
api.HandleError(resp, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
if globalRole != "" {
|
||||
if err := h.am.CreateOrUpdateGlobalRoleBinding(user.Name, globalRole); err != nil {
|
||||
api.HandleError(resp, req, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// ensure encrypted password will not be output
|
||||
created.Spec.EncryptedPassword = ""
|
||||
|
||||
resp.WriteEntity(created)
|
||||
}
|
||||
|
||||
func (h *handler) UpdateUser(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
var user iamv1beta1.User
|
||||
err := request.ReadEntity(&user)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if username != user.Name {
|
||||
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", user.Name, username)
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
globalRole := user.Annotations[iamv1beta1.GlobalRoleAnnotation]
|
||||
|
||||
updated, err := h.im.UpdateUser(&user)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
operator, ok := apirequest.UserFrom(request.Request.Context())
|
||||
if globalRole != "" && ok {
|
||||
if err = h.updateGlobalRoleBinding(operator, updated, globalRole); err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteEntity(updated)
|
||||
}
|
||||
|
||||
func (h *handler) updateGlobalRoleBinding(operator authuser.Info, user *iamv1beta1.User, globalRole string) error {
|
||||
oldGlobalRole, err := h.am.GetGlobalRoleOfUser(user.Name)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
if oldGlobalRole != nil && oldGlobalRole.Name == globalRole {
|
||||
return nil
|
||||
}
|
||||
userManagement := authorizer.AttributesRecord{
|
||||
Resource: iamv1beta1.ResourcesPluralUser,
|
||||
Verb: "update",
|
||||
ResourceScope: apirequest.GlobalScope,
|
||||
ResourceRequest: true,
|
||||
User: operator,
|
||||
}
|
||||
decision, _, err := h.authorizer.Authorize(userManagement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if decision != authorizer.DecisionAllow {
|
||||
return errors.NewForbidden(iamv1beta1.Resource(iamv1beta1.ResourcesSingularUser),
|
||||
user.Name, fmt.Errorf("update global role binding is not allowed"))
|
||||
}
|
||||
if err := h.am.CreateOrUpdateGlobalRoleBinding(user.Name, globalRole); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *handler) ModifyPassword(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
var passwordReset PasswordReset
|
||||
err := request.ReadEntity(&passwordReset)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
operator, ok := apirequest.UserFrom(request.Request.Context())
|
||||
|
||||
if !ok {
|
||||
err = errors.NewInternalError(fmt.Errorf("cannot obtain user info"))
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
userManagement := authorizer.AttributesRecord{
|
||||
Resource: "users/password",
|
||||
Verb: "update",
|
||||
ResourceScope: apirequest.GlobalScope,
|
||||
ResourceRequest: true,
|
||||
User: operator,
|
||||
}
|
||||
|
||||
decision, _, err := h.authorizer.Authorize(userManagement)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
// only the user manager can modify the password without verifying the old password
|
||||
// if old password is defined must be verified
|
||||
if decision != authorizer.DecisionAllow || passwordReset.CurrentPassword != "" {
|
||||
if err = h.im.PasswordVerify(username, passwordReset.CurrentPassword); err != nil {
|
||||
if err == auth.IncorrectPasswordError {
|
||||
err = errors.NewBadRequest("incorrect old password")
|
||||
}
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = h.im.ModifyPassword(username, passwordReset.Password)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) DeleteUser(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
|
||||
err := h.im.DeleteUser(username)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) ListUserLoginRecords(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("user")
|
||||
queryParam := query.ParseQueryParameter(request)
|
||||
result, err := h.im.ListLoginRecords(username, queryParam)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) ListClusterMembers(request *restful.Request, response *restful.Response) {
|
||||
roleName := request.QueryParameter("clusterrole")
|
||||
result := &api.ListResult{Items: make([]runtime.Object, 0)}
|
||||
bindings, err := h.am.ListClusterRoleBindings("", roleName)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
filtered := []runtime.Object{}
|
||||
for _, binding := range bindings {
|
||||
for _, subject := range binding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
filtered = append(filtered, &iamv1beta1.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: subject.Name,
|
||||
Annotations: map[string]string{
|
||||
iamv1beta1.ClusterRoleAnnotation: binding.RoleRef.Name,
|
||||
},
|
||||
},
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list, _, totalCount := resv1beta1.DefaultList(filtered, query.ParseQueryParameter(request), resv1beta1.DefaultCompare, resv1beta1.DefaultFilter)
|
||||
result.Items = list
|
||||
result.TotalItems = totalCount
|
||||
|
||||
_ = response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) ListWorkspaceMembers(request *restful.Request, response *restful.Response) {
|
||||
workspace := request.PathParameter("workspace")
|
||||
roleName := request.QueryParameter("workspacerole")
|
||||
bindings, err := h.am.ListWorkspaceRoleBindings("", roleName, nil, workspace)
|
||||
result := &api.ListResult{Items: make([]runtime.Object, 0)}
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
filtered := []runtime.Object{}
|
||||
for _, binding := range bindings {
|
||||
for _, subject := range binding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
filtered = append(filtered, &iamv1beta1.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: subject.Name,
|
||||
Annotations: map[string]string{
|
||||
iamv1beta1.WorkspaceRoleAnnotation: binding.RoleRef.Name,
|
||||
},
|
||||
},
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
list, _, totalCount := resv1beta1.DefaultList(filtered, query.ParseQueryParameter(request), resv1beta1.DefaultCompare, resv1beta1.DefaultFilter)
|
||||
result.Items = list
|
||||
result.TotalItems = totalCount
|
||||
|
||||
_ = response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) ListNamespaceMembers(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
roleName := request.QueryParameter("role")
|
||||
bindings, err := h.am.ListRoleBindings("", roleName, nil, namespace)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
result := &api.ListResult{Items: make([]runtime.Object, 0)}
|
||||
filtered := []runtime.Object{}
|
||||
for _, binding := range bindings {
|
||||
for _, subject := range binding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
filtered = append(filtered, &iamv1beta1.User{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: subject.Name,
|
||||
Annotations: map[string]string{
|
||||
iamv1beta1.RoleAnnotation: binding.RoleRef.Name,
|
||||
},
|
||||
},
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list, _, totalCount := resv1beta1.DefaultList(filtered, query.ParseQueryParameter(request), resv1beta1.DefaultCompare, resv1beta1.DefaultFilter)
|
||||
result.Items = list
|
||||
result.TotalItems = totalCount
|
||||
|
||||
_ = response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) CreateClusterMembers(request *restful.Request, response *restful.Response) {
|
||||
var members []Member
|
||||
err := request.ReadEntity(&members)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, member := range members {
|
||||
err := h.am.CreateOrUpdateClusterRoleBinding(member.Username, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteEntity(members)
|
||||
}
|
||||
|
||||
func (h *handler) RemoveClusterMember(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("clustermember")
|
||||
|
||||
err := h.am.RemoveUserFromCluster(username)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) CreateNamespaceMembers(request *restful.Request, response *restful.Response) {
|
||||
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
var members []Member
|
||||
err := request.ReadEntity(&members)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, member := range members {
|
||||
err := h.am.CreateOrUpdateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteEntity(members)
|
||||
}
|
||||
|
||||
func (h *handler) RemoveNamespaceMember(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("member")
|
||||
namespace := request.PathParameter("namespace")
|
||||
|
||||
err := h.am.RemoveUserFromNamespace(username, namespace)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) ListRoleTemplateOfUser(request *restful.Request, response *restful.Response) {
|
||||
username := request.PathParameter("username")
|
||||
scope := request.QueryParameter("scope")
|
||||
namespace := request.QueryParameter("namespace")
|
||||
workspace := request.QueryParameter("workspace")
|
||||
|
||||
userInfo, exist := apirequest.UserFrom(request.Request.Context())
|
||||
if !exist {
|
||||
err := errors.NewInternalError(fmt.Errorf("cannot obtain user info"))
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if userInfo.GetName() != username {
|
||||
userManagement := authorizer.AttributesRecord{
|
||||
Resource: "users",
|
||||
Verb: "get",
|
||||
ResourceScope: apirequest.GlobalScope,
|
||||
ResourceRequest: true,
|
||||
User: userInfo,
|
||||
}
|
||||
|
||||
decision, _, err := h.authorizer.Authorize(userManagement)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if decision != authorizer.DecisionAllow {
|
||||
err := errors.NewForbidden(iamv1beta1.Resource("users"), username, fmt.Errorf("not allow to get users"))
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result := &api.ListResult{Items: make([]runtime.Object, 0)}
|
||||
var roleTemplateNames []string
|
||||
|
||||
switch scope {
|
||||
case iamv1beta1.ScopeGlobal:
|
||||
globalRole, err := h.am.GetGlobalRoleOfUser(username)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
if globalRole != nil && globalRole.AggregationRoleTemplates != nil {
|
||||
roleTemplateNames = globalRole.AggregationRoleTemplates.TemplateNames
|
||||
}
|
||||
case iamv1beta1.ScopeWorkspace:
|
||||
workspaceRoles, err := h.am.GetWorkspaceRoleOfUser(username, nil, workspace)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
for _, workspaceRole := range workspaceRoles {
|
||||
if workspaceRole.AggregationRoleTemplates != nil {
|
||||
roleTemplateNames = append(roleTemplateNames, workspaceRole.AggregationRoleTemplates.TemplateNames...)
|
||||
}
|
||||
}
|
||||
case iamv1beta1.ScopeCluster:
|
||||
clusterRole, err := h.am.GetClusterRoleOfUser(username)
|
||||
if err != nil && !errors.IsNotFound(err) {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
if clusterRole != nil && clusterRole.AggregationRoleTemplates != nil {
|
||||
roleTemplateNames = clusterRole.AggregationRoleTemplates.TemplateNames
|
||||
}
|
||||
case iamv1beta1.ScopeNamespace:
|
||||
roles, err := h.am.GetNamespaceRoleOfUser(username, nil, namespace)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
for _, role := range roles {
|
||||
if role.AggregationRoleTemplates != nil {
|
||||
roleTemplateNames = append(roleTemplateNames, role.AggregationRoleTemplates.TemplateNames...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range roleTemplateNames {
|
||||
template, err := h.am.GetRoleTemplate(name)
|
||||
if err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
continue
|
||||
}
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
result.Items = append(result.Items, template)
|
||||
result.TotalItems += 1
|
||||
}
|
||||
|
||||
_ = response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) CreateSubjectAccessReview(request *restful.Request, response *restful.Response) {
|
||||
data := make(map[string]interface{})
|
||||
err := request.ReadEntity(&data)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
uns := unstructured.Unstructured{Object: data}
|
||||
unsConverter := runtime.DefaultUnstructuredConverter
|
||||
if uns.IsList() {
|
||||
list := &iamv1beta1.SubjectAccessReviewList{}
|
||||
err := unsConverter.FromUnstructured(uns.Object, list)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
result, err := h.handleList(*list)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
_ = response.WriteEntity(result)
|
||||
return
|
||||
}
|
||||
|
||||
review := &iamv1beta1.SubjectAccessReview{}
|
||||
err = unsConverter.FromUnstructured(uns.Object, review)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.handleSingle(*review)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
_ = response.WriteEntity(result)
|
||||
}
|
||||
|
||||
func (h *handler) handleList(list iamv1beta1.SubjectAccessReviewList) (iamv1beta1.SubjectAccessReviewList, error) {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
errList []error
|
||||
newItems []iamv1beta1.SubjectAccessReview
|
||||
accessReviewMux sync.Mutex
|
||||
errMux sync.Mutex
|
||||
)
|
||||
for _, review := range list.Items {
|
||||
wg.Add(1)
|
||||
go func(review iamv1beta1.SubjectAccessReview) {
|
||||
defer wg.Done()
|
||||
accessReview, err := h.handleSingle(review)
|
||||
if err != nil {
|
||||
errMux.Lock()
|
||||
errList = append(errList, err)
|
||||
errMux.Unlock()
|
||||
return
|
||||
}
|
||||
accessReviewMux.Lock()
|
||||
newItems = append(newItems, accessReview)
|
||||
accessReviewMux.Unlock()
|
||||
}(review)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
list.Items = newItems
|
||||
return list, utilerrors.NewAggregate(errList)
|
||||
}
|
||||
|
||||
func (h *handler) handleSingle(review iamv1beta1.SubjectAccessReview) (iamv1beta1.SubjectAccessReview, error) {
|
||||
decision, reason, err := h.authorizer.Authorize(prepareAttribute(review))
|
||||
if err != nil {
|
||||
return iamv1beta1.SubjectAccessReview{}, err
|
||||
}
|
||||
|
||||
review.Status = iamv1beta1.SubjectAccessReviewStatus{
|
||||
Allowed: decision == authorizer.DecisionAllow,
|
||||
Denied: decision == authorizer.DecisionDeny,
|
||||
Reason: reason,
|
||||
}
|
||||
|
||||
return review, nil
|
||||
}
|
||||
|
||||
func prepareAttribute(subjectAccessReview iamv1beta1.SubjectAccessReview) authorizer.AttributesRecord {
|
||||
attr := authorizer.AttributesRecord{
|
||||
User: &iamv1beta1.DefaultInfo{
|
||||
Name: subjectAccessReview.Spec.User,
|
||||
UID: subjectAccessReview.Spec.UID,
|
||||
Groups: subjectAccessReview.Spec.Groups,
|
||||
},
|
||||
}
|
||||
|
||||
if subjectAccessReview.Spec.ResourceAttributes != nil {
|
||||
attr.ResourceRequest = true
|
||||
attr.Verb = subjectAccessReview.Spec.ResourceAttributes.Verb
|
||||
attr.APIGroup = subjectAccessReview.Spec.ResourceAttributes.Group
|
||||
attr.APIVersion = subjectAccessReview.Spec.ResourceAttributes.Version
|
||||
attr.Workspace = subjectAccessReview.Spec.ResourceAttributes.Workspace
|
||||
attr.Namespace = subjectAccessReview.Spec.ResourceAttributes.Namespace
|
||||
attr.Resource = subjectAccessReview.Spec.ResourceAttributes.Resource
|
||||
attr.Name = subjectAccessReview.Spec.ResourceAttributes.Name
|
||||
attr.Subresource = subjectAccessReview.Spec.ResourceAttributes.Subresource
|
||||
if attr.Namespace != "" {
|
||||
attr.ResourceScope = apirequest.NamespaceScope
|
||||
} else if attr.Workspace != "" {
|
||||
attr.ResourceScope = apirequest.WorkspaceScope
|
||||
} else {
|
||||
attr.ResourceScope = subjectAccessReview.Spec.ResourceAttributes.ResourceScope
|
||||
}
|
||||
} else if subjectAccessReview.Spec.NonResourceAttributes != nil {
|
||||
attr.ResourceRequest = false
|
||||
attr.Verb = subjectAccessReview.Spec.NonResourceAttributes.Verb
|
||||
attr.Path = subjectAccessReview.Spec.NonResourceAttributes.Path
|
||||
}
|
||||
return attr
|
||||
}
|
||||
|
||||
func (h *handler) CreateWorkspaceMembers(request *restful.Request, response *restful.Response) {
|
||||
workspace := request.PathParameter("workspace")
|
||||
|
||||
var members []Member
|
||||
err := request.ReadEntity(&members)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, member := range members {
|
||||
err := h.am.CreateOrUpdateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
response.WriteEntity(members)
|
||||
}
|
||||
|
||||
func (h *handler) RemoveWorkspaceMember(request *restful.Request, response *restful.Response) {
|
||||
workspace := request.PathParameter("workspace")
|
||||
username := request.PathParameter("workspacemember")
|
||||
|
||||
err := h.am.RemoveUserFromWorkspace(username, workspace)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) DescribeWorkspaceMember(request *restful.Request, response *restful.Response) {
|
||||
workspace := request.PathParameter("workspace")
|
||||
memberName := request.PathParameter("workspacemember")
|
||||
bindings, err := h.am.ListWorkspaceRoleBindings(memberName, "", nil, workspace)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
if len(bindings) == 0 {
|
||||
api.HandleBadRequest(response, request, NewErrMemberNotExist(memberName))
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.im.DescribeUser(memberName)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
user.Annotations[iamv1beta1.WorkspaceRoleAnnotation] = bindings[0].RoleRef.Name
|
||||
_ = response.WriteEntity(user)
|
||||
}
|
||||
|
||||
func (h *handler) UpdateWorkspaceMember(request *restful.Request, response *restful.Response) {
|
||||
workspace := request.PathParameter("workspace")
|
||||
memberName := request.PathParameter("workspacemember")
|
||||
|
||||
var member Member
|
||||
err := request.ReadEntity(&member)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if memberName != member.Username {
|
||||
api.HandleBadRequest(response, request, NewErrIncorrectUsername(memberName))
|
||||
return
|
||||
}
|
||||
|
||||
bindings, err := h.am.ListWorkspaceRoleBindings(memberName, "", nil, workspace)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
if len(bindings) == 0 {
|
||||
api.HandleBadRequest(response, request, NewErrMemberNotExist(member.Username))
|
||||
return
|
||||
}
|
||||
|
||||
err = h.am.CreateOrUpdateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) UpdateClusterMember(request *restful.Request, response *restful.Response) {
|
||||
memberName := request.PathParameter("clustermember")
|
||||
|
||||
var member Member
|
||||
err := request.ReadEntity(&member)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if memberName != member.Username {
|
||||
api.HandleBadRequest(response, request, NewErrIncorrectUsername(memberName))
|
||||
return
|
||||
}
|
||||
|
||||
bindings, err := h.am.ListClusterRoleBindings(memberName, "")
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
if len(bindings) == 0 {
|
||||
api.HandleBadRequest(response, request, NewErrMemberNotExist(member.Username))
|
||||
return
|
||||
}
|
||||
|
||||
err = h.am.CreateOrUpdateClusterRoleBinding(member.Username, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func (h *handler) UpdateNamespaceMember(request *restful.Request, response *restful.Response) {
|
||||
namespace := request.PathParameter("namespace")
|
||||
memberName := request.PathParameter("namespacemember")
|
||||
|
||||
var member Member
|
||||
err := request.ReadEntity(&member)
|
||||
if err != nil {
|
||||
api.HandleBadRequest(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
if memberName != member.Username {
|
||||
api.HandleBadRequest(response, request, NewErrIncorrectUsername(memberName))
|
||||
return
|
||||
}
|
||||
|
||||
bindings, err := h.am.ListRoleBindings(member.Username, "", nil, namespace)
|
||||
if err != nil {
|
||||
api.HandleInternalError(response, request, err)
|
||||
return
|
||||
}
|
||||
if len(bindings) == 0 {
|
||||
api.HandleBadRequest(response, request, NewErrMemberNotExist(member.Username))
|
||||
return
|
||||
}
|
||||
|
||||
err = h.am.CreateOrUpdateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
|
||||
if err != nil {
|
||||
api.HandleError(response, request, err)
|
||||
return
|
||||
}
|
||||
|
||||
response.WriteEntity(servererr.None)
|
||||
}
|
||||
|
||||
func NewErrMemberNotExist(username string) error {
|
||||
return fmt.Errorf("member %s not exist", username)
|
||||
}
|
||||
|
||||
func NewErrIncorrectUsername(username string) error {
|
||||
return fmt.Errorf("incorrect username %s, the username must equal to the member", username)
|
||||
}
|
||||
185
pkg/kapis/iam/v1beta1/register.go
Normal file
185
pkg/kapis/iam/v1beta1/register.go
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Please refer to the LICENSE file in the root directory of the project.
|
||||
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
restfulspec "github.com/emicklei/go-restful-openapi/v2"
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
iamv1beta1 "kubesphere.io/api/iam/v1beta1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
apiserverruntime "kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
)
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: "iam.kubesphere.io", Version: "v1beta1"}
|
||||
|
||||
func (h *handler) AddToContainer(container *restful.Container) error {
|
||||
ws := apiserverruntime.NewWebService(GroupVersion)
|
||||
|
||||
ws.Route(ws.POST("/users").
|
||||
To(h.CreateUser).
|
||||
Doc("Create user").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1beta1.User{}).
|
||||
Reads(iamv1beta1.User{}))
|
||||
ws.Route(ws.PUT("/users/{user}").
|
||||
To(h.UpdateUser).
|
||||
Doc("Update user").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Reads(iamv1beta1.User{}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1beta1.User{}))
|
||||
ws.Route(ws.DELETE("/users/{user}").
|
||||
To(h.DeleteUser).
|
||||
Doc("Delete user").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.PUT("/users/{user}/password").
|
||||
To(h.ModifyPassword).
|
||||
Doc("Reset password").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Reads(PasswordReset{}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.GET("/users/{user}").
|
||||
To(h.DescribeUser).
|
||||
Doc("Get user").
|
||||
Notes("Retrieve user details.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Param(ws.PathParameter("user", "username")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1beta1.User{}))
|
||||
ws.Route(ws.GET("/users").
|
||||
To(h.ListUsers).
|
||||
Doc("List users").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Param(ws.QueryParameter("globalrole", "specific golalrole name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.User{}}}))
|
||||
ws.Route(ws.GET("/users/{user}/loginrecords").
|
||||
To(h.ListUserLoginRecords).
|
||||
Doc("List login records").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagIdentityManagement}).
|
||||
Param(ws.PathParameter("user", "username of the user")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.LoginRecord{}}}))
|
||||
|
||||
// members
|
||||
ws.Route(ws.GET("/clustermembers").
|
||||
To(h.ListClusterMembers).
|
||||
Doc("List all members of cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.QueryParameter("clusterrole", "specific the cluster role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.User{}}}))
|
||||
ws.Route(ws.POST("/clustermembers").
|
||||
To(h.CreateClusterMembers).
|
||||
Doc("Add members to cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}))
|
||||
ws.Route(ws.DELETE("/clustermembers/{clustermember}").
|
||||
To(h.RemoveClusterMember).
|
||||
Doc("Delete member from cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("clustermember", "cluster member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.PUT("/clustermembers/{clustermember}").
|
||||
To(h.UpdateClusterMember).
|
||||
Doc("Update member from the cluster").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("clustermember", "the member name from cluster")).
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers").
|
||||
To(h.ListWorkspaceMembers).
|
||||
Doc("List all members in the specified workspace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("workspace", "The specified workspace.")).
|
||||
Param(ws.QueryParameter("workspacerole", "specific the workspace role name")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.User{}}}))
|
||||
ws.Route(ws.PUT("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(h.UpdateWorkspaceMember).
|
||||
Doc("Update member from the workspace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("workspace", "The specified workspace.")).
|
||||
Param(ws.PathParameter("workspacemember", "the member from workspace")).
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.POST("/workspaces/{workspace}/workspacemembers").
|
||||
To(h.CreateWorkspaceMembers).
|
||||
Doc("Add members to the specified workspace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("workspace", "The specified workspace.")).
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}))
|
||||
ws.Route(ws.DELETE("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(h.RemoveWorkspaceMember).
|
||||
Doc("Delete a member from the workspace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("workspace", "The specified workspace.")).
|
||||
Param(ws.PathParameter("workspacemember", "Workspace member's name.")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.GET("/workspaces/{workspace}/workspacemembers/{workspacemember}").
|
||||
To(h.DescribeWorkspaceMember).
|
||||
Doc("Get workspace member").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("workspace", "The specified workspace.")).
|
||||
Param(ws.PathParameter("workspacemember", "Workspace member's name.")).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1beta1.User{}))
|
||||
|
||||
ws.Route(ws.GET("/namespaces/{namespace}/namespacemembers").
|
||||
To(h.ListNamespaceMembers).
|
||||
Doc("List all members in the specified namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.QueryParameter("role", "specific the role name")).
|
||||
Param(ws.PathParameter("namespace", "The specified namespace.")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.User{}}}))
|
||||
ws.Route(ws.POST("/namespaces/{namespace}/namespacemembers").
|
||||
To(h.CreateNamespaceMembers).
|
||||
Doc("Add members to the namespace in bulk.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Reads([]Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, []Member{}).
|
||||
Param(ws.PathParameter("namespace", "The specified namespace.")))
|
||||
ws.Route(ws.DELETE("/namespaces/{namespace}/namespacemembers/{member}").
|
||||
To(h.RemoveNamespaceMember).
|
||||
Doc("Delete a member from the namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("namespace", "The specified namespace.")).
|
||||
Param(ws.PathParameter("member", "namespace member's username")).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
ws.Route(ws.PUT("/namespaces/{namespace}/namespacemembers/{namespacemember}").
|
||||
To(h.UpdateNamespaceMember).
|
||||
Doc("Update member from the namespace").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("namespace", "The specified namespace.")).
|
||||
Param(ws.PathParameter("namespacemember", "the member from namespace")).
|
||||
Reads(Member{}).
|
||||
Returns(http.StatusOK, api.StatusOK, errors.None))
|
||||
|
||||
ws.Route(ws.GET("/users/{username}/roletemplates").
|
||||
To(h.ListRoleTemplateOfUser).
|
||||
Doc("List all role templates of the specified user").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Param(ws.PathParameter("username", "the name of the specified user")).
|
||||
Param(ws.QueryParameter("scope", "the scope of role templates")).
|
||||
Returns(http.StatusOK, api.StatusOK, api.ListResult{Items: []runtime.Object{&iamv1beta1.RoleTemplate{}}}))
|
||||
|
||||
ws.Route(ws.POST("/subjectaccessreviews").
|
||||
To(h.CreateSubjectAccessReview).
|
||||
Doc("Create subject access review").
|
||||
Notes("Evaluates all of the request attributes against all policies and allows or denies the request.").
|
||||
Metadata(restfulspec.KeyOpenAPITags, []string{api.TagAccessManagement}).
|
||||
Reads(iamv1beta1.SubjectAccessReview{}).
|
||||
Returns(http.StatusOK, api.StatusOK, iamv1beta1.SubjectAccessReview{}))
|
||||
|
||||
container.Add(ws)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user