mirror of https://github.com/minio/minio.git
				
				
				
			
		
			
				
	
	
		
			238 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Go
		
	
	
	
| /*
 | |
|  * Minio Cloud Storage, (C) 2017 Minio, Inc.
 | |
|  *
 | |
|  * 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 cmd
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net/url"
 | |
| 	"os"
 | |
| 	"os/signal"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| 	"syscall"
 | |
| 
 | |
| 	"github.com/gorilla/mux"
 | |
| 	"github.com/minio/cli"
 | |
| 	miniohttp "github.com/minio/minio/pkg/http"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	gatewayCmd = cli.Command{
 | |
| 		Name:            "gateway",
 | |
| 		Usage:           "Start object storage gateway.",
 | |
| 		Flags:           append(serverFlags, globalFlags...),
 | |
| 		HideHelpCommand: true,
 | |
| 	}
 | |
| )
 | |
| 
 | |
| // Gateway represents a gateway backend.
 | |
| type Gateway interface {
 | |
| 	// Name returns the unique name of the gateway.
 | |
| 	Name() string
 | |
| 	// NewGatewayLayer returns a new gateway layer.
 | |
| 	NewGatewayLayer() (GatewayLayer, error)
 | |
| }
 | |
| 
 | |
| // RegisterGatewayCommand registers a new command for gateway.
 | |
| func RegisterGatewayCommand(cmd cli.Command) error {
 | |
| 	// We should not have multiple subcommands with same name.
 | |
| 	for _, c := range gatewayCmd.Subcommands {
 | |
| 		if c.Name == cmd.Name {
 | |
| 			return fmt.Errorf("duplicate gateway: %s", cmd.Name)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	gatewayCmd.Subcommands = append(gatewayCmd.Subcommands, cmd)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // MustRegisterGatewayCommand is like RegisterGatewayCommand but panics instead of returning error.
 | |
| func MustRegisterGatewayCommand(cmd cli.Command) {
 | |
| 	if err := RegisterGatewayCommand(cmd); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Return endpoint.
 | |
| func parseGatewayEndpoint(arg string) (endPoint string, secure bool, err error) {
 | |
| 	schemeSpecified := len(strings.Split(arg, "://")) > 1
 | |
| 	if !schemeSpecified {
 | |
| 		// Default connection will be "secure".
 | |
| 		arg = "https://" + arg
 | |
| 	}
 | |
| 
 | |
| 	u, err := url.Parse(arg)
 | |
| 	if err != nil {
 | |
| 		return "", false, err
 | |
| 	}
 | |
| 
 | |
| 	switch u.Scheme {
 | |
| 	case "http":
 | |
| 		return u.Host, false, nil
 | |
| 	case "https":
 | |
| 		return u.Host, true, nil
 | |
| 	default:
 | |
| 		return "", false, fmt.Errorf("Unrecognized scheme %s", u.Scheme)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Validate gateway arguments.
 | |
| func validateGatewayArguments(serverAddr, endpointAddr string) error {
 | |
| 	if err := CheckLocalServerAddr(serverAddr); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	if runtime.GOOS == "darwin" {
 | |
| 		_, port := mustSplitHostPort(serverAddr)
 | |
| 		// On macOS, if a process already listens on LOCALIPADDR:PORT, net.Listen() falls back
 | |
| 		// to IPv6 address i.e minio will start listening on IPv6 address whereas another
 | |
| 		// (non-)minio process is listening on IPv4 of given port.
 | |
| 		// To avoid this error situation we check for port availability only for macOS.
 | |
| 		if err := checkPortAvailability(port); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if endpointAddr != "" {
 | |
| 		// Reject the endpoint if it points to the gateway handler itself.
 | |
| 		sameTarget, err := sameLocalAddrs(endpointAddr, serverAddr)
 | |
| 		if err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 		if sameTarget {
 | |
| 			return errors.New("endpoint points to the local gateway")
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Handler for 'minio gateway <name>'.
 | |
| func startGateway(ctx *cli.Context, gw Gateway) {
 | |
| 	// Get quiet flag from command line argument.
 | |
| 	quietFlag := ctx.Bool("quiet") || ctx.GlobalBool("quiet")
 | |
| 	if quietFlag {
 | |
| 		log.EnableQuiet()
 | |
| 	}
 | |
| 
 | |
| 	// Fetch address option
 | |
| 	gatewayAddr := ctx.GlobalString("address")
 | |
| 	if gatewayAddr == ":"+globalMinioPort {
 | |
| 		gatewayAddr = ctx.String("address")
 | |
| 	}
 | |
| 
 | |
| 	// Handle common command args.
 | |
| 	handleCommonCmdArgs(ctx)
 | |
| 
 | |
| 	// Handle common env vars.
 | |
| 	handleCommonEnvVars()
 | |
| 
 | |
| 	// Validate if we have access, secret set through environment.
 | |
| 	gatewayName := gw.Name()
 | |
| 	if !globalIsEnvCreds {
 | |
| 		fatalIf(fmt.Errorf("Access and Secret keys should be set through ENVs for backend [%s]", gatewayName), "")
 | |
| 	}
 | |
| 
 | |
| 	// Create certs path.
 | |
| 	fatalIf(createConfigDir(), "Unable to create configuration directories.")
 | |
| 
 | |
| 	// Initialize gateway config.
 | |
| 	initConfig()
 | |
| 
 | |
| 	// Enable loggers as per configuration file.
 | |
| 	enableLoggers()
 | |
| 
 | |
| 	// Init the error tracing module.
 | |
| 	initError()
 | |
| 
 | |
| 	// Check and load SSL certificates.
 | |
| 	var err error
 | |
| 	globalPublicCerts, globalRootCAs, globalTLSCertificate, globalIsSSL, err = getSSLConfig()
 | |
| 	fatalIf(err, "Invalid SSL certificate file")
 | |
| 
 | |
| 	initNSLock(false) // Enable local namespace lock.
 | |
| 
 | |
| 	if ctx.Args().First() == "help" {
 | |
| 		cli.ShowCommandHelpAndExit(ctx, gatewayName, 1)
 | |
| 	}
 | |
| 
 | |
| 	newObject, err := gw.NewGatewayLayer()
 | |
| 	fatalIf(err, "Unable to initialize gateway layer")
 | |
| 
 | |
| 	router := mux.NewRouter().SkipClean(true)
 | |
| 
 | |
| 	// Register web router when its enabled.
 | |
| 	if globalIsBrowserEnabled {
 | |
| 		fatalIf(registerWebRouter(router), "Unable to configure web browser")
 | |
| 	}
 | |
| 	registerGatewayAPIRouter(router, newObject)
 | |
| 
 | |
| 	var handlerFns = []HandlerFunc{
 | |
| 		// Validate all the incoming paths.
 | |
| 		setPathValidityHandler,
 | |
| 		// Limits all requests size to a maximum fixed limit
 | |
| 		setRequestSizeLimitHandler,
 | |
| 		// Adds 'crossdomain.xml' policy handler to serve legacy flash clients.
 | |
| 		setCrossDomainPolicy,
 | |
| 		// Validates all incoming requests to have a valid date header.
 | |
| 		// Redirect some pre-defined browser request paths to a static location prefix.
 | |
| 		setBrowserRedirectHandler,
 | |
| 		// Validates if incoming request is for restricted buckets.
 | |
| 		setReservedBucketHandler,
 | |
| 		// Adds cache control for all browser requests.
 | |
| 		setBrowserCacheControlHandler,
 | |
| 		// Validates all incoming requests to have a valid date header.
 | |
| 		setTimeValidityHandler,
 | |
| 		// CORS setting for all browser API requests.
 | |
| 		setCorsHandler,
 | |
| 		// Validates all incoming URL resources, for invalid/unsupported
 | |
| 		// resources client receives a HTTP error.
 | |
| 		setIgnoreResourcesHandler,
 | |
| 		// Auth handler verifies incoming authorization headers and
 | |
| 		// routes them accordingly. Client receives a HTTP error for
 | |
| 		// invalid/unsupported signatures.
 | |
| 		setAuthHandler,
 | |
| 		// Add new handlers here.
 | |
| 	}
 | |
| 
 | |
| 	globalHTTPServer = miniohttp.NewServer([]string{gatewayAddr}, registerHandlers(router, handlerFns...), globalTLSCertificate)
 | |
| 
 | |
| 	// Start server, automatically configures TLS if certs are available.
 | |
| 	go func() {
 | |
| 		globalHTTPServerErrorCh <- globalHTTPServer.Start()
 | |
| 	}()
 | |
| 
 | |
| 	signal.Notify(globalOSSignalCh, os.Interrupt, syscall.SIGTERM)
 | |
| 
 | |
| 	// Once endpoints are finalized, initialize the new object api.
 | |
| 	globalObjLayerMutex.Lock()
 | |
| 	globalObjectAPI = newObject
 | |
| 	globalObjLayerMutex.Unlock()
 | |
| 
 | |
| 	// Prints the formatted startup message once object layer is initialized.
 | |
| 	if !quietFlag {
 | |
| 		mode := globalMinioModeGatewayPrefix + gatewayName
 | |
| 		// Check update mode.
 | |
| 		checkUpdate(mode)
 | |
| 
 | |
| 		// Print gateway startup message.
 | |
| 		printGatewayStartupMessage(getAPIEndpoints(gatewayAddr), gatewayName)
 | |
| 	}
 | |
| 
 | |
| 	handleSignals()
 | |
| }
 |