refactor authentication (#1950)

This commit is contained in:
zryfish
2020-03-15 17:55:55 +08:00
committed by GitHub
parent abf0d66b22
commit eb8a3c0dc6
32 changed files with 522 additions and 381 deletions

View File

@@ -31,8 +31,9 @@ after_success:
- bash <(curl -s https://codecov.io/bash)
deploy:
skip_cleanup: true
provider: script
script: bash hack/docker_build.sh
on:
branch: master
- skip_cleanup: true
provider: script
script: bash hack/docker_build.sh
on:
all_branches: true
condition: $TRAVIS_BRANCH =~ ^(master|dev)$

View File

@@ -99,7 +99,9 @@ const fakeInterface string = "FAKE"
// NewAPIServer creates an APIServer instance using given options
func (s *ServerRunOptions) NewAPIServer(stopCh <-chan struct{}) (*apiserver.APIServer, error) {
apiServer := &apiserver.APIServer{}
apiServer := &apiserver.APIServer{
AuthenticateOptions: s.AuthenticateOptions,
}
kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions)
if err != nil {

View File

@@ -3,8 +3,9 @@
set -ex
set -o pipefail
# push to kubespheredev with default latest tag
REPO=kubespheredev
TAG=latest
TAG=${TRAVIS_BRANCH:-latest}
# check if build was triggered by a travis cronjob
if [[ -z "$TRAVIS_EVENT_TYPE" ]]; then
@@ -14,17 +15,11 @@ elif [[ $TRAVIS_EVENT_TYPE == "cron" ]]; then
fi
docker build -f build/ks-apigateway/Dockerfile -t $REPO/ks-apigateway:$TAG .
docker build -f build/ks-apiserver/Dockerfile -t $REPO/ks-apiserver:$TAG .
docker build -f build/ks-controller-manager/Dockerfile -t $REPO/ks-controller-manager:$TAG .
docker build -f build/hypersphere/Dockerfile -t $REPO/hypersphere:$TAG .
docker build -f ./pkg/db/Dockerfile -t $REPO/ks-devops:flyway-$TAG ./pkg/db/
# Push image to dockerhub, need to support multiple push
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker push $REPO/ks-apigateway:$TAG
docker push $REPO/ks-apiserver:$TAG
docker push $REPO/ks-controller-manager:$TAG
docker push $REPO/hypersphere:$TAG
docker push $REPO/ks-devops:flyway-$TAG

View File

@@ -1,6 +1,7 @@
package iam
import (
"fmt"
"github.com/spf13/pflag"
"time"
)
@@ -14,10 +15,14 @@ type AuthenticationOptions struct {
MaxAuthenticateRetries int
// token validation duration, will refresh token expiration for each user request
// 0 means never expire
TokenExpiration time.Duration
// allow multiple users login at the same time
MultipleLogin bool
// secret to signed jwt token
JwtSecret string
}
func NewAuthenticateOptions() *AuthenticationOptions {
@@ -27,11 +32,17 @@ func NewAuthenticateOptions() *AuthenticationOptions {
MaxAuthenticateRetries: 0,
TokenExpiration: 0,
MultipleLogin: false,
JwtSecret: "",
}
}
func (options *AuthenticationOptions) Validate() []error {
var errs []error
if len(options.JwtSecret) == 0 {
errs = append(errs, fmt.Errorf("jwt secret is empty"))
}
return errs
}
@@ -39,6 +50,7 @@ func (options *AuthenticationOptions) AddFlags(fs *pflag.FlagSet, s *Authenticat
fs.IntVar(&options.AuthenticateRateLimiterMaxTries, "authenticate-rate-limiter-max-retries", s.AuthenticateRateLimiterMaxTries, "")
fs.DurationVar(&options.AuthenticateRateLimiterDuration, "authenticate-rate-limiter-duration", s.AuthenticateRateLimiterDuration, "")
fs.IntVar(&options.MaxAuthenticateRetries, "authenticate-max-retries", s.MaxAuthenticateRetries, "")
fs.DurationVar(&options.TokenExpiration, "token-expiration", s.TokenExpiration, "")
fs.BoolVar(&options.MultipleLogin, "multiple-login", s.MultipleLogin, "")
fs.DurationVar(&options.TokenExpiration, "token-expiration", s.TokenExpiration, "Token expire duration, for example 30m/2h/1d, 0 means token never expire unless server restart.")
fs.BoolVar(&options.MultipleLogin, "multiple-login", s.MultipleLogin, "Allow multiple login with the same account, disable means only one user can login at the same time.")
fs.StringVar(&options.JwtSecret, "jwt-secret", s.JwtSecret, "Secret to sign jwt token, must not be empty.")
}

View File

@@ -0,0 +1,10 @@
package token
// Issuer issues token to user, tokens are required to perform mutating requests to resources
type Issuer interface {
// IssueTo issues a token a User, return error if issuing process failed
IssueTo(User) (string, error)
// Verify verifies a token, and return a User if it's a valid token, otherwise return error
Verify(string) (User, error)
}

75
pkg/api/iam/token/jwt.go Normal file
View File

@@ -0,0 +1,75 @@
package token
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/server/errors"
"time"
)
const DefaultIssuerName = "kubesphere"
var errInvalidToken = errors.New("invalid token")
type claims struct {
Username string `json:"username"`
UID string `json:"uid"`
// Currently, we are not using any field in jwt.StandardClaims
jwt.StandardClaims
}
type jwtTokenIssuer struct {
name string
secret []byte
keyFunc jwt.Keyfunc
}
func (s *jwtTokenIssuer) Verify(tokenString string) (User, error) {
if len(tokenString) == 0 {
return nil, errInvalidToken
}
clm := &claims{}
_, err := jwt.ParseWithClaims(tokenString, clm, s.keyFunc)
if err != nil {
return nil, err
}
return &iam.User{Username: clm.Username, Email: clm.UID}, nil
}
func (s *jwtTokenIssuer) IssueTo(user User) (string, error) {
clm := &claims{
Username: user.Name(),
UID: user.UID(),
StandardClaims: jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
Issuer: s.name,
NotBefore: time.Now().Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, clm)
tokenString, err := token.SignedString(s.secret)
if err != nil {
return "", err
}
return tokenString, nil
}
func NewJwtTokenIssuer(issuerName string, secret []byte) Issuer {
return &jwtTokenIssuer{
name: issuerName,
secret: secret,
keyFunc: func(token *jwt.Token) (i interface{}, err error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok {
return secret, nil
} else {
return nil, fmt.Errorf("expect token signed with HMAC but got %v", token.Header["alg"])
}
},
}
}

View File

@@ -0,0 +1,49 @@
package token
import (
"github.com/google/go-cmp/cmp"
"kubesphere.io/kubesphere/pkg/api/iam"
"testing"
)
func TestJwtTokenIssuer(t *testing.T) {
issuer := NewJwtTokenIssuer(DefaultIssuerName, []byte("kubesphere"))
testCases := []struct {
description string
name string
email string
}{
{
name: "admin",
email: "admin@kubesphere.io",
},
{
name: "bar",
email: "bar@kubesphere.io",
},
}
for _, testCase := range testCases {
user := &iam.User{
Username: testCase.name,
Email: testCase.email,
}
t.Run(testCase.description, func(t *testing.T) {
token, err := issuer.IssueTo(user)
if err != nil {
t.Fatal(err)
}
got, err := issuer.Verify(token)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(user, got); len(diff) != 0 {
t.Errorf("%T differ (-got, +expected), %s", user, diff)
}
})
}
}

View File

@@ -0,0 +1,8 @@
package token
type User interface {
// Name
Name() string
UID() string
}

View File

@@ -27,6 +27,14 @@ func NewUser() *User {
}
}
func (u *User) Name() string {
return u.Username
}
func (u *User) UID() string {
return u.Email
}
func (u *User) Validate() error {
if u.Username == "" {
return errors.New("username can not be empty")

View File

@@ -5,20 +5,19 @@ import (
"net/http"
)
func HandleInternalError(response *restful.Response, err error) {
statusCode := http.StatusInternalServerError
response.WriteError(statusCode, err)
func HandleInternalError(response *restful.Response, req *restful.Request, err error) {
response.WriteError(http.StatusInternalServerError, err)
}
func HandleBadRequest(response *restful.Response, err error) {
// HandleBadRequest writes http.StatusBadRequest and log error
func HandleBadRequest(response *restful.Response, req *restful.Request, err error) {
response.WriteError(http.StatusBadRequest, err)
}
func HandleNotFound(response *restful.Response, err error) {
func HandleNotFound(response *restful.Response, req *restful.Request, err error) {
response.WriteError(http.StatusNotFound, err)
}
func HandleForbidden(response *restful.Response, err error) {
func HandleForbidden(response *restful.Response, req *restful.Request, err error) {
response.WriteError(http.StatusForbidden, err)
}

View File

@@ -9,11 +9,13 @@ import (
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/request/union"
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/apiserver/authentication"
"kubesphere.io/kubesphere/pkg/apiserver/authentication/authenticators/jwttoken"
authenticationrequest "kubesphere.io/kubesphere/pkg/apiserver/authentication/request"
"kubesphere.io/kubesphere/pkg/apiserver/dispatch"
"kubesphere.io/kubesphere/pkg/apiserver/filters"
"kubesphere.io/kubesphere/pkg/apiserver/request"
@@ -179,7 +181,8 @@ func (s *APIServer) buildHandlerChain() {
handler = filters.WithMultipleClusterDispatcher(handler, dispatch.DefaultClusterDispatch)
handler = filters.WithAuthorization(handler, authorizerfactory.NewAlwaysAllowAuthorizer())
handler = filters.WithAuthentication(handler, bearertoken.New(authentication.NewTokenAuthenticator(s.CacheClient)), failed)
authn := union.New(&authenticationrequest.AnonymousAuthenticator{}, bearertoken.New(jwttoken.NewTokenAuthenticator(s.CacheClient, s.AuthenticateOptions.JwtSecret)))
handler = filters.WithAuthentication(handler, authn, failed)
handler = filters.WithRequestInfo(handler, requestInfoResolver)
s.Server.Handler = handler

View File

@@ -0,0 +1,57 @@
package jwttoken
import (
"context"
"fmt"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"kubesphere.io/kubesphere/pkg/api/iam/token"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
)
var errTokenExpired = errors.New("expired token")
// TokenAuthenticator implements kubernetes token authenticate interface with our custom logic.
// TokenAuthenticator will retrieve user info from cache by given token. If empty or invalid token
// was given, authenticator will still give passed response at the condition user will be user.Anonymous
// and group from user.AllUnauthenticated. This helps requests be passed along the handler chain,
// because some resources are public accessible.
type tokenAuthenticator struct {
cacheClient cache.Interface
jwtTokenIssuer token.Issuer
}
func NewTokenAuthenticator(cacheClient cache.Interface, jwtSecret string) authenticator.Token {
return &tokenAuthenticator{
cacheClient: cacheClient,
jwtTokenIssuer: token.NewJwtTokenIssuer(token.DefaultIssuerName, []byte(jwtSecret)),
}
}
func (t *tokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
providedUser, err := t.jwtTokenIssuer.Verify(token)
if err != nil {
return nil, false, err
}
_, err = t.cacheClient.Get(tokenKeyForUsername(providedUser.Name(), token))
if err != nil {
return nil, false, errTokenExpired
}
// Should we need to refresh token?
return &authenticator.Response{
User: &user.DefaultInfo{
Name: providedUser.Name(),
UID: providedUser.UID(),
Groups: []string{user.AllAuthenticated},
},
}, true, nil
}
func tokenKeyForUsername(username, token string) string {
return fmt.Sprintf("kubesphere:users:%s:token:%s", username, token)
}

View File

@@ -0,0 +1,24 @@
package request
import (
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"net/http"
"strings"
)
type AnonymousAuthenticator struct{}
func (a *AnonymousAuthenticator) AuthenticateRequest(req *http.Request) (*authenticator.Response, bool, error) {
auth := strings.TrimSpace(req.Header.Get("Authorization"))
if auth == "" {
return &authenticator.Response{
User: &user.DefaultInfo{
Name: user.Anonymous,
UID: "",
Groups: []string{user.AllUnauthenticated},
},
}, true, nil
}
return nil, false, nil
}

View File

@@ -0,0 +1 @@
package token

View File

@@ -1,36 +0,0 @@
package authentication
import (
"context"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/user"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
)
// TokenAuthenticator implements kubernetes token authenticate interface with our custom logic.
// TokenAuthenticator will retrieve user info from cache by given token. If empty or invalid token
// was given, authenticator will still give passed response at the condition user will be user.Anonymous
// and group from user.AllUnauthenticated. This helps requests be passed along the handler chain,
// because some resources are public accessible.
type tokenAuthenticator struct {
cacheClient cache.Interface
}
func NewTokenAuthenticator(cacheClient cache.Interface) authenticator.Token {
return &tokenAuthenticator{
cacheClient: cacheClient,
}
}
func (t *tokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
//if len(token) == 0 {
return &authenticator.Response{
User: &user.DefaultInfo{
Name: user.Anonymous,
UID: "",
Groups: []string{user.AllUnauthenticated},
Extra: nil,
},
}, true, nil
//}
}

View File

@@ -33,7 +33,7 @@ func (h ProjectPipelineHandler) GetDevOpsProjectMembersHandler(request *restful.
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
orderBy := request.QueryParameter(params.OrderByParam)
@@ -45,7 +45,7 @@ func (h ProjectPipelineHandler) GetDevOpsProjectMembersHandler(request *restful.
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -62,14 +62,14 @@ func (h ProjectPipelineHandler) GetDevOpsProjectMemberHandler(request *restful.R
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
project, err := h.projectMemberOperator.GetProjectMember(projectId, member)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -85,26 +85,26 @@ func (h ProjectPipelineHandler) AddDevOpsProjectMemberHandler(request *restful.R
err := request.ReadEntity(&member)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
if govalidator.IsNull(member.Username) {
err := fmt.Errorf("error need username")
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
if !reflectutils.In(member.Role, devops.AllRoleSlice) {
err := fmt.Errorf("err role [%s] not in [%s]", member.Role,
devops.AllRoleSlice)
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
@@ -113,7 +113,7 @@ func (h ProjectPipelineHandler) AddDevOpsProjectMemberHandler(request *restful.R
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -129,41 +129,41 @@ func (h ProjectPipelineHandler) UpdateDevOpsProjectMemberHandler(request *restfu
err := request.ReadEntity(&member)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
member.Username = request.PathParameter("member")
if govalidator.IsNull(member.Username) {
err := fmt.Errorf("error need username")
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
if username == member.Username {
err := fmt.Errorf("you can not change your role")
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
if !reflectutils.In(member.Role, devops.AllRoleSlice) {
err := fmt.Errorf("err role [%s] not in [%s]", member.Role,
devops.AllRoleSlice)
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
project, err := h.projectMemberOperator.UpdateProjectMember(projectId, member)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -180,13 +180,13 @@ func (h ProjectPipelineHandler) DeleteDevOpsProjectMemberHandler(request *restfu
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
username, err = h.projectMemberOperator.DeleteProjectMember(projectId, member)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(struct {

View File

@@ -15,13 +15,13 @@ func (h PipelineSonarHandler) GetPipelineSonarStatusHandler(request *restful.Req
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
sonarStatus, err := h.pipelineSonarGetter.GetPipelineSonar(projectId, pipelineId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(sonarStatus)
@@ -35,13 +35,13 @@ func (h PipelineSonarHandler) GetMultiBranchesPipelineSonarStatusHandler(request
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
sonarStatus, err := h.pipelineSonarGetter.GetMultiBranchPipelineSonar(projectId, pipelineId, branchId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(sonarStatus)

View File

@@ -30,14 +30,14 @@ func (h ProjectPipelineHandler) GetDevOpsProjectHandler(request *restful.Request
err := h.projectOperator.CheckProjectUserInRole(username, projectId, devops.AllRoleSlice)
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
project, err := h.projectOperator.GetProject(projectId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -53,21 +53,21 @@ func (h ProjectPipelineHandler) UpdateProjectHandler(request *restful.Request, r
err := request.ReadEntity(&project)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, request, err)
return
}
project.ProjectId = projectId
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
project, err = h.projectOperator.UpdateProject(project)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}

View File

@@ -29,14 +29,14 @@ func (h ProjectPipelineHandler) CreateDevOpsProjectCredentialHandler(request *re
err := request.ReadEntity(&credential)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
credentialId, err := h.projectCredentialOperator.CreateProjectCredential(projectId, username, credential)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -54,14 +54,14 @@ func (h ProjectPipelineHandler) UpdateDevOpsProjectCredentialHandler(request *re
err := request.ReadEntity(&credential)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
credentialId, err = h.projectCredentialOperator.UpdateProjectCredential(projectId, credentialId, credential)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -80,7 +80,7 @@ func (h ProjectPipelineHandler) DeleteDevOpsProjectCredentialHandler(request *re
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -99,7 +99,7 @@ func (h ProjectPipelineHandler) GetDevOpsProjectCredentialHandler(request *restf
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -113,7 +113,7 @@ func (h ProjectPipelineHandler) GetDevOpsProjectCredentialsHandler(request *rest
jenkinsCredentials, err := h.projectCredentialOperator.GetProjectCredentials(projectId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(jenkinsCredentials)

View File

@@ -29,20 +29,20 @@ func (h ProjectPipelineHandler) CreateDevOpsProjectPipelineHandler(request *rest
err := request.ReadEntity(&pipeline)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
pipelineName, err := h.projectPipelineOperator.CreateProjectPipeline(projectId, pipeline)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -60,14 +60,14 @@ func (h ProjectPipelineHandler) DeleteDevOpsProjectPipelineHandler(request *rest
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, request, err)
return
}
pipelineName, err := h.projectPipelineOperator.DeleteProjectPipeline(projectId, pipelineId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -86,20 +86,20 @@ func (h ProjectPipelineHandler) UpdateDevOpsProjectPipelineHandler(request *rest
err := request.ReadEntity(&pipeline)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
err = h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
pipelineName, err := h.projectPipelineOperator.UpdateProjectPipeline(projectId, pipelineId, pipeline)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -118,14 +118,14 @@ func (h ProjectPipelineHandler) GetDevOpsProjectPipelineConfigHandler(request *r
err := h.projectOperator.CheckProjectUserInRole(username, projectId, []string{devops.ProjectOwner, devops.ProjectMaintainer})
if err != nil {
klog.Errorf("%+v", err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
pipeline, err := h.projectPipelineOperator.GetProjectPipelineConfig(projectId, pipelineId)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}

View File

@@ -22,38 +22,38 @@ func (h S2iBinaryHandler) UploadS2iBinaryHandler(req *restful.Request, resp *res
err := req.Request.ParseMultipartForm(bytefmt.MEGABYTE * 20)
if err != nil {
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
if len(req.Request.MultipartForm.File) == 0 {
err := restful.NewError(http.StatusBadRequest, "could not get file from form")
klog.Errorf("%+v", err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
if len(req.Request.MultipartForm.File["s2ibinary"]) == 0 {
err := restful.NewError(http.StatusBadRequest, "could not get file from form")
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
if len(req.Request.MultipartForm.File["s2ibinary"]) > 1 {
err := restful.NewError(http.StatusBadRequest, "s2ibinary should only have one file")
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
defer req.Request.MultipartForm.RemoveAll()
file, err := req.Request.MultipartForm.File["s2ibinary"][0].Open()
if err != nil {
klog.Error(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
filemd5, err := hashutil.GetMD5(file)
if err != nil {
klog.Error(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
md5, ok := req.Request.MultipartForm.Value["md5"]
@@ -61,7 +61,7 @@ func (h S2iBinaryHandler) UploadS2iBinaryHandler(req *restful.Request, resp *res
if md5[0] != filemd5 {
err := restful.NewError(http.StatusBadRequest, fmt.Sprintf("md5 not match, origin: %+v, calculate: %+v", md5[0], filemd5))
klog.Error(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
}
@@ -69,7 +69,7 @@ func (h S2iBinaryHandler) UploadS2iBinaryHandler(req *restful.Request, resp *res
s2ibin, err := h.s2iUploader.UploadS2iBinary(ns, name, filemd5, req.Request.MultipartForm.File["s2ibinary"][0])
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(s2ibin)
@@ -83,7 +83,7 @@ func (h S2iBinaryHandler) DownloadS2iBinaryHandler(req *restful.Request, resp *r
url, err := h.s2iUploader.DownloadS2iBinary(ns, name, fileName)
if err != nil {
klog.Errorf("%+v", err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
http.Redirect(resp.ResponseWriter, req.Request, url, http.StatusFound)

View File

@@ -3,7 +3,6 @@ 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"
@@ -21,7 +20,6 @@ import (
"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"
iamapi "kubesphere.io/kubesphere/pkg/api/iam"
@@ -51,49 +49,22 @@ func (h *iamHandler) TokenReviewHandler(req *restful.Request, resp *restful.Resp
err := req.ReadEntity(&tokenReview)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
klog.Error(err)
api.HandleBadRequest(resp, req, err)
return
}
if err = tokenReview.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
klog.Error(err)
api.HandleBadRequest(resp, req, err)
return
}
token, err := jwtutil.ValidateToken(tokenReview.Spec.Token)
if err != nil {
failed := iamv1alpha2.TokenReview{APIVersion: tokenReview.APIVersion,
Kind: kindTokenReview,
Status: &iamv1alpha2.Status{
Authenticated: false,
},
}
resp.WriteEntity(failed)
return
}
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("invalid token"))
return
}
user, err := h.imOperator.DescribeUser(username)
user, err := h.imOperator.VerifyToken(tokenReview.Spec.Token)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, req, err)
return
}
@@ -143,13 +114,13 @@ func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
err := req.ReadEntity(&createRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
if err := createRequest.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -162,7 +133,7 @@ func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -170,7 +141,7 @@ func (h *iamHandler) CreateUser(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -184,7 +155,7 @@ func (h *iamHandler) DeleteUser(req *restful.Request, resp *restful.Response) {
if operator == username {
err := errors.New("cannot delete yourself")
klog.V(4).Infoln(err)
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
return
}
@@ -192,7 +163,7 @@ func (h *iamHandler) DeleteUser(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -201,7 +172,7 @@ func (h *iamHandler) DeleteUser(req *restful.Request, resp *restful.Response) {
// TODO release user resources
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -218,20 +189,20 @@ func (h *iamHandler) ModifyUser(request *restful.Request, response *restful.Resp
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, 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)
api.HandleBadRequest(response, nil, err)
return
}
if err = modifyUserRequest.Validate(); err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
@@ -244,7 +215,7 @@ func (h *iamHandler) ModifyUser(request *restful.Request, response *restful.Resp
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -261,11 +232,11 @@ func (h *iamHandler) DescribeUser(req *restful.Request, resp *restful.Response)
if err != nil {
if err == iam.UserNotExists {
klog.V(4).Infoln(err)
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -274,7 +245,7 @@ func (h *iamHandler) DescribeUser(req *restful.Request, resp *restful.Response)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -295,7 +266,7 @@ func (h *iamHandler) ListUsers(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -303,7 +274,7 @@ func (h *iamHandler) ListUsers(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -318,7 +289,7 @@ func (h *iamHandler) ListUserRoles(req *restful.Request, resp *restful.Response)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -334,7 +305,7 @@ func (h *iamHandler) ListRoles(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -342,7 +313,7 @@ func (h *iamHandler) ListRoles(req *restful.Request, resp *restful.Response) {
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -357,7 +328,7 @@ func (h *iamHandler) ListClusterRoles(req *restful.Request, resp *restful.Respon
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -365,7 +336,7 @@ func (h *iamHandler) ListClusterRoles(req *restful.Request, resp *restful.Respon
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -381,7 +352,7 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
result := make([]*iamapi.User, 0)
@@ -395,7 +366,7 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
result = append(result, user)
@@ -415,7 +386,7 @@ func (h *iamHandler) ListNamespaceUsers(req *restful.Request, resp *restful.Resp
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -430,7 +401,7 @@ func (h *iamHandler) ListNamespaceUsers(req *restful.Request, resp *restful.Resp
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
result = append(result, user)
@@ -447,7 +418,7 @@ func (h *iamHandler) ListClusterRoleUsers(req *restful.Request, resp *restful.Re
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -462,7 +433,7 @@ func (h *iamHandler) ListClusterRoleUsers(req *restful.Request, resp *restful.Re
}
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
result = append(result, user)
@@ -488,7 +459,7 @@ func (h *iamHandler) ListClusterRoleRules(req *restful.Request, resp *restful.Re
rules, err := h.amOperator.GetClusterRoleSimpleRules(clusterRole)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteEntity(rules)
@@ -502,7 +473,7 @@ func (h *iamHandler) ListRoleRules(req *restful.Request, resp *restful.Response)
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}

View File

@@ -47,7 +47,7 @@ func (h handler) get(req *restful.Request, lvl int, resp *restful.Response) {
noHit, sf, err := h.newSearchFilter(req, lvl)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
}
if noHit {
handleNoHit(typ, resp)
@@ -58,14 +58,14 @@ func (h handler) get(req *restful.Request, lvl int, resp *restful.Response) {
case TypeStat:
res, err := h.lo.GetCurrentStats(sf)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
resp.WriteAsJson(res)
case TypeHist:
interval := req.QueryParameter("interval")
res, err := h.lo.CountLogsByInterval(sf, interval)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
resp.WriteAsJson(res)
case TypeExport:
@@ -73,7 +73,7 @@ func (h handler) get(req *restful.Request, lvl int, resp *restful.Response) {
resp.Header().Set("Content-Disposition", "attachment")
err := h.lo.ExportLogs(sf, resp.ResponseWriter)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
default:
from, _ := strconv.ParseInt(req.QueryParameter("from"), 10, 64)
@@ -87,7 +87,7 @@ func (h handler) get(req *restful.Request, lvl int, resp *restful.Response) {
}
res, err := h.lo.SearchLogs(sf, from, size, order)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
resp.WriteAsJson(res)
}

View File

@@ -39,7 +39,7 @@ func newHandler(k k8s.Client, m monitoring.Interface) *handler {
func (h handler) handleClusterMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelCluster)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -48,7 +48,7 @@ func (h handler) handleClusterMetricsQuery(req *restful.Request, resp *restful.R
func (h handler) handleNodeMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelNode)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -57,7 +57,7 @@ func (h handler) handleNodeMetricsQuery(req *restful.Request, resp *restful.Resp
func (h handler) handleWorkspaceMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelWorkspace)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -66,7 +66,7 @@ func (h handler) handleWorkspaceMetricsQuery(req *restful.Request, resp *restful
func (h handler) handleNamespaceMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelNamespace)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -75,7 +75,7 @@ func (h handler) handleNamespaceMetricsQuery(req *restful.Request, resp *restful
func (h handler) handleWorkloadMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelWorkload)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -84,7 +84,7 @@ func (h handler) handleWorkloadMetricsQuery(req *restful.Request, resp *restful.
func (h handler) handlePodMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelPod)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -93,7 +93,7 @@ func (h handler) handlePodMetricsQuery(req *restful.Request, resp *restful.Respo
func (h handler) handleContainerMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelContainer)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -102,7 +102,7 @@ func (h handler) handleContainerMetricsQuery(req *restful.Request, resp *restful
func (h handler) handlePVCMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelPVC)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -111,7 +111,7 @@ func (h handler) handlePVCMetricsQuery(req *restful.Request, resp *restful.Respo
func (h handler) handleComponentMetricsQuery(req *restful.Request, resp *restful.Response) {
p, err := h.parseRequestParams(req, monitoring.LevelComponent)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
h.handleNamedMetricsQuery(resp, p)
@@ -124,13 +124,13 @@ func (h handler) handleNamedMetricsQuery(resp *restful.Response, p params) {
if p.isRangeQuery() {
res, err = h.mo.GetNamedMetricsOverTime(p.start, p.end, p.step, p.option)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
} else {
res, err = h.mo.GetNamedMetrics(p.time, p.option)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}

View File

@@ -41,7 +41,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
@@ -51,7 +51,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -71,7 +71,7 @@ func (h *openpitrixHandler) ListApplications(request *restful.Request, response
if err != nil {
klog.Errorln(err)
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -94,7 +94,7 @@ func (h *openpitrixHandler) DescribeApplication(req *restful.Request, resp *rest
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -103,7 +103,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)
api.HandleForbidden(resp, nil, err)
return
}
@@ -117,7 +117,7 @@ func (h *openpitrixHandler) CreateApplication(req *restful.Request, resp *restfu
err := req.ReadEntity(&createClusterRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -127,7 +127,7 @@ func (h *openpitrixHandler) CreateApplication(req *restful.Request, resp *restfu
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -141,7 +141,7 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
err := req.ReadEntity(&modifyClusterAttributesRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -157,7 +157,7 @@ func (h *openpitrixHandler) ModifyApplication(req *restful.Request, resp *restfu
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -166,7 +166,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)
api.HandleForbidden(resp, nil, err)
return
}
@@ -196,7 +196,7 @@ func (h *openpitrixHandler) DeleteApplication(req *restful.Request, resp *restfu
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -205,7 +205,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)
api.HandleForbidden(resp, nil, err)
return
}
@@ -228,7 +228,7 @@ func (h *openpitrixHandler) GetAppVersionPackage(req *restful.Request, resp *res
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -240,7 +240,7 @@ func (h *openpitrixHandler) DoAppAction(req *restful.Request, resp *restful.Resp
err := req.ReadEntity(&doActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -262,7 +262,7 @@ func (h *openpitrixHandler) DoAppVersionAction(req *restful.Request, resp *restf
err := req.ReadEntity(&doActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
doActionRequest.Username = req.HeaderParameter(constants.UserNameHeader)
@@ -308,7 +308,7 @@ func (h *openpitrixHandler) ListAppVersionAudits(req *restful.Request, resp *res
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -336,7 +336,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -344,7 +344,7 @@ func (h *openpitrixHandler) ListReviews(req *restful.Request, resp *restful.Resp
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -361,7 +361,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
conditions.Match[openpitrix.AppId] = appId
@@ -370,7 +370,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -380,7 +380,7 @@ func (h *openpitrixHandler) ListAppVersions(req *restful.Request, resp *restful.
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)
api.HandleInternalError(resp, nil, err)
return
}
version.ClusterTotal = &statisticsResult.TotalCount
@@ -400,7 +400,7 @@ func (h *openpitrixHandler) ListApps(req *restful.Request, resp *restful.Respons
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -438,7 +438,7 @@ func (h *openpitrixHandler) ModifyApp(req *restful.Request, resp *restful.Respon
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -474,10 +474,10 @@ func (h *openpitrixHandler) DeleteApp(req *restful.Request, resp *restful.Respon
if err != nil {
if status.Code(err) == codes.NotFound {
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
return
}
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -489,7 +489,7 @@ func (h *openpitrixHandler) CreateApp(req *restful.Request, resp *restful.Respon
err := req.ReadEntity(createAppRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -511,10 +511,10 @@ func (h *openpitrixHandler) CreateApp(req *restful.Request, resp *restful.Respon
if err != nil {
if status.Code(err) == codes.InvalidArgument {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -526,7 +526,7 @@ func (h *openpitrixHandler) CreateAppVersion(req *restful.Request, resp *restful
err := req.ReadEntity(&createAppVersionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
// override app id
@@ -564,7 +564,7 @@ func (h *openpitrixHandler) ModifyAppVersion(req *restful.Request, resp *restful
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -634,7 +634,7 @@ func (h *openpitrixHandler) CreateCategory(req *restful.Request, resp *restful.R
err := req.ReadEntity(createCategoryRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -667,7 +667,7 @@ func (h *openpitrixHandler) ModifyCategory(req *restful.Request, resp *restful.R
err := req.ReadEntity(&modifyCategoryRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -703,7 +703,7 @@ func (h *openpitrixHandler) ListCategories(req *restful.Request, resp *restful.R
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -737,7 +737,7 @@ func (h *openpitrixHandler) CreateRepo(req *restful.Request, resp *restful.Respo
err := req.ReadEntity(createRepoRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
validate, _ := strconv.ParseBool(req.QueryParameter("validate"))
@@ -770,7 +770,7 @@ func (h *openpitrixHandler) DoRepoAction(req *restful.Request, resp *restful.Res
err := req.ReadEntity(repoActionRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -805,7 +805,7 @@ func (h *openpitrixHandler) ModifyRepo(req *restful.Request, resp *restful.Respo
err := req.ReadEntity(&updateRepoRequest)
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -841,7 +841,7 @@ func (h *openpitrixHandler) ListRepos(req *restful.Request, resp *restful.Respon
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -863,7 +863,7 @@ func (h *openpitrixHandler) ListRepoEvents(req *restful.Request, resp *restful.R
if err != nil {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -881,14 +881,14 @@ func (h *openpitrixHandler) ListRepoEvents(req *restful.Request, resp *restful.R
func handleOpenpitrixError(resp *restful.Response, err error) {
if status.Code(err) == codes.NotFound {
klog.V(4).Infoln(err)
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
return
}
if status.Code(err) == codes.InvalidArgument {
klog.V(4).Infoln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}

View File

@@ -73,7 +73,7 @@ func (r *resourceHandler) handleListNamespaceResources(request *restful.Request,
result, err := r.resourcesGetter.ListResources(namespace, resource, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -84,7 +84,7 @@ func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, respon
result, err := r.componentsGetter.GetSystemHealthStatus()
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -96,7 +96,7 @@ func (r *resourceHandler) handleGetComponentStatus(request *restful.Request, res
result, err := r.componentsGetter.GetComponentStatus(component)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -107,7 +107,7 @@ func (r *resourceHandler) handleGetComponents(_ *restful.Request, response *rest
result, err := r.componentsGetter.GetAllComponentsStatus()
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -117,7 +117,7 @@ func (r *resourceHandler) handleGetComponents(_ *restful.Request, response *rest
func (r *resourceHandler) handleGetClusterQuotas(_ *restful.Request, response *restful.Response) {
result, err := r.resourceQuotaGetter.GetClusterQuota()
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -129,7 +129,7 @@ func (r *resourceHandler) handleGetNamespaceQuotas(request *restful.Request, res
quota, err := r.resourceQuotaGetter.GetNamespaceQuota(namespace)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -182,7 +182,7 @@ func (r *resourceHandler) handleGetStatefulSetRevision(request *restful.Request,
result, err := r.revisionGetter.GetStatefulSetRevision(namespace, statefulset, revision)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
response.WriteAsJson(result)
@@ -196,7 +196,7 @@ func (r *resourceHandler) handleGetRouter(request *restful.Request, response *re
if k8serr.IsNotFound(err) {
response.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err))
} else {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
}
return
}
@@ -221,7 +221,7 @@ func (r *resourceHandler) handleCreateRouter(request *restful.Request, response
router, err := r.routerOperator.CreateRouter(namespace, routerType, newRouter.Annotations)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -234,7 +234,7 @@ func (r *resourceHandler) handleDeleteRouter(request *restful.Request, response
router, err := r.routerOperator.DeleteRouter(namespace)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -257,7 +257,7 @@ func (r *resourceHandler) handleUpdateRouter(request *restful.Request, response
router, err := r.routerOperator.UpdateRouter(namespace, routerType, newRouter.Annotations)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -269,13 +269,13 @@ func (r *resourceHandler) handleVerifyGitCredential(request *restful.Request, re
var credential api.GitCredential
err := request.ReadEntity(&credential)
if err != nil {
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
err = r.gitVerifier.VerifyGitCredential(credential.RemoteUrl, credential.SecretRef.Namespace, credential.SecretRef.Name)
if err != nil {
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
@@ -286,13 +286,13 @@ func (r *resourceHandler) handleVerifyRegistryCredential(request *restful.Reques
var credential api.RegistryCredential
err := request.ReadEntity(&credential)
if err != nil {
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
err = r.registryGetter.VerifyRegistryCredential(credential)
if err != nil {
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
@@ -306,7 +306,7 @@ func (r *resourceHandler) handleGetRegistryEntry(request *restful.Request, respo
detail, err := r.registryGetter.GetEntry(namespace, secretName, imageName)
if err != nil {
api.HandleBadRequest(response, err)
api.HandleBadRequest(response, nil, err)
return
}
@@ -335,7 +335,7 @@ func (r *resourceHandler) handleGetNamespacedAbnormalWorkloads(request *restful.
res, err := r.resourcesGetter.ListResources(namespace, workloadType, &params.Conditions{Match: map[string]string{v1alpha2.Status: notReadyStatus}}, "", false, -1, 0)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
}
result.Count[workloadType] = len(res.Items)

View File

@@ -29,7 +29,7 @@ func (h Handler) handleGetNamespacedResource(request *restful.Request, response
result, err := h.namespacedResourceGetter.Get(resource, namespace, name)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -44,7 +44,7 @@ func (h Handler) handleListNamespacedResource(request *restful.Request, response
result, err := h.namespacedResourceGetter.List(resource, namespace, query)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -56,7 +56,7 @@ func (h Handler) handleGetComponentStatus(request *restful.Request, response *re
result, err := h.componentsGetter.GetComponentStatus(component)
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -67,7 +67,7 @@ func (h Handler) handleGetSystemHealthStatus(request *restful.Request, response
result, err := h.componentsGetter.GetSystemHealthStatus()
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -80,7 +80,7 @@ func (h Handler) handleGetComponents(request *restful.Request, response *restful
result, err := h.componentsGetter.GetAllComponentsStatus()
if err != nil {
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}

View File

@@ -87,7 +87,7 @@ func getServiceTracing(request *restful.Request, response *restful.Response) {
if err != nil {
klog.Errorf("query jaeger faile with err %v", err)
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}
@@ -96,7 +96,7 @@ func getServiceTracing(request *restful.Request, response *restful.Response) {
if err != nil {
klog.Errorf("read response error : %v", err)
api.HandleInternalError(response, err)
api.HandleInternalError(response, nil, err)
return
}

View File

@@ -44,7 +44,7 @@ func (h *tenantHandler) ListWorkspaceRules(req *restful.Request, resp *restful.R
if err != nil {
klog.Errorln(err)
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -60,14 +60,14 @@ func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Respo
if err != nil {
klog.Errorln(err)
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
result, err := h.tenant.ListWorkspaces(username, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -82,9 +82,9 @@ func (h *tenantHandler) DescribeWorkspace(req *restful.Request, resp *restful.Re
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
} else {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
return
}
@@ -107,7 +107,7 @@ func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Respo
conditions, err := params.ParseConditions(req)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
@@ -116,7 +116,7 @@ func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Respo
result, err := h.tenant.ListNamespaces(username, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -145,7 +145,7 @@ func (h *tenantHandler) CreateNamespace(req *restful.Request, resp *restful.Resp
var namespace v1.Namespace
err := req.ReadEntity(&namespace)
if err != nil {
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
return
}
@@ -153,9 +153,9 @@ func (h *tenantHandler) CreateNamespace(req *restful.Request, resp *restful.Resp
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleForbidden(resp, err)
api.HandleForbidden(resp, nil, err)
} else {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
return
}
@@ -166,7 +166,7 @@ func (h *tenantHandler) CreateNamespace(req *restful.Request, resp *restful.Resp
if k8serr.IsAlreadyExists(err) {
resp.WriteHeaderAndEntity(http.StatusConflict, err)
} else {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
return
}
@@ -181,9 +181,9 @@ func (h *tenantHandler) DeleteNamespace(req *restful.Request, resp *restful.Resp
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleNotFound(resp, err)
api.HandleNotFound(resp, nil, err)
} else {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
}
return
}
@@ -204,7 +204,7 @@ func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.R
conditions, err := params.ParseConditions(req)
if err != nil {
api.HandleBadRequest(resp, err)
api.HandleBadRequest(resp, nil, err)
return
}
conditions.Match["workspace"] = workspace
@@ -212,7 +212,7 @@ func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.R
result, err := h.tenant.ListDevopsProjects(username, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -224,7 +224,7 @@ func (h *tenantHandler) GetDevOpsProjectsCount(req *restful.Request, resp *restf
result, err := h.tenant.ListDevopsProjects(username, nil, "", false, 1, 0)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteEntity(struct {
@@ -239,14 +239,14 @@ func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.
_, err := h.tenant.DescribeWorkspace("", workspace)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, req, err)
return
}
err = h.tenant.DeleteDevOpsProject(username, projectId)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -264,7 +264,7 @@ func (h *tenantHandler) ListNamespaceRules(req *restful.Request, resp *restful.R
rules, err := h.tenant.GetNamespaceSimpleRules(namespace, username)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}
@@ -279,7 +279,7 @@ func (h *tenantHandler) ListDevopsRules(req *restful.Request, resp *restful.Resp
rules, err := h.tenant.GetUserDevopsSimpleRules(username, devops)
if err != nil {
api.HandleInternalError(resp, err)
api.HandleInternalError(resp, nil, err)
return
}

View File

@@ -19,17 +19,16 @@ package iam
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
"golang.org/x/oauth2"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/api/iam/token"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/utils/jwtutil"
"time"
)
@@ -42,12 +41,14 @@ type IdentityManagementInterface interface {
ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
GetUserRoles(username string) ([]*rbacv1.Role, error)
GetUserRole(namespace string, username string) (*rbacv1.Role, error)
VerifyToken(token string) (*iam.User, error)
}
type imOperator struct {
authenticateOptions *iam.AuthenticationOptions
ldapClient ldap.Interface
cacheClient cache.Interface
issuer token.Issuer
}
var (
@@ -57,7 +58,12 @@ var (
)
func NewIMOperator(ldapClient ldap.Interface, cacheClient cache.Interface, options *iam.AuthenticationOptions) *imOperator {
return &imOperator{ldapClient: ldapClient, cacheClient: cacheClient, authenticateOptions: options}
return &imOperator{
ldapClient: ldapClient,
cacheClient: cacheClient,
authenticateOptions: options,
issuer: token.NewJwtTokenIssuer(token.DefaultIssuerName, []byte(options.JwtSecret)),
}
}
@@ -78,18 +84,6 @@ func (im *imOperator) ModifyUser(user *iam.User) (*iam.User, error) {
return im.ldapClient.Get(user.Username)
}
func authenticationFailedKeyForUsername(username, failedTimestamp string) string {
return fmt.Sprintf("kubesphere:authfailed:%s:%s", username, failedTimestamp)
}
func tokenKeyForUsername(username, token string) string {
return fmt.Sprintf("kubesphere:users:%s:token:%s", username, token)
}
func loginKeyForUsername(username, loginTimestamp, ip string) string {
return fmt.Sprintf("kubesphere:users:%s:login-log:%s:%s", username, loginTimestamp, ip)
}
func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error) {
records, err := im.cacheClient.Keys(authenticationFailedKeyForUsername(username, "*"))
@@ -97,7 +91,7 @@ func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error
return nil, err
}
if len(records) >= im.authenticateOptions.MaxAuthenticateRetries {
if len(records) > im.authenticateOptions.MaxAuthenticateRetries {
return nil, AuthRateLimitExceeded
}
@@ -114,15 +108,12 @@ func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error
return nil, err
}
loginTime := time.Now()
// token without expiration time will auto sliding
claims := jwt.MapClaims{
"iat": loginTime.Unix(),
"username": user.Username,
"email": user.Email,
issuedToken, err := im.issuer.IssueTo(user)
if err != nil {
return nil, err
}
token := jwtutil.MustSigned(claims)
// TODO: I think we should come up with a better strategy to prevent multiple login.
tokenKey := tokenKeyForUsername(user.Username, "*")
if !im.authenticateOptions.MultipleLogin {
// multi login not allowed, remove the previous token
@@ -140,17 +131,17 @@ func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error
}
}
// cache token with expiration time
if err = im.cacheClient.Set(tokenKey, token, im.authenticateOptions.TokenExpiration); err != nil {
// save token with expiration time
if err = im.cacheClient.Set(tokenKey, issuedToken, im.authenticateOptions.TokenExpiration); err != nil {
return nil, err
}
im.loginRecord(user.Username, ip, loginTime)
im.logLogin(user.Username, ip, time.Now())
return &oauth2.Token{AccessToken: token}, nil
return &oauth2.Token{AccessToken: issuedToken}, nil
}
func (im *imOperator) loginRecord(username, ip string, loginTime time.Time) {
func (im *imOperator) logLogin(username, ip string, loginTime time.Time) {
if ip != "" {
_ = im.cacheClient.Set(loginKeyForUsername(username, loginTime.UTC().Format("2006-01-02T15:04:05Z"), ip), "", 30*24*time.Hour)
}
@@ -174,7 +165,6 @@ func (im *imOperator) DescribeUser(username string) (*iam.User, error) {
}
func (im *imOperator) getLastLoginTime(username string) string {
return ""
}
@@ -191,6 +181,20 @@ func (im *imOperator) CreateUser(user *iam.User) (*iam.User, error) {
return user, nil
}
func (im *imOperator) VerifyToken(tokenString string) (*iam.User, error) {
providedUser, err := im.issuer.Verify(tokenString)
if err != nil {
return nil, err
}
user, err := im.ldapClient.Get(providedUser.Name())
if err != nil {
return nil, err
}
return user, nil
}
func (im *imOperator) uidNumberNext() int {
// TODO fix me
return 0
@@ -202,3 +206,15 @@ func (im *imOperator) GetUserRoles(username string) ([]*rbacv1.Role, error) {
func (im *imOperator) GetUserRole(namespace string, username string) (*rbacv1.Role, error) {
panic("implement me")
}
func authenticationFailedKeyForUsername(username, failedTimestamp string) string {
return fmt.Sprintf("kubesphere:authfailed:%s:%s", username, failedTimestamp)
}
func tokenKeyForUsername(username, token string) string {
return fmt.Sprintf("kubesphere:users:%s:token:%s", username, token)
}
func loginKeyForUsername(username, loginTimestamp, ip string) string {
return fmt.Sprintf("kubesphere:users:%s:login-log:%s:%s", username, loginTimestamp, ip)
}

View File

@@ -1,6 +1,9 @@
package ldap
import "kubesphere.io/kubesphere/pkg/api/iam"
import (
"kubesphere.io/kubesphere/pkg/api/iam"
"time"
)
// simpleLdap is a implementation of ldap.Interface, you should never use this in production env!
type simpleLdap struct {
@@ -8,9 +11,22 @@ type simpleLdap struct {
}
func NewSimpleLdap() Interface {
return &simpleLdap{
sl := &simpleLdap{
store: map[string]*iam.User{},
}
// initialize with a admin user
admin := &iam.User{
Username: "admin",
Email: "admin@kubesphere.io",
Lang: "eng",
Description: "administrator",
CreateTime: time.Now(),
Groups: nil,
Password: "P@88w0rd",
}
sl.store[admin.Username] = admin
return sl
}
func (s simpleLdap) Create(user *iam.User) error {

View File

@@ -1,70 +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 jwtutil
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"os"
)
const secretEnv = "JWT_SECRET"
var secretKey []byte
func init() {
if secret := os.Getenv(secretEnv); secret != "" {
Setup(secret)
}
}
func Setup(secret string) {
secretKey = []byte(secret)
}
func MustSigned(claims jwt.MapClaims) string {
uToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
token, err := uToken.SignedString(secretKey)
if err != nil {
panic(err)
}
return token
}
func provideKey(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); ok {
return secretKey, nil
} else {
return nil, fmt.Errorf("expect token signed with HMAC but got %v", token.Header["alg"])
}
}
func ValidateToken(uToken string) (*jwt.Token, error) {
if len(uToken) == 0 {
return nil, fmt.Errorf("token length is zero")
}
token, err := jwt.Parse(uToken, provideKey)
if err != nil {
return nil, err
}
return token, nil
}