未验证 提交 eb8a3c0d 编写于 作者: Z zryfish 提交者: GitHub

refactor authentication (#1950)

上级 abf0d66b
......@@ -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)$
......@@ -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 {
......
......@@ -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
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.")
}
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)
}
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"])
}
},
}
}
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)
}
})
}
}
package token
type User interface {
// Name
Name() string
UID() string
}
......@@ -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")
......
......@@ -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)
}
......@@ -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
......
package authentication
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
cacheClient cache.Interface
jwtTokenIssuer token.Issuer
}
func NewTokenAuthenticator(cacheClient cache.Interface) authenticator.Token {
func NewTokenAuthenticator(cacheClient cache.Interface, jwtSecret string) authenticator.Token {
return &tokenAuthenticator{
cacheClient: cacheClient,
cacheClient: cacheClient,
jwtTokenIssuer: token.NewJwtTokenIssuer(token.DefaultIssuerName, []byte(jwtSecret)),
}
}
func (t *tokenAuthenticator) AuthenticateToken(ctx context.Context, token string) (*authenticator.Response, bool, error) {
//if len(token) == 0 {
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: user.Anonymous,
UID: "",
Groups: []string{user.AllUnauthenticated},
Extra: nil,
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)
}
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
}
......@@ -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 {
......
......@@ -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)
......
......@@ -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
}
......
......@@ -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)
......
......@@ -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
}
......
......@@ -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)
......
......@@ -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
}
......
......@@ -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)
}
......
......@@ -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
}
......
......@@ -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)
}
......@@ -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)
......
......@@ -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
}
......
......@@ -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
}
......
......@@ -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
}
......
......@@ -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)
}
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 {
......
/*
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
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册