Gateway setup interactive (#1904)
This commit is contained in:
parent
d903865346
commit
47c869b33d
@ -32,6 +32,7 @@ import (
|
||||
type GatewayFlags struct {
|
||||
Identity identity.Config
|
||||
GenerateTestCerts bool `default:"false" help:"generate sample TLS certs for Minio GW" setup:"true"`
|
||||
NonInteractive bool `help:"disable interactive mode" default:"false" setup:"true"`
|
||||
|
||||
Server miniogw.ServerConfig
|
||||
Minio miniogw.MinioConfig
|
||||
@ -40,6 +41,8 @@ type GatewayFlags struct {
|
||||
}
|
||||
|
||||
var (
|
||||
// Error is the default gateway setup errs class
|
||||
Error = errs.Class("gateway setup error")
|
||||
// rootCmd represents the base gateway command when called without any subcommands
|
||||
rootCmd = &cobra.Command{
|
||||
Use: "gateway",
|
||||
@ -108,6 +111,7 @@ func cmdSetup(cmd *cobra.Command, args []string) (err error) {
|
||||
}
|
||||
|
||||
overrides := map[string]interface{}{}
|
||||
|
||||
accessKeyFlag := cmd.Flag("minio.access-key")
|
||||
if !accessKeyFlag.Changed {
|
||||
accessKey, err := generateKey()
|
||||
@ -125,6 +129,10 @@ func cmdSetup(cmd *cobra.Command, args []string) (err error) {
|
||||
overrides[secretKeyFlag.Name] = secretKey
|
||||
}
|
||||
|
||||
if !setupCfg.NonInteractive {
|
||||
return setupCfg.interactive(cmd, setupDir, overrides)
|
||||
}
|
||||
|
||||
return process.SaveConfigWithAllDefaults(cmd.Flags(), filepath.Join(setupDir, "config.yaml"), overrides)
|
||||
}
|
||||
|
||||
@ -260,6 +268,48 @@ func (flags GatewayFlags) NewGateway(ctx context.Context, ident *identity.FullId
|
||||
), nil
|
||||
}
|
||||
|
||||
func (flags GatewayFlags) interactive(cmd *cobra.Command, setupDir string, overrides map[string]interface{}) error {
|
||||
satelliteAddress, err := cfgstruct.PromptForSatelitte(cmd)
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
apiKey, err := cfgstruct.PromptForAPIKey()
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
encKey, err := cfgstruct.PromptForEncryptionKey()
|
||||
if err != nil {
|
||||
return Error.Wrap(err)
|
||||
}
|
||||
|
||||
overrides["satellite-addr"] = satelliteAddress
|
||||
overrides["api-key"] = apiKey
|
||||
overrides["enc.key"] = encKey
|
||||
|
||||
err = process.SaveConfigWithAllDefaults(cmd.Flags(), filepath.Join(setupDir, "config.yaml"), overrides)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = fmt.Println(`
|
||||
Your S3 Gateway is configured and ready to use!
|
||||
|
||||
Some things to try next:
|
||||
|
||||
* Run 'gateway --help' to see the operations that can be performed
|
||||
|
||||
* See https://github.com/storj/docs/blob/master/S3-Gateway.md#using-the-aws-s3-commandline-interface for some example commands
|
||||
`)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
process.Exec(rootCmd)
|
||||
}
|
||||
|
@ -305,6 +305,7 @@ func newNetwork(flags *Flags) (*Processes, error) {
|
||||
process.WaitForStart(satellite)
|
||||
process.Arguments = withCommon(process.Directory, Arguments{
|
||||
"setup": {
|
||||
"--non-interactive=true",
|
||||
"--identity-dir", process.Directory,
|
||||
"--satellite-addr", satellite.Address,
|
||||
|
||||
|
156
pkg/cfgstruct/utils.go
Normal file
156
pkg/cfgstruct/utils.go
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information
|
||||
|
||||
package cfgstruct
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zeebo/errs"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
// applyDefaultHostAndPortToAddr applies the default host and/or port if either is missing in the specified address.
|
||||
func applyDefaultHostAndPortToAddr(address, defaultAddress string) (string, error) {
|
||||
defaultHost, defaultPort, err := net.SplitHostPort(defaultAddress)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
addressParts := strings.Split(address, ":")
|
||||
numberOfParts := len(addressParts)
|
||||
|
||||
if numberOfParts > 1 && len(addressParts[0]) > 0 && len(addressParts[1]) > 0 {
|
||||
// address is host:port so skip applying any defaults.
|
||||
return address, nil
|
||||
}
|
||||
|
||||
// We are missing a host:port part. Figure out which part we are missing.
|
||||
indexOfPortSeparator := strings.Index(address, ":")
|
||||
lengthOfFirstPart := len(addressParts[0])
|
||||
|
||||
if indexOfPortSeparator < 0 {
|
||||
if lengthOfFirstPart == 0 {
|
||||
// address is blank.
|
||||
return defaultAddress, nil
|
||||
}
|
||||
// address is host
|
||||
return net.JoinHostPort(addressParts[0], defaultPort), nil
|
||||
}
|
||||
|
||||
if indexOfPortSeparator == 0 {
|
||||
// address is :1234
|
||||
return net.JoinHostPort(defaultHost, addressParts[1]), nil
|
||||
}
|
||||
|
||||
// address is host:
|
||||
return net.JoinHostPort(addressParts[0], defaultPort), nil
|
||||
}
|
||||
|
||||
// PromptForSatelitte handles user input for a satelitte address to be used with wizards
|
||||
func PromptForSatelitte(cmd *cobra.Command) (string, error) {
|
||||
_, err := fmt.Print(`
|
||||
Pick satellite to use:
|
||||
[1] mars.tardigrade.io
|
||||
[2] jupiter.tardigrade.io
|
||||
[3] saturn.tardigrade.io
|
||||
Please enter numeric choice or enter satellite address manually [1]: `)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
satellites := []string{"mars.tardigrade.io", "jupiter.tardigrade.io", "saturn.tardigrade.io"}
|
||||
var satelliteAddress string
|
||||
n, err := fmt.Scanln(&satelliteAddress)
|
||||
if err != nil {
|
||||
if n == 0 {
|
||||
// fmt.Scanln cannot handle empty input
|
||||
satelliteAddress = satellites[0]
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add better validation
|
||||
if satelliteAddress == "" {
|
||||
return "", errs.New("satellite address cannot be empty")
|
||||
} else if len(satelliteAddress) == 1 {
|
||||
switch satelliteAddress {
|
||||
case "1":
|
||||
satelliteAddress = satellites[0]
|
||||
case "2":
|
||||
satelliteAddress = satellites[1]
|
||||
case "3":
|
||||
satelliteAddress = satellites[2]
|
||||
default:
|
||||
return "", errs.New("Satellite address cannot be one character")
|
||||
}
|
||||
}
|
||||
|
||||
return applyDefaultHostAndPortToAddr(satelliteAddress, cmd.Flags().Lookup("satellite-addr").Value.String())
|
||||
}
|
||||
|
||||
// PromptForAPIKey handles user input for an API key to be used with wizards
|
||||
func PromptForAPIKey() (string, error) {
|
||||
_, err := fmt.Print("Enter your API key: ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var apiKey string
|
||||
n, err := fmt.Scanln(&apiKey)
|
||||
if err != nil && n != 0 {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if apiKey == "" {
|
||||
return "", errs.New("API key cannot be empty")
|
||||
}
|
||||
|
||||
return apiKey, nil
|
||||
}
|
||||
|
||||
// PromptForEncryptionKey handles user input for an encryption key to be used with wizards
|
||||
func PromptForEncryptionKey() (string, error) {
|
||||
_, err := fmt.Print("Enter your encryption passphrase: ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
encKey, err := terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = fmt.Println()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = fmt.Print("Enter your encryption passphrase again: ")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
repeatedEncKey, err := terminal.ReadPassword(int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
_, err = fmt.Println()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if !bytes.Equal(encKey, repeatedEncKey) {
|
||||
return "", errs.New("encryption passphrases doesn't match")
|
||||
}
|
||||
|
||||
if len(encKey) == 0 {
|
||||
_, err = fmt.Println("Warning: Encryption passphrase is empty!")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return string(encKey), nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user