code refactor (#1786)

* implement LDAP mock client

Signed-off-by: hongming <talonwan@yunify.com>

* update

Signed-off-by: hongming <talonwan@yunify.com>

* update

Signed-off-by: hongming <talonwan@yunify.com>

* resolve conflict

Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
hongming
2020-02-24 15:39:36 +08:00
committed by GitHub
parent 96aee0e60b
commit abf9fee845
39 changed files with 1338 additions and 2467 deletions

View File

@@ -2,21 +2,26 @@ package v1alpha2
import (
"errors"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/emicklei/go-restful"
"github.com/go-ldap/ldap"
rbacv1 "k8s.io/api/rbac/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
kserr "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
apierr "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/utils/iputil"
"kubesphere.io/kubesphere/pkg/utils/jwtutil"
"net/http"
"sort"
)
type iamHandler struct {
@@ -24,29 +29,34 @@ type iamHandler struct {
imOperator iam.IdentityManagementInterface
}
func newIAMHandler() *iamHandler {
return &iamHandler{}
func newIAMHandler(k8sClient k8s.Client, ldapClient ldappool.Client, options iam.Config) *iamHandler {
factory := informers.NewInformerFactories(k8sClient.Kubernetes(), k8sClient.KubeSphere(), k8sClient.S2i(), k8sClient.Application())
return &iamHandler{
amOperator: iam.NewAMOperator(factory.KubernetesSharedInformerFactory()),
imOperator: iam.NewIMOperator(ldapClient, options),
}
}
// k8s token review
// Implement webhook authentication interface
// https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication
func (h *iamHandler) TokenReviewHandler(req *restful.Request, resp *restful.Response) {
var tokenReview iamv1alpha2.TokenReview
err := req.ReadEntity(&tokenReview)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
if tokenReview.Spec == nil {
api.HandleBadRequest(resp, errors.New("token must not be null"))
if err = tokenReview.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
uToken := tokenReview.Spec.Token
token, err := jwtutil.ValidateToken(uToken)
token, err := jwtutil.ValidateToken(tokenReview.Spec.Token)
if err != nil {
failed := iamv1alpha2.TokenReview{APIVersion: tokenReview.APIVersion,
@@ -59,18 +69,24 @@ func (h *iamHandler) TokenReviewHandler(req *restful.Request, resp *restful.Resp
return
}
claims := token.Claims.(jwt.MapClaims)
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
api.HandleBadRequest(resp, errors.New("invalid token"))
return
}
username, ok := claims["username"].(string)
if !ok {
api.HandleBadRequest(resp, errors.New("username not found"))
api.HandleBadRequest(resp, errors.New("invalid token"))
return
}
user, err := h.imOperator.DescribeUser(username)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -92,7 +108,9 @@ func (h *iamHandler) Login(req *restful.Request, resp *restful.Response) {
err := req.ReadEntity(&loginRequest)
if err != nil || loginRequest.Username == "" || loginRequest.Password == "" {
resp.WriteHeaderAndEntity(http.StatusUnauthorized, errors.New("incorrect username or password"))
err = errors.New("incorrect username or password")
klog.V(4).Infoln(err)
resp.WriteHeaderAndEntity(http.StatusUnauthorized, err)
return
}
@@ -101,10 +119,12 @@ func (h *iamHandler) Login(req *restful.Request, resp *restful.Response) {
token, err := h.imOperator.Login(loginRequest.Username, loginRequest.Password, ip)
if err != nil {
if serviceError, ok := err.(restful.ServiceError); ok {
resp.WriteHeaderAndEntity(serviceError.Code, errors.New(serviceError.Message))
if err == iam.AuthRateLimitExceeded {
klog.V(4).Infoln(err)
resp.WriteHeaderAndEntity(http.StatusTooManyRequests, err)
return
}
klog.V(4).Infoln(err)
resp.WriteHeaderAndEntity(http.StatusUnauthorized, err)
return
}
@@ -113,14 +133,16 @@ func (h *iamHandler) Login(req *restful.Request, resp *restful.Response) {
}
func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
var createRequest iamv1alpha2.UserCreateRequest
var createRequest iamv1alpha2.CreateUserRequest
err := req.ReadEntity(&createRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
if err := createRequest.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -128,23 +150,223 @@ func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
created, err := h.imOperator.CreateUser(createRequest.User)
if err != nil {
if ldap.IsErrorWithCode(err, ldap.LDAPResultEntryAlreadyExists) {
resp.WriteHeaderAndEntity(http.StatusConflict, kserr.Wrap(err))
if err == iam.UserAlreadyExists {
klog.V(4).Infoln(err)
resp.WriteHeaderAndEntity(http.StatusConflict, err)
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
err := h.amOperator.CreateClusterRoleBinding(created.Username, createRequest.ClusterRole)
err = h.amOperator.CreateClusterRoleBinding(created.Username, createRequest.ClusterRole)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(created)
}
func (h *iamHandler) DeleteUser(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("user")
operator := req.HeaderParameter(constants.UserNameHeader)
if operator == username {
err := errors.New("cannot delete yourself")
klog.V(4).Infoln(err)
api.HandleForbidden(resp, err)
return
}
err := h.amOperator.UnBindAllRoles(username)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
err = h.imOperator.DeleteUser(username)
// TODO release user resources
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(apierr.None)
}
func (h *iamHandler) ModifyUser(request *restful.Request, response *restful.Response) {
username := request.PathParameter("user")
operator := request.HeaderParameter(constants.UserNameHeader)
var modifyUserRequest iamv1alpha2.ModifyUserRequest
err := request.ReadEntity(&modifyUserRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
return
}
if username != modifyUserRequest.Username {
err = fmt.Errorf("the name of user (%s) does not match the name on the URL (%s)", modifyUserRequest.Username, username)
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
return
}
if err = modifyUserRequest.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
return
}
// change password by self
if operator == modifyUserRequest.Username && modifyUserRequest.Password != "" {
}
result, err := h.imOperator.ModifyUser(modifyUserRequest.User)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
return
}
// TODO modify cluster role
response.WriteEntity(result)
}
func (h *iamHandler) DescribeUser(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("user")
user, err := h.imOperator.DescribeUser(username)
if err != nil {
if err == iam.UserNotExists {
klog.V(4).Infoln(err)
api.HandleNotFound(resp, err)
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
// TODO append more user info
clusterRole, err := h.amOperator.GetClusterRole(username)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
result := iamv1alpha2.UserDetail{
User: user,
ClusterRole: clusterRole.Name,
}
resp.WriteEntity(result)
}
func (h *iamHandler) ListUsers(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
result, err := h.imOperator.ListUsers(conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(result)
}
func (h *iamHandler) ListUserRoles(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("user")
roles, err := h.imOperator.GetUserRoles(username)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(roles)
}
func (h *iamHandler) ListRoles(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
result, err := h.amOperator.ListRoles(namespace, conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(result)
}
func (h *iamHandler) ListClusterRoles(req *restful.Request, resp *restful.Response) {
limit, offset := params.ParsePaging(req)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
result, err := h.amOperator.ListClusterRoles(conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(result)
}
func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response) {
role := req.PathParameter("role")
namespace := req.PathParameter("namespace")
@@ -152,6 +374,7 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
roleBindings, err := h.amOperator.ListRoleBindings(namespace, role)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -159,12 +382,13 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
for _, roleBinding := range roleBindings {
for _, subject := range roleBinding.Subjects {
if subject.Kind == rbacv1.UserKind {
user, err := h.imOperator.GetUserInfo(subject.Name)
user, err := h.imOperator.DescribeUser(subject.Name)
// skip if user not exist
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
continue
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -176,152 +400,133 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
resp.WriteEntity(result)
}
func (h *iamHandler) ListClusterRoles(req *restful.Request, resp *restful.Response) {
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
orderBy := req.QueryParameter(params.OrderByParam)
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
reverse := params.ParseReverse(req)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := iam.ListClusterRoles(conditions, orderBy, reverse, limit, offset)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}
func (h *iamHandler) ListRoles(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
orderBy := req.QueryParameter(params.OrderByParam)
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
reverse := params.ParseReverse(req)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := iam.ListRoles(namespace, conditions, orderBy, reverse, limit, offset)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}
// List users by namespace
func (h *iamHandler) ListNamespaceUsers(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
users, err := iam.NamespaceUsers(namespace)
roleBindings, err := h.amOperator.ListRoleBindings(namespace, "")
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
// sort by time by default
sort.Slice(users, func(i, j int) bool {
return users[i].RoleBindTime.After(*users[j].RoleBindTime)
})
result := make([]*iam.User, 0)
for _, roleBinding := range roleBindings {
for _, subject := range roleBinding.Subjects {
if subject.Kind == rbacv1.UserKind {
user, err := h.imOperator.DescribeUser(subject.Name)
// skip if user not exist
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
continue
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
result = append(result, user)
}
}
}
resp.WriteAsJson(users)
resp.WriteEntity(result)
}
func (h *iamHandler) ListUserRoles(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("user")
roles, err := iam.GetUserRoles("", username)
func (h *iamHandler) ListClusterRoleUsers(req *restful.Request, resp *restful.Response) {
clusterRole := req.PathParameter("clusterrole")
clusterRoleBindings, err := h.amOperator.ListClusterRoleBindings(clusterRole)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
_, clusterRoles, err := iam.GetUserClusterRoles(username)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
result := make([]*iam.User, 0)
for _, roleBinding := range clusterRoleBindings {
for _, subject := range roleBinding.Subjects {
if subject.Kind == rbacv1.UserKind {
user, err := h.imOperator.DescribeUser(subject.Name)
// skip if user not exist
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
continue
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
result = append(result, user)
}
}
}
roleList := RoleList{}
roleList.Roles = roles
roleList.ClusterRoles = clusterRoles
resp.WriteAsJson(roleList)
resp.WriteEntity(result)
}
func (h *iamHandler) RulesMapping(req *restful.Request, resp *restful.Response) {
rules := policy.RoleRuleMapping
resp.WriteAsJson(rules)
resp.WriteEntity(rules)
}
func (h *iamHandler) ClusterRulesMapping(req *restful.Request, resp *restful.Response) {
rules := policy.ClusterRoleRuleMapping
resp.WriteAsJson(rules)
resp.WriteEntity(rules)
}
func (h *iamHandler) ListClusterRoleRules(req *restful.Request, resp *restful.Response) {
clusterRoleName := req.PathParameter("clusterrole")
rules, err := iam.GetClusterRoleSimpleRules(clusterRoleName)
clusterRole := req.PathParameter("clusterrole")
rules, err := h.amOperator.GetClusterRoleSimpleRules(clusterRole)
if err != nil {
resp.WriteError(http.StatusInternalServerError, err)
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(rules)
}
func (h *iamHandler) ListClusterRoleUsers(req *restful.Request, resp *restful.Response) {
clusterRoleName := req.PathParameter("clusterrole")
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
orderBy := req.QueryParameter(params.OrderByParam)
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
reverse := params.ParseReverse(req)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := iam.ListClusterRoleUsers(clusterRoleName, conditions, orderBy, reverse, limit, offset)
if err != nil {
if k8serr.IsNotFound(err) {
resp.WriteError(http.StatusNotFound, err)
} else {
resp.WriteError(http.StatusInternalServerError, err)
}
return
}
resp.WriteAsJson(result)
resp.WriteEntity(rules)
}
func (h *iamHandler) ListRoleRules(req *restful.Request, resp *restful.Response) {
namespaceName := req.PathParameter("namespace")
roleName := req.PathParameter("role")
namespace := req.PathParameter("namespace")
role := req.PathParameter("role")
rules, err := iam.GetRoleSimpleRules(namespaceName, roleName)
rules, err := h.amOperator.GetRoleSimpleRules(namespace, role)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(rules)
resp.WriteEntity(rules)
}
func (h *iamHandler) ListWorkspaceRoles(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) DescribeWorkspaceRole(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) ListWorkspaceRoleRules(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) ListWorkspaceUsers(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) InviteUser(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) RemoveUser(request *restful.Request, response *restful.Response) {
panic("implement me")
}
func (h *iamHandler) DescribeWorkspaceUser(request *restful.Request, response *restful.Response) {
panic("implement me")
}

View File

@@ -24,104 +24,25 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/api/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/iam"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
iam2 "kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"net/http"
"time"
)
const GroupName = "iam.kubesphere.io"
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
var (
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
AddToContainer = WebServiceBuilder.AddToContainer
)
type UserUpdateRequest struct {
Username string `json:"username" description:"username"`
Email string `json:"email" description:"email address"`
Lang string `json:"lang" description:"user's language setting, default is zh-CN"`
Description string `json:"description" description:"user's description"`
Password string `json:"password,omitempty" description:"this is necessary if you need to change your password"`
CurrentPassword string `json:"current_password,omitempty" description:"this is necessary if you need to change your password"`
ClusterRole string `json:"cluster_role" description:"user's cluster role"`
}
type CreateUserRequest struct {
Username string `json:"username" description:"username"`
Email string `json:"email" description:"email address"`
Lang string `json:"lang,omitempty" description:"user's language setting, default is zh-CN"`
Description string `json:"description" description:"user's description"`
Password string `json:"password" description:"password'"`
ClusterRole string `json:"cluster_role" description:"user's cluster role"`
}
type UserList struct {
Items []struct {
Username string `json:"username" description:"username"`
Email string `json:"email" description:"email address"`
Lang string `json:"lang,omitempty" description:"user's language setting, default is zh-CN"`
Description string `json:"description" description:"user's description"`
ClusterRole string `json:"cluster_role" description:"user's cluster role"`
CreateTime time.Time `json:"create_time" description:"user creation time"`
LastLoginTime time.Time `json:"last_login_time" description:"last login time"`
} `json:"items" description:"paging data"`
TotalCount int `json:"total_count" description:"total count"`
}
type NamespacedUser struct {
Username string `json:"username" description:"username"`
Email string `json:"email" description:"email address"`
Lang string `json:"lang,omitempty" description:"user's language setting, default is zh-CN"`
Description string `json:"description" description:"user's description"`
Role string `json:"role" description:"user's role in the specified namespace"`
RoleBinding string `json:"role_binding" description:"user's role binding name in the specified namespace"`
RoleBindTime string `json:"role_bind_time" description:"user's role binding time"`
CreateTime time.Time `json:"create_time" description:"user creation time"`
LastLoginTime time.Time `json:"last_login_time" description:"last login time"`
}
type ClusterRoleList struct {
Items []rbacv1.ClusterRole `json:"items" description:"paging data"`
TotalCount int `json:"total_count" description:"total count"`
}
type LoginLog struct {
LoginTime string `json:"login_time" description:"last login time"`
LoginIP string `json:"login_ip" description:"last login ip"`
}
type RoleList struct {
Items []rbacv1.Role `json:"items" description:"paging data"`
TotalCount int `json:"total_count" description:"total count"`
}
type InviteUserRequest struct {
Username string `json:"username" description:"username"`
WorkspaceRole string `json:"workspace_role" description:"user's workspace role'"`
}
type DescribeWorkspaceUserResponse struct {
Username string `json:"username" description:"username"`
Email string `json:"email" description:"email address"`
Lang string `json:"lang" description:"user's language setting, default is zh-CN"`
Description string `json:"description" description:"user's description"`
ClusterRole string `json:"cluster_role" description:"user's cluster role"`
WorkspaceRole string `json:"workspace_role" description:"user's workspace role"`
CreateTime time.Time `json:"create_time" description:"user creation time"`
LastLoginTime time.Time `json:"last_login_time" description:"last login time"`
}
func addWebService(c *restful.Container) error {
func AddToContainer(c *restful.Container, k8sClient k8s.Client, ldapClient ldappool.Client, options iam.Config) error {
ws := runtime.NewWebService(GroupVersion)
handler := newIAMHandler()
handler := newIAMHandler(k8sClient, ldapClient, options)
ws.Route(ws.POST("/authenticate").
To(handler.TokenReviewHandler).
@@ -138,152 +59,132 @@ func addWebService(c *restful.Container) error {
ws.Route(ws.POST("/users").
To(handler.CreateUser).
Doc("Create a user account.").
Reads(CreateUserRequest{}).
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Reads(iamv1alpha2.CreateUserRequest{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.UserDetail{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.GET("/users/{user}").
To(iam.DescribeUser).
Doc("Describe the specified user.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iam2.User{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.DELETE("/users/{user}").
To(iam.DeleteUser).
To(handler.DeleteUser).
Doc("Delete the specified user.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.PUT("/users/{user}").
To(iam.UpdateUser).
To(handler.ModifyUser).
Doc("Update information about the specified user.").
Param(ws.PathParameter("user", "username")).
Reads(UserUpdateRequest{}).
Reads(iamv1alpha2.ModifyUserRequest{}).
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.GET("/users/{user}/logs").
To(iam.UserLoginLogs).
Doc("Retrieve the \"login logs\" for the specified user.").
ws.Route(ws.GET("/users/{user}").
To(handler.DescribeUser).
Doc("Describe the specified user.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, LoginLog{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.UserDetail{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.GET("/users").
To(iam.ListUsers).
To(handler.ListUsers).
Doc("List all users.").
Returns(http.StatusOK, api.StatusOK, UserList{}).
Returns(http.StatusOK, api.StatusOK, iamv1alpha2.ListUserResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.IdentityManagementTag}))
ws.Route(ws.GET("/users/{user}/roles").
To(iam.ListUserRoles).
To(handler.ListUserRoles).
Doc("Retrieve all the roles that are assigned to the specified user.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iam.RoleList{}).
Returns(http.StatusOK, api.StatusOK, []*rbacv1.Role{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/roles").
To(iam.ListRoles).
To(handler.ListRoles).
Doc("Retrieve the roles that are assigned to the user in the specified namespace.").
Param(ws.PathParameter("namespace", "kubernetes namespace")).
Returns(http.StatusOK, api.StatusOK, RoleList{}).
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clusterroles").
To(iam.ListClusterRoles).
To(handler.ListClusterRoles).
Doc("List all cluster roles.").
Returns(http.StatusOK, api.StatusOK, ClusterRoleList{}).
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/roles/{role}/users").
To(handler.ListRoleUsers).
Doc("Retrieve the users that are bound to the role in the specified namespace.").
Param(ws.PathParameter("namespace", "kubernetes namespace")).
Param(ws.PathParameter("role", "role name")).
Returns(http.StatusOK, api.StatusOK, []NamespacedUser{}).
Returns(http.StatusOK, api.StatusOK, []iamv1alpha2.ListUserResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/users").
To(iam.ListNamespaceUsers).
To(handler.ListNamespaceUsers).
Doc("List all users in the specified namespace.").
Param(ws.PathParameter("namespace", "kubernetes namespace")).
Returns(http.StatusOK, api.StatusOK, []NamespacedUser{}).
Returns(http.StatusOK, api.StatusOK, []iamv1alpha2.ListUserResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clusterroles/{clusterrole}/users").
To(iam.ListClusterRoleUsers).
To(handler.ListClusterRoleUsers).
Doc("List all users that are bound to the specified cluster role.").
Param(ws.PathParameter("clusterrole", "cluster role name")).
Returns(http.StatusOK, api.StatusOK, UserList{}).
Returns(http.StatusOK, api.StatusOK, []iamv1alpha2.ListUserResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/clusterroles/{clusterrole}/rules").
To(iam.ListClusterRoleRules).
To(handler.ListClusterRoleRules).
Doc("List all policy rules of the specified cluster role.").
Param(ws.PathParameter("clusterrole", "cluster role name")).
Returns(http.StatusOK, api.StatusOK, []iam2.SimpleRule{}).
Returns(http.StatusOK, api.StatusOK, []iam.SimpleRule{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/roles/{role}/rules").
To(iam.ListRoleRules).
To(handler.ListRoleRules).
Doc("List all policy rules of the specified role in the given namespace.").
Param(ws.PathParameter("namespace", "kubernetes namespace")).
Param(ws.PathParameter("role", "role name")).
Returns(http.StatusOK, api.StatusOK, []iam2.SimpleRule{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/devops/{devops}/roles/{role}/rules").
To(iam.ListDevopsRoleRules).
Doc("List all policy rules of the specified role in the given devops project.").
Param(ws.PathParameter("devops", "devops project ID")).
Param(ws.PathParameter("role", "devops role name")).
Returns(http.StatusOK, api.StatusOK, []iam2.SimpleRule{}).
Returns(http.StatusOK, api.StatusOK, []iam.SimpleRule{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/rulesmapping/clusterroles").
To(iam.ClusterRulesMapping).
To(handler.ClusterRulesMapping).
Doc("Get the mapping relationships between cluster roles and policy rules.").
Returns(http.StatusOK, api.StatusOK, policy.ClusterRoleRuleMapping).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/rulesmapping/roles").
To(iam.RulesMapping).
To(handler.RulesMapping).
Doc("Get the mapping relationships between namespaced roles and policy rules.").
Returns(http.StatusOK, api.StatusOK, policy.RoleRuleMapping).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/roles").
To(iam.ListWorkspaceRoles).
To(handler.ListWorkspaceRoles).
Doc("List all workspace roles.").
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, ClusterRoleList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/roles/{role}").
To(iam.DescribeWorkspaceRole).
To(handler.DescribeWorkspaceRole).
Doc("Describe the workspace role.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("role", "workspace role name")).
Returns(http.StatusOK, api.StatusOK, rbacv1.ClusterRole{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/roles/{role}/rules").
To(iam.ListWorkspaceRoleRules).
To(handler.ListWorkspaceRoleRules).
Doc("List all policy rules of the specified workspace role.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("role", "workspace role name")).
Returns(http.StatusOK, api.StatusOK, []iam2.SimpleRule{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/members").
To(iam.ListWorkspaceUsers).
To(handler.ListWorkspaceUsers).
Doc("List all members in the specified workspace.").
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, UserList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.POST("/workspaces/{workspace}/members").
To(iam.InviteUser).
To(handler.InviteUser).
Doc("Invite a member to the specified workspace.").
Param(ws.PathParameter("workspace", "workspace name")).
Reads(InviteUserRequest{}).
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/members/{member}").
To(iam.RemoveUser).
To(handler.RemoveUser).
Doc("Remove the specified member from the workspace.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("member", "username")).
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}").
To(iam.DescribeWorkspaceUser).
To(handler.DescribeWorkspaceUser).
Doc("Describe the specified user in the given workspace.").
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("member", "username")).
Returns(http.StatusOK, api.StatusOK, DescribeWorkspaceUserResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
c.Add(ws)
return nil

View File

@@ -13,22 +13,25 @@ import (
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
op "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
)
func InstallAPIs(container *restful.Container, client k8s.Client) {
func InstallAPIs(container *restful.Container, client k8s.Client, op op.Client, db *mysql.Database) {
urlruntime.Must(servicemeshv1alpha2.AddToContainer(container))
urlruntime.Must(devopsv1alpha2.AddToContainer(container))
urlruntime.Must(loggingv1alpha2.AddToContainer(container))
urlruntime.Must(monitoringv1alpha2.AddToContainer(container))
urlruntime.Must(openpitrixv1.AddToContainer(container))
urlruntime.Must(openpitrixv1.AddToContainer(container, client, op))
urlruntime.Must(operationsv1alpha2.AddToContainer(container, client))
urlruntime.Must(resourcesv1alpha2.AddToContainer(container, client))
urlruntime.Must(tenantv1alpha2.AddToContainer(container))
urlruntime.Must(terminalv1alpha2.AddToContainer(container))
urlruntime.Must(tenantv1alpha2.AddToContainer(container))
urlruntime.Must(tenantv1alpha2.AddToContainer(container, client, db))
urlruntime.Must(terminalv1alpha2.AddToContainer(container, client))
}
func InstallAuthorizationAPIs(container *restful.Container) {
urlruntime.Must(iamv1alpha2.AddToContainer(container))
func InstallAuthorizationAPIs(container *restful.Container, k8sClient k8s.Client, ldapClient ldappool.Client, imOptions iam.Config) {
urlruntime.Must(iamv1alpha2.AddToContainer(container, k8sClient, ldapClient, imOptions))
}

View File

@@ -6,6 +6,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
k8sinformers "k8s.io/client-go/informers"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
@@ -15,7 +16,6 @@ import (
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
op "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"net/http"
"strconv"
"strings"
)
@@ -43,6 +43,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
conditions, err := params.ParseConditions(request)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
return
}
@@ -52,6 +53,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
ns, err := h.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
return
}
@@ -71,6 +73,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
result, err := h.openpitrix.ListApplications(conditions, limit, offset, orderBy, reverse)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
return
}
@@ -85,17 +88,15 @@ func (h *openpitrixHandler) DescribeApplication(req *restful.Request, resp *rest
app, err := h.openpitrix.DescribeApplication(namespace, clusterId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
ns, err := h.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -104,6 +105,7 @@ func (h *openpitrixHandler) DescribeApplication(req *restful.Request, resp *rest
if runtimeId != app.Cluster.RuntimeId {
err = fmt.Errorf("rumtime not match %s,%s", app.Cluster.RuntimeId, runtimeId)
klog.V(4).Infoln(err)
api.HandleForbidden(resp, err)
return
}
@@ -117,6 +119,7 @@ func (h *openpitrixHandler) CreateApplication(req *restful.Request, resp *restfu
var createClusterRequest openpitrix.CreateClusterRequest
err := req.ReadEntity(&createClusterRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -126,6 +129,7 @@ func (h *openpitrixHandler) CreateApplication(req *restful.Request, resp *restfu
err = h.openpitrix.CreateApplication(namespace, createClusterRequest)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -139,6 +143,7 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
namespace := req.PathParameter("namespace")
err := req.ReadEntity(&modifyClusterAttributesRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -146,17 +151,15 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
app, err := h.openpitrix.DescribeApplication(namespace, clusterId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
ns, err := h.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -165,6 +168,7 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
if runtimeId != app.Cluster.RuntimeId {
err = fmt.Errorf("rumtime not match %s,%s", app.Cluster.RuntimeId, runtimeId)
klog.V(4).Infoln(err)
api.HandleForbidden(resp, err)
return
}
@@ -172,11 +176,8 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
err = h.openpitrix.ModifyApplication(modifyClusterAttributesRequest)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -189,17 +190,15 @@ func (h *openpitrixHandler) DeleteApplication(req *restful.Request, resp *restfu
app, err := h.openpitrix.DescribeApplication(namespace, clusterId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
ns, err := h.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -208,6 +207,7 @@ func (h *openpitrixHandler) DeleteApplication(req *restful.Request, resp *restfu
if runtimeId != app.Cluster.RuntimeId {
err = fmt.Errorf("rumtime not match %s,%s", app.Cluster.RuntimeId, runtimeId)
klog.V(4).Infoln(err)
api.HandleForbidden(resp, err)
return
}
@@ -215,11 +215,8 @@ func (h *openpitrixHandler) DeleteApplication(req *restful.Request, resp *restfu
err = h.openpitrix.DeleteApplication(clusterId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -233,6 +230,7 @@ func (h *openpitrixHandler) GetAppVersionPackage(req *restful.Request, resp *res
result, err := h.openpitrix.GetAppVersionPackage(appId, versionId)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -244,6 +242,7 @@ func (h *openpitrixHandler) DoAppAction(req *restful.Request, resp *restful.Resp
var doActionRequest openpitrix.ActionRequest
err := req.ReadEntity(&doActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -253,15 +252,8 @@ func (h *openpitrixHandler) DoAppAction(req *restful.Request, resp *restful.Resp
err = h.openpitrix.DoAppAction(appId, &doActionRequest)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -272,6 +264,7 @@ func (h *openpitrixHandler) DoAppVersionAction(req *restful.Request, resp *restf
var doActionRequest openpitrix.ActionRequest
err := req.ReadEntity(&doActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -282,15 +275,8 @@ func (h *openpitrixHandler) DoAppVersionAction(req *restful.Request, resp *restf
err = h.openpitrix.DoAppVersionAction(versionId, &doActionRequest)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -307,11 +293,8 @@ func (h *openpitrixHandler) GetAppVersionFiles(req *restful.Request, resp *restf
result, err := h.openpitrix.GetAppVersionFiles(versionId, getAppVersionFilesRequest)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -327,6 +310,7 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -339,7 +323,8 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res
result, err := h.openpitrix.ListAppVersionAudits(conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -353,6 +338,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -360,6 +346,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
result, err := h.openpitrix.ListAppVersionReviews(conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -376,6 +363,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -384,6 +372,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
result, err := h.openpitrix.ListAppVersions(conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -393,6 +382,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
if version, ok := item.(*openpitrix.AppVersion); ok {
statisticsResult, err := h.openpitrix.ListApplications(&params.Conditions{Match: map[string]string{"app_id": version.AppId, "version_id": version.VersionId}}, 0, 0, "", false)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
@@ -412,6 +402,7 @@ func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Respons
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -419,7 +410,8 @@ func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Respons
result, err := h.openpitrix.ListApps(conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -429,7 +421,8 @@ func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Respons
statuses := "active|used|enabled|stopped|pending|creating|upgrading|updating|rollbacking|stopping|starting|recovering|resizing|scaling|deleting"
statisticsResult, err := h.openpitrix.ListApplications(&params.Conditions{Match: map[string]string{openpitrix.AppId: app.AppId, openpitrix.Status: statuses}}, 0, 0, "", false)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
app.ClusterTotal = &statisticsResult.TotalCount
@@ -447,6 +440,7 @@ func (h *openpitrixHandler) ModifyApp(req *restful.Request, resp *restful.Respon
appId := req.PathParameter("app")
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -454,15 +448,8 @@ func (h *openpitrixHandler) ModifyApp(req *restful.Request, resp *restful.Respon
err = h.openpitrix.ModifyApp(appId, &patchAppRequest)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -475,11 +462,8 @@ func (h *openpitrixHandler) DescribeApp(req *restful.Request, resp *restful.Resp
result, err := h.openpitrix.DescribeApp(appId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -507,7 +491,8 @@ func (h *openpitrixHandler) CreateApp(req *restful.Request, resp *restful.Respon
createAppRequest := &openpitrix.CreateAppRequest{}
err := req.ReadEntity(createAppRequest)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -543,6 +528,7 @@ func (h *openpitrixHandler) CreateAppVersion(req *restful.Request, resp *restful
var createAppVersionRequest openpitrix.CreateAppVersionRequest
err := req.ReadEntity(&createAppVersionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -565,11 +551,8 @@ func (h *openpitrixHandler) CreateAppVersion(req *restful.Request, resp *restful
}
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -583,6 +566,7 @@ func (h *openpitrixHandler) ModifyAppVersion(req *restful.Request, resp *restful
versionId := req.PathParameter("version")
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -590,11 +574,8 @@ func (h *openpitrixHandler) ModifyAppVersion(req *restful.Request, resp *restful
err = h.openpitrix.ModifyAppVersion(versionId, &patchAppVersionRequest)
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -607,11 +588,8 @@ func (h *openpitrixHandler) DeleteAppVersion(req *restful.Request, resp *restful
err := h.openpitrix.DeleteAppVersion(versionId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -624,11 +602,8 @@ func (h *openpitrixHandler) DescribeAppVersion(req *restful.Request, resp *restf
result, err := h.openpitrix.DescribeAppVersion(versionId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -641,11 +616,8 @@ func (h *openpitrixHandler) DescribeAttachment(req *restful.Request, resp *restf
result, err := h.openpitrix.DescribeAttachment(attachmentId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -664,6 +636,7 @@ func (h *openpitrixHandler) CreateCategory(req *restful.Request, resp *restful.R
createCategoryRequest := &openpitrix.CreateCategoryRequest{}
err := req.ReadEntity(createCategoryRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -671,11 +644,8 @@ func (h *openpitrixHandler) CreateCategory(req *restful.Request, resp *restful.R
result, err := h.openpitrix.CreateCategory(createCategoryRequest)
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -687,11 +657,8 @@ func (h *openpitrixHandler) DeleteCategory(req *restful.Request, resp *restful.R
err := h.openpitrix.DeleteCategory(categoryId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -702,6 +669,7 @@ func (h *openpitrixHandler) ModifyCategory(req *restful.Request, resp *restful.R
categoryId := req.PathParameter("category")
err := req.ReadEntity(&modifyCategoryRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -709,11 +677,8 @@ func (h *openpitrixHandler) ModifyCategory(req *restful.Request, resp *restful.R
err = h.openpitrix.ModifyCategory(categoryId, &modifyCategoryRequest)
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -725,11 +690,8 @@ func (h *openpitrixHandler) DescribeCategory(req *restful.Request, resp *restful
result, err := h.openpitrix.DescribeCategory(categoryId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -743,6 +705,7 @@ func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.R
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -750,7 +713,8 @@ func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.R
result, err := h.openpitrix.ListCategories(conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -759,7 +723,8 @@ func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.R
if category, ok := item.(*openpitrix.Category); ok {
statisticsResult, err := h.openpitrix.ListApps(&params.Conditions{Match: map[string]string{"category_id": category.CategoryID, "status": openpitrix.StatusActive, "repo": openpitrix.BuiltinRepoId}}, "", false, 0, 0)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
category.AppTotal = &statisticsResult.TotalCount
@@ -774,6 +739,7 @@ func (h *openpitrixHandler) CreateRepo(req *restful.Request, resp *restful.Respo
createRepoRequest := &openpitrix.CreateRepoRequest{}
err := req.ReadEntity(createRepoRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -793,11 +759,8 @@ func (h *openpitrixHandler) CreateRepo(req *restful.Request, resp *restful.Respo
}
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -809,6 +772,7 @@ func (h *openpitrixHandler) DoRepoAction(req *restful.Request, resp *restful.Res
repoId := req.PathParameter("repo")
err := req.ReadEntity(repoActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -816,11 +780,8 @@ func (h *openpitrixHandler) DoRepoAction(req *restful.Request, resp *restful.Res
err = h.openpitrix.DoRepoAction(repoId, repoActionRequest)
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -833,11 +794,8 @@ func (h *openpitrixHandler) DeleteRepo(req *restful.Request, resp *restful.Respo
err := h.openpitrix.DeleteRepo(repoId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -849,6 +807,7 @@ func (h *openpitrixHandler) ModifyRepo(req *restful.Request, resp *restful.Respo
repoId := req.PathParameter("repo")
err := req.ReadEntity(&updateRepoRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -856,11 +815,8 @@ func (h *openpitrixHandler) ModifyRepo(req *restful.Request, resp *restful.Respo
err = h.openpitrix.ModifyRepo(repoId, &updateRepoRequest)
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -873,11 +829,8 @@ func (h *openpitrixHandler) DescribeRepo(req *restful.Request, resp *restful.Res
result, err := h.openpitrix.DescribeRepo(repoId)
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
return
}
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -890,6 +843,7 @@ func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Respon
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -897,7 +851,8 @@ func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Respon
result, err := h.openpitrix.ListRepos(conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
@@ -910,6 +865,7 @@ func (h *openpitrixHandler) ListRepoEvents(req *restful.Request, resp *restful.R
conditions, err := params.ParseConditions(req)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -917,9 +873,25 @@ func (h *openpitrixHandler) ListRepoEvents(req *restful.Request, resp *restful.R
result, err := h.openpitrix.ListRepoEvents(repoId, conditions, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
klog.Errorln(err)
handleOpenpitrixError(resp, err)
return
}
resp.WriteEntity(result)
}
func handleOpenpitrixError(resp *restful.Response, err error) {
if status.Code(err) == codes.NotFound {
klog.V(4).Infoln(err)
api.HandleNotFound(resp, err)
return
}
if status.Code(err) == codes.InvalidArgument {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
}

View File

@@ -1,154 +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 (
"github.com/emicklei/go-restful"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"net/http"
)
func (h *tenantHandler) DeleteDevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
projectId := req.PathParameter("devops")
workspaceName := req.PathParameter("workspace")
username := req.HeaderParameter(constants.UserNameHeader)
_, err := h.tenant.GetWorkspace(workspaceName)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
return
}
err = h.tenant.DeleteDevOpsProject(projectId, username)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(err, resp)
return
}
resp.WriteAsJson(errors.None)
}
func (h *tenantHandler) CreateDevOpsProjectHandler(req *restful.Request, resp *restful.Response) {
workspaceName := req.PathParameter("workspace")
username := req.HeaderParameter(constants.UserNameHeader)
var devops devopsv1alpha2.DevOpsProject
err := req.ReadEntity(&devops)
if err != nil {
klog.Infof("%+v", err)
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
return
}
klog.Infoln("create workspace", username, workspaceName, devops)
project, err := h.tenant.CreateDevOpsProject(username, workspaceName, &devops)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(err, resp)
return
}
resp.WriteAsJson(project)
}
func (h *tenantHandler) GetDevOpsProjectsCountHandler(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
result, err := h.tenant.GetDevOpsProjectsCount(username)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(err, resp)
return
}
resp.WriteAsJson(struct {
Count uint32 `json:"count"`
}{Count: result})
}
func (h *tenantHandler) ListDevOpsProjectsHandler(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.PathParameter("member")
if username == "" {
username = req.HeaderParameter(constants.UserNameHeader)
}
orderBy := req.QueryParameter(params.OrderByParam)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, false)
limit, offset := params.ParsePaging(req)
conditions, err := params.ParseConditions(req)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), resp)
return
}
result, err := h.tenant.ListDevOpsProjects(workspace, username, conditions, orderBy, reverse, limit, offset)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(err, resp)
return
}
resp.WriteAsJson(result)
}
func (h *tenantHandler) ListDevOpsRules(req *restful.Request, resp *restful.Response) {
devops := req.PathParameter("devops")
username := req.HeaderParameter(constants.UserNameHeader)
rules, err := h.tenant.GetUserDevOpsSimpleRules(username, devops)
if err != nil {
klog.Errorf("%+v", err)
errors.ParseSvcErr(err, resp)
return
}
resp.WriteAsJson(rules)
}
func (h *tenantHandler) ListDevopsRules(req *restful.Request, resp *restful.Response) {
devops := req.PathParameter("devops")
username := req.HeaderParameter(constants.UserNameHeader)
rules, err := h.tenant.GetUserDevOpsSimpleRules(username, devops)
if err != nil {
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(rules)
}

View File

@@ -11,12 +11,15 @@ import (
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/logging"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/tenant"
"kubesphere.io/kubesphere/pkg/server/errors"
apierr "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"net/http"
"strings"
@@ -24,24 +27,31 @@ import (
type tenantHandler struct {
tenant tenant.Interface
am iam.AccessManagementInterface
}
func newTenantHandler() *tenantHandler {
return &tenantHandler{}
func newTenantHandler(k8sClient k8s.Client, db *mysql.Database) *tenantHandler {
factory := informers.NewInformerFactories(k8sClient.Kubernetes(), k8sClient.KubeSphere(), k8sClient.S2i(), k8sClient.Application())
return &tenantHandler{
tenant: tenant.New(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory(), factory.KubeSphereSharedInformerFactory(), db),
am: iam.NewAMOperator(factory.KubernetesSharedInformerFactory()),
}
}
func (h *tenantHandler) ListWorkspaceRules(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.HeaderParameter(constants.UserNameHeader)
rules, err := iam.GetUserWorkspaceSimpleRules(workspace, username)
rules, err := h.tenant.GetWorkspaceSimpleRules(workspace, username)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(rules)
resp.WriteEntity(rules)
}
func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Response) {
@@ -52,6 +62,7 @@ func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Respo
conditions, err := params.ParseConditions(req)
if err != nil {
klog.Errorln(err)
api.HandleBadRequest(resp, err)
return
}
@@ -180,9 +191,49 @@ func (h *tenantHandler) DeleteNamespace(req *restful.Request, resp *restful.Resp
return
}
resp.WriteAsJson(errors.None)
resp.WriteAsJson(apierr.None)
}
func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.PathParameter("member")
if username == "" {
username = req.HeaderParameter(constants.UserNameHeader)
}
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
limit, offset := params.ParsePaging(req)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
api.HandleBadRequest(resp, err)
return
}
conditions.Match["workspace"] = workspace
result, err := h.tenant.ListDevopsProjects(username, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(result)
}
func (h *tenantHandler) GetDevOpsProjectsCount(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
result, err := h.tenant.ListDevopsProjects(username, nil, "", false, 1, 0)
if err != nil {
api.HandleInternalError(resp, err)
return
}
resp.WriteEntity(struct {
Count int `json:"count"`
}{Count: result.TotalCount})
}
func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.Response) {
projectId := req.PathParameter("devops")
workspace := req.PathParameter("workspace")
@@ -195,21 +246,40 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
return
}
err = h.tenant.DeleteDevOpsProject(projectId, username)
err = h.tenant.DeleteDevOpsProject(username, projectId)
if err != nil {
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(errors.None)
resp.WriteEntity(apierr.None)
}
func (h *tenantHandler) CreateDevopsProject(req *restful.Request, resp *restful.Response) {
}
func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
username := req.HeaderParameter(constants.UserNameHeader)
rules, err := iam.GetUserNamespaceSimpleRules(namespace, username)
rules, err := h.tenant.GetNamespaceSimpleRules(namespace, username)
if err != nil {
api.HandleInternalError(resp, err)
return
}
resp.WriteAsJson(rules)
}
func (h *tenantHandler) ListDevopsRules(req *restful.Request, resp *restful.Response) {
devops := req.PathParameter("devops")
username := req.HeaderParameter(constants.UserNameHeader)
rules, err := h.tenant.GetUserDevopsSimpleRules(username, devops)
if err != nil {
api.HandleInternalError(resp, err)
@@ -247,19 +317,20 @@ func (h *tenantHandler) regenerateLoggingRequest(req *restful.Request) (*restful
newUrl := net.FormatURL("http", "127.0.0.1", 80, "/kapis/logging.kubesphere.io/v1alpha2/cluster")
values := req.Request.URL.Query()
clusterRules, err := iam.GetUserClusterRules(username)
clusterRoleRules, err := h.am.GetClusterPolicyRules(username)
if err != nil {
klog.Errorln(err)
return nil, err
}
hasClusterLogAccess := iam.RulesMatchesRequired(clusterRules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}})
hasClusterLogAccess := iam.RulesMatchesRequired(clusterRoleRules, rbacv1.PolicyRule{Verbs: []string{"get"}, Resources: []string{"*"}, APIGroups: []string{"logging.kubesphere.io"}})
// if the user is not a cluster admin
if !hasClusterLogAccess {
queryNamespaces := strings.Split(req.QueryParameter("namespaces"), ",")
// then the user can only view logs of namespaces he belongs to
namespaces := make([]string, 0)
roles, err := iam.GetUserRoles("", username)
roles, err := h.am.GetRoles("", username)
if err != nil {
klog.Errorln(err)
return nil, err

View File

@@ -32,6 +32,8 @@ import (
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
)
@@ -42,9 +44,9 @@ const (
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
func AddToContainer(c *restful.Container) error {
func AddToContainer(c *restful.Container, k8sClient k8s.Client, db *mysql.Database) error {
ws := runtime.NewWebService(GroupVersion)
handler := newTenantHandler()
handler := newTenantHandler(k8sClient, db)
ws.Route(ws.GET("/workspaces").
To(handler.ListWorkspaces).
@@ -103,7 +105,7 @@ func AddToContainer(c *restful.Container) error {
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/devops").
To(handler.ListDevOpsProjectsHandler).
To(handler.ListDevopsProjects).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.QueryParameter(params.PagingParam, "page").
Required(false).
@@ -115,7 +117,7 @@ func AddToContainer(c *restful.Container) error {
Doc("List devops projects for the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/devops").
To(handler.ListDevOpsProjectsHandler).
To(handler.ListDevopsProjects).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("member", "workspace member's username")).
Param(ws.QueryParameter(params.PagingParam, "page").
@@ -129,14 +131,14 @@ func AddToContainer(c *restful.Container) error {
Doc("List the devops projects for the workspace member").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/devopscount").
To(handler.GetDevOpsProjectsCountHandler).
To(handler.GetDevOpsProjectsCount).
Returns(http.StatusOK, api.StatusOK, struct {
Count uint32 `json:"count"`
}{}).
Doc("Get the devops projects count for the member").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.POST("/workspaces/{workspace}/devops").
To(handler.CreateDevOpsProjectHandler).
To(handler.CreateDevopsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("Create a devops project in the specified workspace").
Reads(devopsv1alpha2.DevOpsProject{}).

View File

@@ -21,11 +21,10 @@ import (
"github.com/emicklei/go-restful"
"github.com/emicklei/go-restful-openapi"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
)
const (
@@ -34,11 +33,11 @@ const (
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
func AddToContainer(c *restful.Container, client kubernetes.Interface, config *rest.Config) error {
func AddToContainer(c *restful.Container, k8sClient k8s.Client) error {
webservice := runtime.NewWebService(GroupVersion)
handler := newTerminalHandler(client, config)
handler := newTerminalHandler(k8sClient.Kubernetes(), k8sClient.Config())
webservice.Route(webservice.GET("/namespaces/{namespace}/pods/{pod}").
To(handler.handleTerminalSession).