diff --git a/go.mod b/go.mod index 8740ca367..ff9e3c4e5 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/minio/mc v0.0.0-20220419155441-cc4ff3a0cc82 github.com/minio/minio-go/v7 v7.0.24 github.com/minio/operator v0.0.0-20220414212219-ba4c097324b2 - github.com/minio/pkg v1.1.21 + github.com/minio/pkg v1.1.23 github.com/minio/selfupdate v0.4.0 github.com/mitchellh/go-homedir v1.1.0 github.com/rs/xid v1.4.0 @@ -41,6 +41,7 @@ require ( k8s.io/api v0.23.5 k8s.io/apimachinery v0.23.5 k8s.io/client-go v0.23.5 + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 ) require ( @@ -104,6 +105,7 @@ require ( github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/montanaflynn/stats v0.6.6 // indirect github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect @@ -153,7 +155,6 @@ require ( gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect k8s.io/klog/v2 v2.40.1 // indirect k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect maze.io/x/duration v0.0.0-20160924141736-faac084b6075 // indirect sigs.k8s.io/controller-runtime v0.11.1 // indirect sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect diff --git a/go.sum b/go.sum index e8ebfc420..c96b9104b 100644 --- a/go.sum +++ b/go.sum @@ -488,8 +488,8 @@ github.com/minio/minio-go/v7 v7.0.24/go.mod h1:x81+AX5gHSfCSqw7jxRKHvxUXMlE5uKX0 github.com/minio/operator v0.0.0-20220414212219-ba4c097324b2 h1:GdjU5qV+Wv0P2Y/TVGRELapzBdph8Vyi6u9VjgvtVIs= github.com/minio/operator v0.0.0-20220414212219-ba4c097324b2/go.mod h1:4Bo6a+XrBFEfCiiEtB14bw8l/nT3hcvZQKrZGZu27mA= github.com/minio/pkg v1.1.20/go.mod h1:Xo7LQshlxGa9shKwJ7NzQbgW4s8T/Wc1cOStR/eUiMY= -github.com/minio/pkg v1.1.21 h1:sqPIwfmlMbufFd3xiEiAdrgyle7c67YIXFf+rFtCeyA= -github.com/minio/pkg v1.1.21/go.mod h1:z9PfmEI804KFkF6eY4LoGe8IDVvTCsYGVuaf58Dr0WI= +github.com/minio/pkg v1.1.23 h1:CJSoPslQCWZW3z3T79+pv9dVBDCQEK3ipiwXcoAtzY0= +github.com/minio/pkg v1.1.23/go.mod h1:z9PfmEI804KFkF6eY4LoGe8IDVvTCsYGVuaf58Dr0WI= github.com/minio/selfupdate v0.4.0 h1:A7t07pN4Ch1tBTIRStW0KhUVyykz+2muCqFsITQeEW8= github.com/minio/selfupdate v0.4.0/go.mod h1:mcDkzMgq8PRcpCRJo/NlPY7U45O5dfYl2Y0Rg7IustY= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= @@ -517,6 +517,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= diff --git a/restapi/client.go b/restapi/client.go index 3d4e0344b..6bfff244b 100644 --- a/restapi/client.go +++ b/restapi/client.go @@ -21,13 +21,13 @@ import ( "errors" "fmt" "io" - "net/url" "path" "strings" "time" "github.com/minio/minio-go/v7/pkg/replication" "github.com/minio/minio-go/v7/pkg/sse" + xnet "github.com/minio/pkg/net" "github.com/minio/console/models" "github.com/minio/console/pkg" @@ -388,20 +388,18 @@ func newMinioClient(claims *models.Principal) (*minio.Client, error) { // computeObjectURLWithoutEncode returns a MinIO url containing the object filename without encoding func computeObjectURLWithoutEncode(bucketName, prefix string) (string, error) { endpoint := getMinIOServer() - u, err := url.Parse(endpoint) + u, err := xnet.ParseHTTPURL(endpoint) if err != nil { return "", fmt.Errorf("the provided endpoint is invalid") } - objectURL := fmt.Sprintf("%s:%s", u.Hostname(), u.Port()) + var p string if strings.TrimSpace(bucketName) != "" { - objectURL = path.Join(objectURL, bucketName) + p = path.Join(p, bucketName) } if strings.TrimSpace(prefix) != "" { - objectURL = pathJoinFinalSlash(objectURL, prefix) + p = pathJoinFinalSlash(p, prefix) } - - objectURL = fmt.Sprintf("%s://%s", u.Scheme, objectURL) - return objectURL, nil + return fmt.Sprintf("%s://%s/%s", u.Scheme, u.Host, p), nil } // newS3BucketClient creates a new mc S3Client to talk to the server based on a bucket diff --git a/restapi/config.go b/restapi/config.go index 2b339cc48..2275e1bf3 100644 --- a/restapi/config.go +++ b/restapi/config.go @@ -19,12 +19,12 @@ package restapi import ( "crypto/x509" "net" - "net/url" "strconv" "strings" xcerts "github.com/minio/pkg/certs" "github.com/minio/pkg/env" + xnet "github.com/minio/pkg/net" ) var ( @@ -59,7 +59,7 @@ func GetMinIORegion() string { } func getMinIOEndpoint() string { - u, err := url.Parse(getMinIOServer()) + u, err := xnet.ParseHTTPURL(getMinIOServer()) if err != nil { panic(err) } @@ -67,7 +67,7 @@ func getMinIOEndpoint() string { } func getMinIOEndpointIsSecure() bool { - u, err := url.Parse(getMinIOServer()) + u, err := xnet.ParseHTTPURL(getMinIOServer()) if err != nil { panic(err) } diff --git a/restapi/configure_console.go b/restapi/configure_console.go index 69271f7b4..2720ba587 100644 --- a/restapi/configure_console.go +++ b/restapi/configure_console.go @@ -43,6 +43,7 @@ import ( portal_ui "github.com/minio/console/portal-ui" "github.com/minio/pkg/env" "github.com/minio/pkg/mimedb" + xnet "github.com/minio/pkg/net" "github.com/go-openapi/errors" "github.com/go-openapi/swag" @@ -212,11 +213,11 @@ func setupGlobalMiddleware(handler http.Handler) http.Handler { next = AuthenticationMiddleware(next) sslHostFn := secure.SSLHostFunc(func(host string) string { - h, _, err := net.SplitHostPort(host) + xhost, err := xnet.ParseHost(host) if err != nil { return host } - return net.JoinHostPort(h, TLSPort) + return net.JoinHostPort(xhost.Name, TLSPort) }) // Secure middleware, this middleware wrap all the previous handlers and add @@ -257,6 +258,7 @@ func RejectS3Middleware(next http.Handler) http.Handler { strings.HasPrefix(r.Header.Get("Authorization"), "AWS4-HMAC-SHA256") || r.URL.Query().Get("AWSAccessKeyId") != "" { w.WriteHeader(http.StatusForbidden) + w.Header().Set("Location", getMinIOServer()) w.Write([]byte(` AccessDenied diff --git a/restapi/user_session.go b/restapi/user_session.go index 783f78ea6..ef6d94424 100644 --- a/restapi/user_session.go +++ b/restapi/user_session.go @@ -20,12 +20,11 @@ import ( "bytes" "context" "encoding/json" - "net/http" - "net/url" "strconv" "time" policies "github.com/minio/console/restapi/policy" + "github.com/minio/madmin-go" jwtgo "github.com/golang-jwt/jwt/v4" "github.com/minio/pkg/bucket/policy/condition" @@ -40,31 +39,6 @@ import ( authApi "github.com/minio/console/restapi/operations/auth" ) -func isErasureMode() bool { - u, err := url.Parse(getMinIOServer()) - if err != nil { - panic(err) - } - u.Path = "/minio/health/cluster" - - req, err := http.NewRequest(http.MethodGet, u.String(), nil) - if err != nil { - panic(err) - } - - clnt := GetConsoleHTTPClient() - resp, err := clnt.Do(req) - if err != nil { - panic(err) - } - - if resp.StatusCode != http.StatusOK { - return false - } - - return resp.Header.Get("x-minio-write-quorum") != "" -} - func registerSessionHandlers(api *operations.ConsoleAPI) { // session check api.AuthSessionCheckHandler = authApi.SessionCheckHandlerFunc(func(params authApi.SessionCheckParams, session *models.Principal) middleware.Responder { @@ -94,6 +68,7 @@ func getClaimsFromToken(sessionToken string) (map[string]interface{}, error) { func getSessionResponse(ctx context.Context, session *models.Principal) (*models.SessionResponse, *models.Error) { ctx, cancel := context.WithCancel(ctx) defer cancel() + // serialize output if session == nil { return nil, ErrorWithContext(ctx, ErrInvalidSession) @@ -116,6 +91,7 @@ func getSessionResponse(ctx context.Context, session *models.Principal) (*models if err != nil { return nil, ErrorWithContext(ctx, err, ErrInvalidSession) } + erasure := accountInfo.Server.Type == madmin.Erasure rawPolicy := policies.ReplacePolicyVariables(tokenClaims, accountInfo) policy, err := minioIAMPolicy.ParseConfig(bytes.NewReader(rawPolicy)) if err != nil { @@ -232,7 +208,7 @@ func getSessionResponse(ctx context.Context, session *models.Principal) (*models Features: getListOfEnabledFeatures(session), Status: models.SessionResponseStatusOk, Operator: false, - DistributedMode: isErasureMode(), + DistributedMode: erasure, Permissions: resourcePermissions, } return sessionResp, nil diff --git a/restapi/user_session_test.go b/restapi/user_session_test.go index f9ba3396c..f980d84c9 100644 --- a/restapi/user_session_test.go +++ b/restapi/user_session_test.go @@ -51,27 +51,6 @@ func Test_getSessionResponse(t *testing.T) { want: nil, wantErr: true, }, - { - name: "malformed minio endpoint URL", - args: args{ - ctx: ctx, - session: &models.Principal{ - STSAccessKeyID: "", - STSSecretAccessKey: "", - STSSessionToken: "", - AccountAccessKey: "", - Hm: false, - }, - }, - want: nil, - wantErr: true, - preFunc: func() { - os.Setenv(ConsoleMinIOServer, "malformed") - }, - postFunc: func() { - os.Unsetenv(ConsoleMinIOServer) - }, - }, { name: "malformed session", args: args{ @@ -89,6 +68,7 @@ func Test_getSessionResponse(t *testing.T) { }, } for _, tt := range tests { + tt := tt t.Run(tt.name, func(t *testing.T) { if tt.preFunc != nil { tt.preFunc()