1489 lines
41 KiB
Go
1489 lines
41 KiB
Go
/*
|
|
Copyright 2020 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 (
|
|
"fmt"
|
|
"strings"
|
|
|
|
authuser "k8s.io/apiserver/pkg/authentication/user"
|
|
|
|
"kubesphere.io/kubesphere/pkg/apiserver/request"
|
|
"kubesphere.io/kubesphere/pkg/models/auth"
|
|
|
|
restful "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"
|
|
"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/iam/am"
|
|
"kubesphere.io/kubesphere/pkg/models/iam/group"
|
|
"kubesphere.io/kubesphere/pkg/models/iam/im"
|
|
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 iamHandler struct {
|
|
am am.AccessManagementInterface
|
|
im im.IdentityManagementInterface
|
|
group group.GroupOperator
|
|
authorizer authorizer.Authorizer
|
|
}
|
|
|
|
func newIAMHandler(im im.IdentityManagementInterface, am am.AccessManagementInterface, group group.GroupOperator, authorizer authorizer.Authorizer) *iamHandler {
|
|
return &iamHandler{
|
|
am: am,
|
|
im: im,
|
|
group: group,
|
|
authorizer: authorizer,
|
|
}
|
|
}
|
|
|
|
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)
|
|
// ignore not found error
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
if globalRole != nil {
|
|
user = appendGlobalRoleAnnotation(user, 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")
|
|
|
|
user, err := h.im.DescribeUser(username)
|
|
if err != nil {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
|
|
workspaceRoles, err := h.am.GetWorkspaceRoleOfUser(username, user.Spec.Groups, 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
|
|
}
|
|
templateRoles := make(map[string]*iamv1alpha2.WorkspaceRole)
|
|
for _, role := range workspaceRoles {
|
|
// merge template Role
|
|
result, err := h.am.ListWorkspaceRoles(&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
|
|
}
|
|
|
|
for _, obj := range result.Items {
|
|
templateRole := obj.(*iamv1alpha2.WorkspaceRole)
|
|
templateRoles[templateRole.Name] = templateRole
|
|
}
|
|
}
|
|
|
|
results := make([]*iamv1alpha2.WorkspaceRole, 0, len(templateRoles))
|
|
for _, value := range templateRoles {
|
|
results = append(results, value)
|
|
}
|
|
|
|
response.WriteEntity(results)
|
|
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
|
|
}
|
|
|
|
user, err := h.im.DescribeUser(username)
|
|
if err != nil {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
|
|
roles, err := h.am.GetNamespaceRoleOfUser(username, user.Spec.Groups, 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
|
|
}
|
|
|
|
templateRoles := make(map[string]*rbacv1.Role)
|
|
for _, role := range roles {
|
|
// merge template Role
|
|
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
|
|
}
|
|
|
|
for _, obj := range result.Items {
|
|
templateRole := obj.(*rbacv1.Role)
|
|
templateRoles[templateRole.Name] = templateRole
|
|
}
|
|
}
|
|
|
|
results := make([]*rbacv1.Role, 0, len(templateRoles))
|
|
for _, value := range templateRoles {
|
|
results = append(results, value)
|
|
}
|
|
|
|
response.WriteEntity(results)
|
|
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)
|
|
// ignore not found error
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
if globalRole != nil {
|
|
user = appendGlobalRoleAnnotation(user, globalRole.Name)
|
|
}
|
|
result.Items[i] = user
|
|
}
|
|
response.WriteEntity(result)
|
|
}
|
|
|
|
func appendGlobalRoleAnnotation(user *iamv1alpha2.User, globalRole string) *iamv1alpha2.User {
|
|
if user.Annotations == nil {
|
|
user.Annotations = make(map[string]string, 0)
|
|
}
|
|
user.Annotations[iamv1alpha2.GlobalRoleAnnotation] = globalRole
|
|
return user
|
|
}
|
|
|
|
func (h *iamHandler) ListRoles(request *restful.Request, response *restful.Response) {
|
|
namespace, err := h.resolveNamespace(request.PathParameter("namespace"), request.PathParameter("devops"))
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
queryParam := query.New()
|
|
queryParam.Filters[query.FieldNames] = 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.FieldNames] = 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 {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.am.CreateOrUpdateWorkspaceRole(workspace, &workspaceRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
created, err := h.am.CreateOrUpdateWorkspaceRole(workspace, &workspaceRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(servererr.None)
|
|
}
|
|
|
|
func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
|
|
var user iamv1alpha2.User
|
|
err := req.ReadEntity(&user)
|
|
if err != nil {
|
|
api.HandleBadRequest(resp, req, err)
|
|
return
|
|
}
|
|
operator, ok := request.UserFrom(req.Request.Context())
|
|
if ok && operator.GetName() == iamv1alpha2.PreRegistrationUser {
|
|
extra := operator.GetExtra()
|
|
// The token used for registration must contain additional information
|
|
if len(extra[iamv1alpha2.ExtraIdentityProvider]) != 1 || len(extra[iamv1alpha2.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[iamv1alpha2.IdentifyProviderLabel] = extra[iamv1alpha2.ExtraIdentityProvider][0]
|
|
user.Labels[iamv1alpha2.OriginUIDLabel] = extra[iamv1alpha2.ExtraUID][0]
|
|
// default role
|
|
delete(user.Annotations, iamv1alpha2.GlobalRoleAnnotation)
|
|
}
|
|
|
|
globalRole := user.Annotations[iamv1alpha2.GlobalRoleAnnotation]
|
|
delete(user.Annotations, iamv1alpha2.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.CreateGlobalRoleBinding(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 *iamHandler) UpdateUser(request *restful.Request, response *restful.Response) {
|
|
username := request.PathParameter("user")
|
|
|
|
var user iamv1alpha2.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[iamv1alpha2.GlobalRoleAnnotation]
|
|
delete(user.Annotations, iamv1alpha2.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 {
|
|
err = h.updateGlobalRoleBinding(operator, updated, globalRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
updated = appendGlobalRoleAnnotation(updated, globalRole)
|
|
}
|
|
|
|
response.WriteEntity(updated)
|
|
}
|
|
|
|
func (h *iamHandler) 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 *iamHandler) 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 *iamHandler) CreateGlobalRole(request *restful.Request, response *restful.Response) {
|
|
|
|
var globalRole iamv1alpha2.GlobalRole
|
|
err := request.ReadEntity(&globalRole)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
created, err := h.am.CreateOrUpdateGlobalRole(&globalRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.am.CreateOrUpdateGlobalRole(&globalRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
created, err := h.am.CreateOrUpdateClusterRole(&clusterRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.am.CreateOrUpdateClusterRole(&clusterRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
var role rbacv1.Role
|
|
err = request.ReadEntity(&role)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
created, err := h.am.CreateOrUpdateNamespaceRole(namespace, &role)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
err = h.am.DeleteNamespaceRole(namespace, role)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
var role rbacv1.Role
|
|
err = request.ReadEntity(&role)
|
|
if err != nil {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.am.CreateOrUpdateNamespaceRole(namespace, &role)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
for _, member := range members {
|
|
err := h.am.CreateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
err = h.am.CreateUserWorkspaceRoleBinding(member.Username, workspace, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
var members []Member
|
|
err = request.ReadEntity(&members)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
for _, member := range members {
|
|
err := h.am.CreateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
var member Member
|
|
err = request.ReadEntity(&member)
|
|
if err != nil {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
err = h.am.CreateNamespaceRoleBinding(member.Username, namespace, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
err = h.am.RemoveUserFromNamespace(username, namespace)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
for _, member := range members {
|
|
err := h.am.CreateClusterRoleBinding(member.Username, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, 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 {
|
|
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)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
err = h.am.CreateClusterRoleBinding(member.Username, member.RoleRef)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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.FieldNames] = 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
role, err := h.am.GetNamespaceRole(namespace, roleName)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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.GetDevOpsRelatedNamespace(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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
workspaceRole.Name = workspaceRoleName
|
|
patched, err := h.am.PatchWorkspaceRole(workspaceName, &workspaceRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
globalRole.Name = globalRoleName
|
|
patched, err := h.am.PatchGlobalRole(&globalRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
var role rbacv1.Role
|
|
err = request.ReadEntity(&role)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
role.Name = roleName
|
|
patched, err := h.am.PatchNamespaceRole(namespaceName, &role)
|
|
if err != nil {
|
|
api.HandleError(response, request, 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 {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
clusterRole.Name = clusterRoleName
|
|
patched, err := h.am.PatchClusterRole(&clusterRole)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(patched)
|
|
}
|
|
|
|
func (h *iamHandler) updateGlobalRoleBinding(operator authuser.Info, user *iamv1alpha2.User, globalRole string) error {
|
|
|
|
oldGlobalRole, err := h.am.GetGlobalRoleOfUser(user.Name)
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
klog.Error(err)
|
|
return err
|
|
}
|
|
|
|
if oldGlobalRole != nil && oldGlobalRole.Name == globalRole {
|
|
return nil
|
|
}
|
|
|
|
userManagement := authorizer.AttributesRecord{
|
|
Resource: iamv1alpha2.ResourcesPluralUser,
|
|
Verb: "update",
|
|
ResourceScope: apirequest.GlobalScope,
|
|
ResourceRequest: true,
|
|
User: operator,
|
|
}
|
|
decision, _, err := h.authorizer.Authorize(userManagement)
|
|
if err != nil {
|
|
klog.Error(err)
|
|
return err
|
|
}
|
|
if decision != authorizer.DecisionAllow {
|
|
err = errors.NewForbidden(iamv1alpha2.Resource(iamv1alpha2.ResourcesSingularUser),
|
|
user.Name, fmt.Errorf("update global role binding is not allowed"))
|
|
klog.Warning(err)
|
|
return err
|
|
}
|
|
if err := h.am.CreateGlobalRoleBinding(user.Name, globalRole); err != nil {
|
|
klog.Error(err)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h *iamHandler) 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 *iamHandler) ListWorkspaceGroups(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
queryParam := query.ParseQueryParameter(request)
|
|
result, err := h.group.ListGroups(workspaceName, queryParam)
|
|
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(result)
|
|
}
|
|
|
|
func (h *iamHandler) CreateGroup(request *restful.Request, response *restful.Response) {
|
|
workspace := request.PathParameter("workspace")
|
|
var group iamv1alpha2.Group
|
|
|
|
err := request.ReadEntity(&group)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
created, err := h.group.CreateGroup(workspace, &group)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(created)
|
|
}
|
|
|
|
func (h *iamHandler) DescribeGroup(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
groupName := request.PathParameter("group")
|
|
ns, err := h.group.DescribeGroup(workspaceName, groupName)
|
|
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(ns)
|
|
}
|
|
|
|
func (h *iamHandler) DeleteGroup(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
groupName := request.PathParameter("group")
|
|
|
|
err := h.group.DeleteGroup(workspaceName, groupName)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(servererr.None)
|
|
}
|
|
|
|
func (h *iamHandler) UpdateGroup(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
groupName := request.PathParameter("group")
|
|
|
|
var group iamv1alpha2.Group
|
|
err := request.ReadEntity(&group)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
if groupName != group.Name {
|
|
err := fmt.Errorf("the name of the object (%s) does not match the name on the URL (%s)", group.Name, groupName)
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
updated, err := h.group.UpdateGroup(workspaceName, &group)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(updated)
|
|
}
|
|
|
|
func (h *iamHandler) PatchGroup(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
groupName := request.PathParameter("group")
|
|
|
|
var group iamv1alpha2.Group
|
|
err := request.ReadEntity(&group)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
group.Name = groupName
|
|
patched, err := h.group.PatchGroup(workspaceName, &group)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(patched)
|
|
}
|
|
|
|
func (h *iamHandler) ListGroupBindings(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
queryParam := query.ParseQueryParameter(request)
|
|
result, err := h.group.ListGroupBindings(workspaceName, queryParam)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(result)
|
|
}
|
|
|
|
func (h *iamHandler) ListGroupRoleBindings(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
queryParam := query.ParseQueryParameter(request)
|
|
result, err := h.am.ListGroupRoleBindings(workspaceName, queryParam)
|
|
if err != nil {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(result)
|
|
}
|
|
|
|
func (h *iamHandler) CreateRoleBinding(request *restful.Request, response *restful.Response) {
|
|
namespace := request.PathParameter("namespace")
|
|
var roleBindings []rbacv1.RoleBinding
|
|
err := request.ReadEntity(&roleBindings)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
var results []rbacv1.RoleBinding
|
|
for _, item := range roleBindings {
|
|
r, err := h.am.CreateRoleBinding(namespace, &item)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
results = append(results, *r)
|
|
}
|
|
|
|
response.WriteEntity(results)
|
|
}
|
|
|
|
func (h *iamHandler) DeleteRoleBinding(request *restful.Request, response *restful.Response) {
|
|
name := request.PathParameter("rolebinding")
|
|
namespace := request.PathParameter("namespace")
|
|
|
|
err := h.am.DeleteRoleBinding(namespace, name)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(servererr.None)
|
|
}
|
|
|
|
func (h *iamHandler) ListGroupWorkspaceRoleBindings(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
queryParam := query.ParseQueryParameter(request)
|
|
result, err := h.am.ListGroupWorkspaceRoleBindings(workspaceName, queryParam)
|
|
if err != nil {
|
|
api.HandleInternalError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(result)
|
|
}
|
|
|
|
func (h *iamHandler) CreateWorkspaceRoleBinding(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
|
|
var roleBindings []iamv1alpha2.WorkspaceRoleBinding
|
|
err := request.ReadEntity(&roleBindings)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
var results []iamv1alpha2.WorkspaceRoleBinding
|
|
for _, item := range roleBindings {
|
|
r, err := h.am.CreateWorkspaceRoleBinding(workspaceName, &item)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
results = append(results, *r)
|
|
}
|
|
|
|
response.WriteEntity(results)
|
|
}
|
|
|
|
func (h *iamHandler) DeleteWorkspaceRoleBinding(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
name := request.PathParameter("rolebinding")
|
|
|
|
err := h.am.DeleteWorkspaceRoleBinding(workspaceName, name)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(servererr.None)
|
|
}
|
|
|
|
func (h *iamHandler) CreateGroupBinding(request *restful.Request, response *restful.Response) {
|
|
|
|
workspace := request.PathParameter("workspace")
|
|
|
|
var members []GroupMember
|
|
err := request.ReadEntity(&members)
|
|
if err != nil {
|
|
api.HandleBadRequest(response, request, err)
|
|
return
|
|
}
|
|
|
|
var results []iamv1alpha2.GroupBinding
|
|
for _, item := range members {
|
|
b, err := h.group.CreateGroupBinding(workspace, item.GroupName, item.UserName)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
results = append(results, *b)
|
|
}
|
|
|
|
response.WriteEntity(results)
|
|
}
|
|
|
|
func (h *iamHandler) DeleteGroupBinding(request *restful.Request, response *restful.Response) {
|
|
workspaceName := request.PathParameter("workspace")
|
|
name := request.PathParameter("groupbinding")
|
|
|
|
err := h.group.DeleteGroupBinding(workspaceName, name)
|
|
if err != nil {
|
|
api.HandleError(response, request, err)
|
|
return
|
|
}
|
|
|
|
response.WriteEntity(servererr.None)
|
|
}
|