mirror of
https://github.com/versity/versitygw.git
synced 2026-08-17 12:46:23 +00:00
Merge pull request #1883 from versity/ben/gateways-config
feat: add cli options to specify webui gateway/admin listing
This commit is contained in:
+121
-5
@@ -21,6 +21,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -97,6 +98,8 @@ var (
|
||||
webuiPorts []string
|
||||
webuiCertFile, webuiKeyFile string
|
||||
webuiNoTLS bool
|
||||
webuiGateways []string
|
||||
webuiAdminGateways []string
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -150,6 +153,8 @@ documentation can be found in the GitHub wiki.`,
|
||||
ports = ctx.StringSlice("port")
|
||||
webuiPorts = ctx.StringSlice("webui")
|
||||
admPorts = ctx.StringSlice("admin-port")
|
||||
webuiGateways = ctx.StringSlice("webui-gateways")
|
||||
webuiAdminGateways = ctx.StringSlice("webui-admin-gateways")
|
||||
return nil
|
||||
},
|
||||
Action: func(ctx *cli.Context) error {
|
||||
@@ -203,6 +208,16 @@ func initFlags() []cli.Flag {
|
||||
EnvVars: []string{"VGW_WEBUI_NO_TLS"},
|
||||
Destination: &webuiNoTLS,
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "webui-gateways",
|
||||
Usage: "override auto-detected S3 gateway URLs for WebUI (e.g. 'http://localhost:7070', 'https://s3.example.com'; can be specified multiple times)",
|
||||
EnvVars: []string{"VGW_WEBUI_GATEWAYS"},
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "webui-admin-gateways",
|
||||
Usage: "override auto-detected admin gateway URLs for WebUI (e.g. 'http://localhost:7080', 'https://admin.example.com'; can be specified multiple times)",
|
||||
EnvVars: []string{"VGW_WEBUI_ADMIN_GATEWAYS"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "access",
|
||||
Usage: "root user access key",
|
||||
@@ -1023,16 +1038,37 @@ func runGateway(ctx context.Context, be backend.Backend) error {
|
||||
}
|
||||
|
||||
var gateways []string
|
||||
for _, p := range ports {
|
||||
urls, err := buildServiceURLs(p, sslEnabled)
|
||||
if len(webuiGateways) > 0 {
|
||||
// Use explicitly provided gateway URLs if specified
|
||||
// Validate explicitly provided URLs
|
||||
validGateways, err := validateGatewayURLs(webuiGateways, "webui gateway")
|
||||
if err != nil {
|
||||
return fmt.Errorf("webui: build gateway URLs: %w", err)
|
||||
return err
|
||||
}
|
||||
gateways = append(gateways, urls...)
|
||||
gateways = validGateways
|
||||
} else {
|
||||
// Auto-detect from configured ports
|
||||
for _, p := range ports {
|
||||
urls, err := buildServiceURLs(p, sslEnabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("webui: build gateway URLs: %w", err)
|
||||
}
|
||||
gateways = append(gateways, urls...)
|
||||
}
|
||||
// Sort so localhost/127.0.0.1 URLs appear last
|
||||
sortGatewayURLs(gateways)
|
||||
}
|
||||
|
||||
adminGateways := gateways
|
||||
if len(admPorts) > 0 {
|
||||
if len(webuiAdminGateways) > 0 {
|
||||
// Validate explicitly provided admin gateway URLs
|
||||
validAdminGateways, err := validateGatewayURLs(webuiAdminGateways, "webui admin gateway")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
adminGateways = validAdminGateways
|
||||
} else if len(admPorts) > 0 {
|
||||
// Auto-detect from configured admin ports
|
||||
adminGateways = nil
|
||||
for _, admPort := range admPorts {
|
||||
urls, err := buildServiceURLs(admPort, admSSLEnabled)
|
||||
@@ -1041,6 +1077,8 @@ func runGateway(ctx context.Context, be backend.Backend) error {
|
||||
}
|
||||
adminGateways = append(adminGateways, urls...)
|
||||
}
|
||||
// Sort so localhost/127.0.0.1 URLs appear last
|
||||
sortGatewayURLs(adminGateways)
|
||||
}
|
||||
|
||||
if quiet {
|
||||
@@ -1462,6 +1500,84 @@ func buildServiceURLs(spec string, ssl bool) ([]string, error) {
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
// isLocalhost checks if a URL contains a localhost address
|
||||
func isLocalhost(url string) bool {
|
||||
return strings.Contains(url, "localhost") ||
|
||||
strings.Contains(url, "127.0.0.1") ||
|
||||
strings.Contains(url, "[::1]")
|
||||
}
|
||||
|
||||
// validateGatewayURLs validates a list of gateway URLs and returns only valid ones.
|
||||
// It prints warnings for invalid URLs and returns an error if the input list is non-empty
|
||||
// but contains no valid URLs after filtering.
|
||||
func validateGatewayURLs(urls []string, urlType string) ([]string, error) {
|
||||
if len(urls) == 0 {
|
||||
return urls, nil
|
||||
}
|
||||
|
||||
var validURLs []string
|
||||
for _, urlStr := range urls {
|
||||
// Skip empty strings
|
||||
if strings.TrimSpace(urlStr) == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
parsedURL, err := url.Parse(urlStr)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: %v\n", urlType, urlStr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the URL has a scheme (http or https)
|
||||
if parsedURL.Scheme == "" {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: missing scheme (must be http:// or https://)\n", urlType, urlStr)
|
||||
continue
|
||||
}
|
||||
|
||||
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: unsupported scheme %q (must be http or https)\n", urlType, urlStr, parsedURL.Scheme)
|
||||
continue
|
||||
}
|
||||
|
||||
// Ensure the URL has a host
|
||||
if parsedURL.Host == "" {
|
||||
fmt.Fprintf(os.Stderr, "WARNING: invalid %s URL %q: missing host\n", urlType, urlStr)
|
||||
continue
|
||||
}
|
||||
|
||||
validURLs = append(validURLs, urlStr)
|
||||
}
|
||||
|
||||
if len(validURLs) == 0 {
|
||||
return nil, fmt.Errorf("%s URLs specified but none are valid", urlType)
|
||||
}
|
||||
|
||||
return validURLs, nil
|
||||
}
|
||||
|
||||
// sortGatewayURLs sorts a list of URLs so that localhost and 127.0.0.1 URLs appear last
|
||||
func sortGatewayURLs(urls []string) {
|
||||
if len(urls) <= 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// Partition URLs into two groups: non-localhost and localhost
|
||||
var nonLocal []string
|
||||
var local []string
|
||||
|
||||
for _, url := range urls {
|
||||
if isLocalhost(url) {
|
||||
local = append(local, url)
|
||||
} else {
|
||||
nonLocal = append(nonLocal, url)
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild the slice with non-localhost first, then localhost
|
||||
copy(urls, nonLocal)
|
||||
copy(urls[len(nonLocal):], local)
|
||||
}
|
||||
|
||||
// validatePortConflicts checks for port conflicts across s3 api, admin, and webui ports.
|
||||
// A bare port spec (e.g., ":7071") binds to all interfaces and will conflict with any other
|
||||
// binding on the same port, whether it's ":7071" or "ip:7071".
|
||||
|
||||
@@ -245,6 +245,24 @@ ROOT_SECRET_ACCESS_KEY=
|
||||
# 'https://webui.example.com') to improve security.
|
||||
#VGW_CORS_ALLOW_ORIGIN=
|
||||
|
||||
# The VGW_WEBUI_GATEWAYS option allows you to override the auto-detected S3
|
||||
# gateway URLs that are provided to the Web GUI. By default, the gateway
|
||||
# auto-detects URLs based on the configured VGW_PORT settings. Use this option
|
||||
# to specify custom URLs when the auto-detected values are incorrect (e.g., when
|
||||
# running behind a reverse proxy or load balancer). Multiple URLs can be
|
||||
# specified as a comma-separated list.
|
||||
# Example: VGW_WEBUI_GATEWAYS=https://s3.example.com,http://192.168.1.100:7070
|
||||
#VGW_WEBUI_GATEWAYS=
|
||||
|
||||
# The VGW_WEBUI_ADMIN_GATEWAYS option allows you to override the auto-detected
|
||||
# admin gateway URLs that are provided to the Web GUI. By default, the gateway
|
||||
# auto-detects URLs based on the configured VGW_ADMIN_PORT settings (or uses the
|
||||
# same URLs as VGW_WEBUI_GATEWAYS if no admin ports are configured). Use this
|
||||
# option to specify custom admin URLs when the auto-detected values are incorrect.
|
||||
# Multiple URLs can be specified as a comma-separated list.
|
||||
# Example: VGW_WEBUI_ADMIN_GATEWAYS=https://admin.example.com,http://192.168.1.100:7080
|
||||
#VGW_WEBUI_ADMIN_GATEWAYS=
|
||||
|
||||
#######################
|
||||
# Debug / Diagnostics #
|
||||
#######################
|
||||
|
||||
Reference in New Issue
Block a user