Files
kubesphere/pkg/kapis/iam/v1alpha2/handler.go
2020-06-23 16:26:24 +08:00

1208 lines
30 KiB
Go

package v1alpha2
import (
"fmt"
"github.com/emicklei/go-restful"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im"
servererr "kubesphere.io/kubesphere/pkg/server/errors"
"strings"
)
type iamHandler struct {
am am.AccessManagementInterface
im im.IdentityManagementInterface
}
func newIAMHandler(im im.IdentityManagementInterface, am am.AccessManagementInterface, options *authoptions.AuthenticationOptions) *iamHandler {
return &iamHandler{
am: am,
im: im,
}
}
type Member struct {
Username string `json:"username"`
RoleRef string `json:"roleRef"`
}
func (h *iamHandler) DescribeUser(request *restful.Request, response *restful.Response) {
username := request.PathParameter("user")
user, err := h.im.DescribeUser(username)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
globalRole, err := h.am.GetGlobalRoleOfUser(username)
if err != nil && !errors.IsNotFound(err) {
api.HandleInternalError(response, request, err)
return
}
if globalRole != nil {
if user.Annotations == nil {
user.Annotations = make(map[string]string, 0)
}
user.Annotations[iamv1alpha2.GlobalRoleAnnotation] = globalRole.Name
}
response.WriteEntity(user)
}
func (h *iamHandler) RetrieveMemberRoleTemplates(request *restful.Request, response *restful.Response) {
if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralGlobalRole) {
username := request.PathParameter("user")
globalRole, err := h.am.GetGlobalRoleOfUser(username)
if err != nil {
// if role binding not exist return empty list
if errors.IsNotFound(err) {
response.WriteEntity([]interface{}{})
return
}
api.HandleInternalError(response, request, err)
return
}
result, err := h.am.ListGlobalRoles(&query.Query{
Pagination: query.NoPagination,
SortBy: "",
Ascending: false,
Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(globalRole.Name)},
})
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result.Items)
return
}
if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralClusterRole) {
username := request.PathParameter("clustermember")
clusterRole, err := h.am.GetClusterRoleOfUser(username)
if err != nil {
// if role binding not exist return empty list
if errors.IsNotFound(err) {
response.WriteEntity([]interface{}{})
return
}
api.HandleInternalError(response, request, err)
return
}
result, err := h.am.ListClusterRoles(&query.Query{
Pagination: query.NoPagination,
SortBy: "",
Ascending: false,
Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(clusterRole.Name)},
})
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result.Items)
return
}
if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralWorkspaceRole) {
workspace := request.PathParameter("workspace")
username := request.PathParameter("workspacemember")
workspaceRole, err := h.am.GetWorkspaceRoleOfUser(username, workspace)
if err != nil {
// if role binding not exist return empty list
if errors.IsNotFound(err) {
response.WriteEntity([]interface{}{})
return
}
api.HandleInternalError(response, request, err)
return
}
result, err := h.am.ListWorkspaceRoles(&query.Query{
Pagination: query.NoPagination,
SortBy: "",
Ascending: false,
Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(workspaceRole.Name)},
})
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result.Items)
return
}
if strings.HasSuffix(request.Request.URL.Path, iamv1alpha2.ResourcesPluralRole) {
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
username := request.PathParameter("member")
if err != nil {
api.HandleInternalError(response, request, err)
return
}
role, err := h.am.GetNamespaceRoleOfUser(username, namespace)
if err != nil {
// if role binding not exist return empty list
if errors.IsNotFound(err) {
response.WriteEntity([]interface{}{})
return
}
api.HandleInternalError(response, request, err)
return
}
result, err := h.am.ListRoles(namespace, &query.Query{
Pagination: query.NoPagination,
SortBy: "",
Ascending: false,
Filters: map[query.Field]query.Value{iamv1alpha2.AggregateTo: query.Value(role.Name)},
})
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result.Items)
return
}
}
func (h *iamHandler) ListUsers(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
for i, item := range result.Items {
user := item.(*iamv1alpha2.User)
user = user.DeepCopy()
globalRole, err := h.am.GetGlobalRoleOfUser(user.Name)
if err != nil && !errors.IsNotFound(err) {
klog.Error(err)
api.HandleInternalError(response, request, err)
return
}
if globalRole != nil {
if user.Annotations == nil {
user.Annotations = make(map[string]string, 0)
}
user.Annotations[iamv1alpha2.GlobalRoleAnnotation] = globalRole.Name
}
result.Items[i] = user
}
response.WriteEntity(result)
}
func (h *iamHandler) ListRoles(request *restful.Request, response *restful.Response) {
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
queryParam := query.ParseQueryParameter(request)
result, err := h.am.ListRoles(namespace, queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) ListClusterRoles(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
result, err := h.am.ListClusterRoles(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) ListGlobalRoles(req *restful.Request, resp *restful.Response) {
queryParam := query.ParseQueryParameter(req)
result, err := h.am.ListGlobalRoles(queryParam)
if err != nil {
api.HandleInternalError(resp, req, err)
return
}
resp.WriteEntity(result)
}
func (h *iamHandler) ListNamespaceMembers(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
queryParam.Filters[iamv1alpha2.ScopeNamespace] = query.Value(namespace)
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) DescribeNamespaceMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("member")
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
queryParam := query.New()
queryParam.Filters[query.FieldName] = query.Value(username)
queryParam.Filters[iamv1alpha2.ScopeNamespace] = query.Value(namespace)
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
if len(result.Items) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularUser), username)
api.HandleNotFound(response, request, err)
return
}
response.WriteEntity(result.Items[0])
}
func (h *iamHandler) ListWorkspaceRoles(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
workspace := request.PathParameter("workspace")
queryParam.Filters[iamv1alpha2.ScopeWorkspace] = query.Value(workspace)
// shared workspace role template
if string(queryParam.Filters[query.FieldLabel]) == fmt.Sprintf("%s=%s", iamv1alpha2.RoleTemplateLabel, "true") ||
queryParam.Filters[iamv1alpha2.AggregateTo] != "" {
delete(queryParam.Filters, iamv1alpha2.ScopeWorkspace)
}
result, err := h.am.ListWorkspaceRoles(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) ListWorkspaceMembers(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
workspace := request.PathParameter("workspace")
queryParam.Filters[iamv1alpha2.ScopeWorkspace] = query.Value(workspace)
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) DescribeWorkspaceMember(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
username := request.PathParameter("workspacemember")
queryParam := query.New()
queryParam.Filters[query.FieldName] = query.Value(username)
queryParam.Filters[iamv1alpha2.ScopeWorkspace] = query.Value(workspace)
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
if len(result.Items) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularUser), username)
api.HandleNotFound(response, request, err)
return
}
response.WriteEntity(result.Items[0])
}
func (h *iamHandler) UpdateWorkspaceRole(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
workspaceRoleName := request.PathParameter("workspacerole")
var workspaceRole iamv1alpha2.WorkspaceRole
err := request.ReadEntity(&workspaceRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
if workspaceRoleName != workspaceRole.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", workspaceRole.Name, workspaceRoleName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
updated, err := h.am.CreateOrUpdateWorkspaceRole(workspace, &workspaceRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(updated)
}
func (h *iamHandler) CreateWorkspaceRole(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
var workspaceRole iamv1alpha2.WorkspaceRole
err := request.ReadEntity(&workspaceRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.am.CreateOrUpdateWorkspaceRole(workspace, &workspaceRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(created)
}
func (h *iamHandler) DeleteWorkspaceRole(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
workspaceRoleName := request.PathParameter("workspacerole")
err := h.am.DeleteWorkspaceRole(workspace, workspaceRoleName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) CreateUser(request *restful.Request, response *restful.Response) {
var user iamv1alpha2.User
err := request.ReadEntity(&user)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
globalRole := user.Annotations[iamv1alpha2.GlobalRoleAnnotation]
delete(user.Annotations, iamv1alpha2.RoleAnnotation)
if globalRole != "" {
if _, err = h.am.GetGlobalRole(globalRole); err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
created, err := h.im.CreateUser(&user)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
if globalRole != "" {
if err := h.am.CreateGlobalRoleBinding(user.Name, globalRole); err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
// ensure encrypted password will not be output
created.Spec.EncryptedPassword = ""
response.WriteEntity(created)
}
func (h *iamHandler) UpdateUser(request *restful.Request, response *restful.Response) {
username := request.PathParameter("user")
var user iamv1alpha2.User
err := request.ReadEntity(&user)
if err != nil {
klog.Errorf("%+v", err)
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)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
globalRole := user.Annotations[iamv1alpha2.GlobalRoleAnnotation]
delete(user.Annotations, iamv1alpha2.GlobalRoleAnnotation)
updated, err := h.im.UpdateUser(&user)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
if globalRole != "" {
if err := h.am.CreateGlobalRoleBinding(user.Name, globalRole); err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
response.WriteEntity(updated)
}
func (h *iamHandler) DeleteUser(request *restful.Request, response *restful.Response) {
username := request.PathParameter("user")
err := h.im.DeleteUser(username)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) CreateGlobalRole(request *restful.Request, response *restful.Response) {
var globalRole iamv1alpha2.GlobalRole
err := request.ReadEntity(&globalRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.am.CreateOrUpdateGlobalRole(&globalRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(created)
}
func (h *iamHandler) DeleteGlobalRole(request *restful.Request, response *restful.Response) {
globalRole := request.PathParameter("globalrole")
err := h.am.DeleteGlobalRole(globalRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) UpdateGlobalRole(request *restful.Request, response *restful.Response) {
globalRoleName := request.PathParameter("globalrole")
var globalRole iamv1alpha2.GlobalRole
err := request.ReadEntity(&globalRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
if globalRoleName != globalRole.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", globalRole.Name, globalRoleName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
updated, err := h.am.CreateOrUpdateGlobalRole(&globalRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(updated)
}
func (h *iamHandler) DescribeGlobalRole(request *restful.Request, response *restful.Response) {
globalRoleName := request.PathParameter("globalrole")
globalRole, err := h.am.GetGlobalRole(globalRoleName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(globalRole)
}
func (h *iamHandler) CreateClusterRole(request *restful.Request, response *restful.Response) {
var clusterRole rbacv1.ClusterRole
err := request.ReadEntity(&clusterRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.am.CreateOrUpdateClusterRole(&clusterRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(created)
}
func (h *iamHandler) DeleteClusterRole(request *restful.Request, response *restful.Response) {
clusterrole := request.PathParameter("clusterrole")
err := h.am.DeleteClusterRole(clusterrole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) UpdateClusterRole(request *restful.Request, response *restful.Response) {
clusterRoleName := request.PathParameter("clusterrole")
var clusterRole rbacv1.ClusterRole
err := request.ReadEntity(&clusterRole)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
if clusterRoleName != clusterRole.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", clusterRole.Name, clusterRoleName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
updated, err := h.am.CreateOrUpdateClusterRole(&clusterRole)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(updated)
}
func (h *iamHandler) DescribeClusterRole(request *restful.Request, response *restful.Response) {
clusterRoleName := request.PathParameter("clusterrole")
clusterRole, err := h.am.GetClusterRole(clusterRoleName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(clusterRole)
}
func (h *iamHandler) DescribeWorkspaceRole(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
workspaceRoleName := request.PathParameter("workspacerole")
workspaceRole, err := h.am.GetWorkspaceRole(workspace, workspaceRoleName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(workspaceRole)
}
func (h *iamHandler) CreateNamespaceRole(request *restful.Request, response *restful.Response) {
namespace, 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.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
created, err := h.am.CreateOrUpdateNamespaceRole(namespace, &role)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(created)
}
func (h *iamHandler) DeleteNamespaceRole(request *restful.Request, response *restful.Response) {
role := request.PathParameter("role")
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
err = h.am.DeleteNamespaceRole(namespace, role)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) UpdateNamespaceRole(request *restful.Request, response *restful.Response) {
roleName := request.PathParameter("role")
namespace, 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.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
if roleName != role.Name {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", role.Name, roleName)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
updated, err := h.am.CreateOrUpdateNamespaceRole(namespace, &role)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(updated)
}
func (h *iamHandler) CreateWorkspaceMembers(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
var members []Member
err := request.ReadEntity(&members)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
for _, member := range members {
err := h.am.CreateWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
response.WriteEntity(members)
}
func (h *iamHandler) RemoveWorkspaceMember(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
username := request.PathParameter("workspacemember")
err := h.am.RemoveUserFromWorkspace(username, workspace)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) UpdateWorkspaceMember(request *restful.Request, response *restful.Response) {
workspace := request.PathParameter("workspace")
username := request.PathParameter("workspacemember")
var member Member
err := request.ReadEntity(&member)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
if username != member.Username {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", member.Username, username)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
err = h.am.CreateWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(member)
}
func (h *iamHandler) CreateNamespaceMembers(request *restful.Request, response *restful.Response) {
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
var members []Member
err = request.ReadEntity(&members)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
for _, member := range members {
err := h.am.CreateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
response.WriteEntity(members)
}
func (h *iamHandler) UpdateNamespaceMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("member")
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
var member Member
err = request.ReadEntity(&member)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
if username != member.Username {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", member.Username, username)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
err = h.am.CreateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(member)
}
func (h *iamHandler) RemoveNamespaceMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("member")
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
err = h.am.RemoveUserFromNamespace(username, namespace)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) CreateClusterMembers(request *restful.Request, response *restful.Response) {
var members []Member
err := request.ReadEntity(&members)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
for _, member := range members {
err := h.am.CreateClusterRoleBinding(member.Username, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
}
response.WriteEntity(members)
}
func (h *iamHandler) RemoveClusterMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("clustermember")
err := h.am.RemoveUserFromCluster(username)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(servererr.None)
}
func (h *iamHandler) UpdateClusterMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("clustermember")
var member Member
err := request.ReadEntity(&member)
if err != nil {
klog.Error(err)
api.HandleBadRequest(response, request, err)
return
}
if username != member.Username {
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", member.Username, username)
klog.Errorf("%+v", err)
api.HandleBadRequest(response, request, err)
return
}
err = h.am.CreateClusterRoleBinding(member.Username, member.RoleRef)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(member)
}
func (h *iamHandler) DescribeClusterMember(request *restful.Request, response *restful.Response) {
username := request.PathParameter("clustermember")
queryParam := query.New()
queryParam.Filters[query.FieldName] = query.Value(username)
queryParam.Filters[iamv1alpha2.ScopeCluster] = "true"
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
if len(result.Items) == 0 {
err := errors.NewNotFound(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularUser), username)
api.HandleNotFound(response, request, err)
return
}
response.WriteEntity(result.Items[0])
}
func (h *iamHandler) ListClusterMembers(request *restful.Request, response *restful.Response) {
queryParam := query.ParseQueryParameter(request)
queryParam.Filters[iamv1alpha2.ScopeCluster] = "true"
result, err := h.im.ListUsers(queryParam)
if err != nil {
api.HandleInternalError(response, request, err)
return
}
response.WriteEntity(result)
}
func (h *iamHandler) DescribeNamespaceRole(request *restful.Request, response *restful.Response) {
roleName := request.PathParameter("role")
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
role, err := h.am.GetNamespaceRole(namespace, roleName)
if err != nil {
klog.Error(err)
handleError(request, response, err)
return
}
response.WriteEntity(role)
}
// resolve the namespace which controlled by the devops project
func (h *iamHandler) resolveNamespace(namespace string, devops string) (string, error) {
if devops == "" {
return namespace, nil
}
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)
} else if errors.IsNotFound(err) {
api.HandleNotFound(response, request, err)
} else if errors.IsAlreadyExists(err) {
api.HandleConflict(response, request, err)
} else {
api.HandleInternalError(response, request, err)
}
}