From da0fd5f05667532d6e36364fb7a41c069025729c Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 9 Jul 2021 14:27:09 -0700 Subject: [PATCH] fix: allow customizing console redirection (#12665) MinIO might be running inside proxies, and console while being on another port might not be reachable on a specific port behind such proxies. For such scenarios customize the redirect URL such that console can be redirected to correct proxy endpoint instead. fixes #12661 --- README.md | 7 +++++++ cmd/common-main.go | 16 ++++++++++++++++ cmd/generic-handlers.go | 9 ++++++--- cmd/globals.go | 5 +++++ internal/config/constants.go | 3 ++- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a76b91c44..bb25124ae 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,13 @@ MinIO Server comes with an embedded web based object browser. Point your web bro > NOTE: MinIO runs console on random port by default if you wish choose a specific port use `--console-address` to pick a specific interface and port. +### Things to consider +MinIO redirects browser access requests to the configured server port (i.e. `127.0.0.1:9000`) to the configured Console port. MinIO uses the hostname or IP address specified in the request when building the redirect URI. The URL and port *must* be accessible by the client for the redirection to work + +For deployments behind a load balancer, proxy, or ingress rule where the MinIO host IP address or port is not public, use the `MINIO_BROWSER_REDIRECT_URI` environment variable to specify the external hostname for the redirect. The LB/Proxy must have rules for directing traffic to the Console port specifically. + +For example, consider a MinIO deployment behind a proxy `https://minio.example.net`, `https://console.minio.example.net` with rules for forwarding traffic on port :9000 and :9001 to MinIO and the MinIO Console respectively on the internal network. Set `MINIO_BROWSER_REDIRECT_URL` to `https://console.minio.example.net` to ensure the browser receives a valid reachable URL. + | Dashboard | Creating a bucket | | ------------- | ------------- | | ![Dashboard](https://github.com/minio/minio/blob/master/docs/screenshots/pic1.png?raw=true) | ![Dashboard](https://github.com/minio/minio/blob/master/docs/screenshots/pic2.png?raw=true) | diff --git a/cmd/common-main.go b/cmd/common-main.go index 45a4e90d9..8c9b537fb 100644 --- a/cmd/common-main.go +++ b/cmd/common-main.go @@ -415,6 +415,22 @@ func handleCommonEnvVars() { if err != nil { logger.Fatal(config.ErrInvalidBrowserValue(err), "Invalid MINIO_BROWSER value in environment variable") } + if globalBrowserEnabled { + if redirectURL := env.Get(config.EnvMinIOBrowserRedirectURL, ""); redirectURL != "" { + u, err := xnet.ParseHTTPURL(redirectURL) + if err != nil { + logger.Fatal(err, "Invalid MINIO_BROWSER_REDIRECT value in environment variable") + } + // Look for if URL has invalid values and return error. + if !((u.Scheme == "http" || u.Scheme == "https") && + (u.Path == "/" || u.Path == "") && u.Opaque == "" && + !u.ForceQuery && u.RawQuery == "" && u.Fragment == "") { + err := fmt.Errorf("URL contains unexpected resources, expected URL to be of http(s)://minio.example.com format: %v", u) + logger.Fatal(err, "Invalid MINIO_BROWSER_REDIRECT value is environment variable") + } + globalBrowserRedirectURL = u + } + } globalFSOSync, err = config.ParseBool(env.Get(config.EnvFSOSync, config.EnableOff)) if err != nil { diff --git a/cmd/generic-handlers.go b/cmd/generic-handlers.go index b7bf21e09..7b7d49fe9 100644 --- a/cmd/generic-handlers.go +++ b/cmd/generic-handlers.go @@ -21,13 +21,13 @@ import ( "context" "net" "net/http" - "net/url" "path" "strings" "sync/atomic" "time" "github.com/minio/minio-go/v7/pkg/set" + xnet "github.com/minio/pkg/net" humanize "github.com/dustin/go-humanize" "github.com/minio/minio/internal/config/dns" @@ -183,7 +183,7 @@ func shouldProxy() bool { // redirectable, this is purely internal function and // serves only limited purpose on redirect-handler for // browser requests. -func getRedirectLocation(r *http.Request) *url.URL { +func getRedirectLocation(r *http.Request) *xnet.URL { resource, err := getResource(r.URL.Path, r.Host, globalDomainNames) if err != nil { return nil @@ -197,11 +197,14 @@ func getRedirectLocation(r *http.Request) *url.URL { } { bucket, _ := path2BucketObject(resource) if path.Clean(bucket) == prefix || resource == slashSeparator { + if globalBrowserRedirectURL != nil { + return globalBrowserRedirectURL + } hostname, _, _ := net.SplitHostPort(r.Host) if hostname == "" { hostname = r.Host } - return &url.URL{ + return &xnet.URL{ Host: net.JoinHostPort(hostname, globalMinioConsolePort), Scheme: func() string { scheme := "http" diff --git a/cmd/globals.go b/cmd/globals.go index 954943c91..5e513be4c 100644 --- a/cmd/globals.go +++ b/cmd/globals.go @@ -45,6 +45,7 @@ import ( "github.com/minio/minio/internal/event" "github.com/minio/minio/internal/pubsub" "github.com/minio/pkg/certs" + xnet "github.com/minio/pkg/net" ) // minio configuration related constants. @@ -137,6 +138,10 @@ var ( // This flag is set to 'true' by default globalBrowserEnabled = true + // Custom browser redirect URL, not set by default + // and it is automatically deduced. + globalBrowserRedirectURL *xnet.URL + // This flag is set to 'true' when MINIO_UPDATE env is set to 'off'. Default is false. globalInplaceUpdateDisabled = false diff --git a/internal/config/constants.go b/internal/config/constants.go index 911d256ee..a22cffb40 100644 --- a/internal/config/constants.go +++ b/internal/config/constants.go @@ -37,7 +37,8 @@ const ( EnvArgs = "MINIO_ARGS" EnvDNSWebhook = "MINIO_DNS_WEBHOOK_ENDPOINT" - EnvRootDiskThresholdSize = "MINIO_ROOTDISK_THRESHOLD_SIZE" + EnvMinIOBrowserRedirectURL = "MINIO_BROWSER_REDIRECT_URL" + EnvRootDiskThresholdSize = "MINIO_ROOTDISK_THRESHOLD_SIZE" EnvUpdate = "MINIO_UPDATE"