diff --git a/cmd/admin-user-add.go b/cmd/admin-user-add.go index d3c5e90fc4..1d7d6b09ff 100644 --- a/cmd/admin-user-add.go +++ b/cmd/admin-user-add.go @@ -17,7 +17,9 @@ package cmd import ( + "bufio" "fmt" + "os" "strings" "github.com/fatih/color" @@ -25,6 +27,7 @@ import ( json "github.com/minio/mc/pkg/colorjson" "github.com/minio/mc/pkg/probe" "github.com/minio/minio/pkg/console" + "golang.org/x/crypto/ssh/terminal" ) var adminUserAddCmd = cli.Command{ @@ -53,13 +56,23 @@ EXAMPLES: {{.DisableHistory}} {{.Prompt}} {{.HelpName}} myminio foobar foo12345 {{.EnableHistory}} + 2. Add a new user 'foobar' to MinIO server, prompting for keys. + {{.Prompt}} {{.HelpName}} myminio + Enter Access Key: foobar + Enter Secret Key: foobar12345 + 3. Add a new user 'foobar' to MinIO server using piped keys. + {{.DisableHistory}} + {{.Prompt}} echo -e "foobar\nfoobar12345" | {{.HelpName}} myminio + {{.EnableHistory}} `, } // checkAdminUserAddSyntax - validate all the passed arguments func checkAdminUserAddSyntax(ctx *cli.Context) { - if len(ctx.Args()) != 3 { - cli.ShowCommandHelpAndExit(ctx, "add", 1) // last argument is exit code + argsNr := len(ctx.Args()) + if argsNr > 3 || argsNr < 1 { + fatalIf(errInvalidArgument().Trace(ctx.Args().Tail()...), + "Incorrect number of arguments for user add command.") } } @@ -115,6 +128,43 @@ func (u userMessage) JSON() string { return string(jsonMessageBytes) } +// fetchUserKeys - returns the access and secret key +func fetchUserKeys(args cli.Args) (string, string) { + accessKey := "" + secretKey := "" + console.SetColor(cred, color.New(color.FgYellow, color.Italic)) + isTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) + reader := bufio.NewReader(os.Stdin) + + argCount := len(args) + + if argCount == 1 { + if isTerminal { + fmt.Printf("%s", console.Colorize(cred, "Enter Access Key: ")) + } + value, _, _ := reader.ReadLine() + accessKey = string(value) + } else { + accessKey = args.Get(1) + } + + if argCount == 1 || argCount == 2 { + if isTerminal { + fmt.Printf("%s", console.Colorize(cred, "Enter Secret Key: ")) + bytePassword, _ := terminal.ReadPassword(int(os.Stdin.Fd())) + fmt.Printf("\n") + secretKey = string(bytePassword) + } else { + value, _, _ := reader.ReadLine() + secretKey = string(value) + } + } else { + secretKey = args.Get(2) + } + + return accessKey, secretKey +} + // mainAdminUserAdd is the handle for "mc admin user add" command. func mainAdminUserAdd(ctx *cli.Context) error { checkAdminUserAddSyntax(ctx) @@ -124,17 +174,18 @@ func mainAdminUserAdd(ctx *cli.Context) error { // Get the alias parameter from cli args := ctx.Args() aliasedURL := args.Get(0) + accessKey, secretKey := fetchUserKeys(args) // Create a new MinIO Admin Client client, err := newAdminClient(aliasedURL) fatalIf(err, "Unable to initialize admin connection.") - fatalIf(probe.NewError(client.AddUser(args.Get(1), args.Get(2))).Trace(args...), "Cannot add new user") + fatalIf(probe.NewError(client.AddUser(accessKey, secretKey)).Trace(args...), "Cannot add new user") printMsg(userMessage{ op: "add", - AccessKey: args.Get(1), - SecretKey: args.Get(2), + AccessKey: accessKey, + SecretKey: secretKey, UserStatus: "enabled", }) diff --git a/cmd/config-host-add.go b/cmd/config-host-add.go index 7b482c5ce5..d824e5ba5e 100644 --- a/cmd/config-host-add.go +++ b/cmd/config-host-add.go @@ -17,15 +17,21 @@ package cmd import ( + "bufio" + "fmt" "math/rand" + "os" "time" "github.com/fatih/color" "github.com/minio/cli" "github.com/minio/mc/pkg/probe" "github.com/minio/minio/pkg/console" + "golang.org/x/crypto/ssh/terminal" ) +const cred = "YellowItalics" + var hostAddFlags = []cli.Flag{ cli.StringFlag{ Name: "lookup", @@ -71,24 +77,34 @@ EXAMPLES: {{.Prompt}} {{.HelpName}} mys3 https://s3.amazonaws.com \ BKIKJAA5BMMU2RHO6IBB V8f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 {{.EnableHistory}} + + 4. Add Amazon S3 storage service under "mys3" alias, prompting for keys. + {{.Prompt}} {{.HelpName}} mys3 https://s3.amazonaws.com --api "s3v4" --lookup "dns" + Enter Access Key: BKIKJAA5BMMU2RHO6IBB + Enter Secret Key: V8f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 + + 5. Add Amazon S3 storage service under "mys3" alias using piped keys. + {{.DisableHistory}} + {{.Prompt}} echo -e "BKIKJAA5BMMU2RHO6IBB\nV8f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12" | \ + {{.HelpName}} mys3 https://s3.amazonaws.com --api "s3v4" --lookup "dns" + {{.EnableHistory}} `, } // checkConfigHostAddSyntax - verifies input arguments to 'config host add'. -func checkConfigHostAddSyntax(ctx *cli.Context) { +func checkConfigHostAddSyntax(ctx *cli.Context, accessKey string, secretKey string) { args := ctx.Args() argsNr := len(args) - if argsNr < 4 || argsNr > 5 { + if argsNr > 4 || argsNr < 2 { fatalIf(errInvalidArgument().Trace(ctx.Args().Tail()...), "Incorrect number of arguments for host add command.") } alias := args.Get(0) url := args.Get(1) - accessKey := args.Get(2) - secretKey := args.Get(3) api := ctx.String("api") bucketLookup := ctx.String("lookup") + if !isValidAlias(alias) { fatalIf(errInvalidAlias(alias), "Invalid alias.") } @@ -213,18 +229,54 @@ func buildS3Config(url, accessKey, secretKey, api, lookup string) (*Config, *pro return s3Config, nil } +// fetchHostKeys - returns the user accessKey and secretKey +func fetchHostKeys(args cli.Args) (string, string) { + accessKey := "" + secretKey := "" + console.SetColor(cred, color.New(color.FgYellow, color.Italic)) + isTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) + reader := bufio.NewReader(os.Stdin) + + argsNr := len(args) + + if argsNr == 2 { + if isTerminal { + fmt.Printf("%s", console.Colorize(cred, "Enter Access Key: ")) + } + value, _, _ := reader.ReadLine() + accessKey = string(value) + } else { + accessKey = args.Get(2) + } + + if argsNr == 2 || argsNr == 3 { + if isTerminal { + fmt.Printf("%s", console.Colorize(cred, "Enter Secret Key: ")) + bytePassword, _ := terminal.ReadPassword(int(os.Stdin.Fd())) + fmt.Printf("\n") + secretKey = string(bytePassword) + } else { + value, _, _ := reader.ReadLine() + secretKey = string(value) + } + } else { + secretKey = args.Get(3) + } + + return accessKey, secretKey +} + func mainConfigHostAdd(ctx *cli.Context) error { - checkConfigHostAddSyntax(ctx) console.SetColor("HostMessage", color.New(color.FgGreen)) var ( - args = ctx.Args() - url = trimTrailingSeparator(args.Get(1)) - accessKey = args.Get(2) - secretKey = args.Get(3) - api = ctx.String("api") - lookup = ctx.String("lookup") + args = ctx.Args() + url = trimTrailingSeparator(args.Get(1)) + api = ctx.String("api") + lookup = ctx.String("lookup") ) + accessKey, secretKey := fetchHostKeys(args) + checkConfigHostAddSyntax(ctx, accessKey, secretKey) s3Config, err := buildS3Config(url, accessKey, secretKey, api, lookup) fatalIf(err.Trace(ctx.Args()...), "Unable to initialize new config from the provided credentials.") diff --git a/docs/minio-admin-complete-guide.md b/docs/minio-admin-complete-guide.md index 773d5a65e1..7b4aff6b3c 100644 --- a/docs/minio-admin-complete-guide.md +++ b/docs/minio-admin-complete-guide.md @@ -99,14 +99,35 @@ MinIO server displays URL, access and secret keys. #### Usage ``` -mc config host add +mc config host add [YOUR-ACCESS-KEY] [YOUR-SECRET-KEY] ``` +Keys must be supplied by argument or standard input. + Alias is simply a short name to your MinIO service. MinIO end-point, access and secret keys are supplied by your MinIO service. Admin API uses "S3v4" signature and cannot be changed. -``` -mc config host add minio http://192.168.1.51:9000 BKIKJAA5BMMU2RHO6IBB V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 -``` +### Examples + +1. Keys by argument + + ``` + mc config host add minio http://192.168.1.51:9000 BKIKJAA5BMMU2RHO6IBB V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 + ``` + +2. Keys by prompt + + ``` + mc config host add minio http://192.168.1.51:9000 + Enter Access Key: BKIKJAA5BMMU2RHO6IBB + Enter Secret Key: V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 + ``` + +2. Keys by pipe + + ``` + echo -e "BKIKJAA5BMMU2RHO6IBB\nV7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12" | \ + mc config host add minio http://192.168.1.51:9000 + ``` ## 4. Test Your Setup @@ -430,6 +451,14 @@ COMMANDS: mc admin user add myminio/ newuser newuser123 ``` +*Example: Add a new user 'newuser' on MinIO, using standard input.* + +``` +mc admin user add myminio/ +Enter Access Key: newuser +Enter Secret Key: newuser123 +``` + *Example: Disable a user 'newuser' on MinIO.* ``` diff --git a/docs/minio-client-complete-guide.md b/docs/minio-client-complete-guide.md index 1e3d41de97..7b9f5927a2 100644 --- a/docs/minio-client-complete-guide.md +++ b/docs/minio-client-complete-guide.md @@ -119,9 +119,11 @@ To add one or more Amazon S3 compatible hosts, please follow the instructions be #### Usage ``` -mc config host add +mc config host add [YOUR-ACCESS-KEY] [YOUR-SECRET-KEY] [--api API-SIGNATURE] ``` +Keys must be supplied by argument or standard input. + Alias is simply a short name to your cloud storage service. S3 end-point, access and secret keys are supplied by your cloud storage provider. API signature is an optional argument. By default, it is set to "S3v4". ### Example - MinIO Cloud Storage @@ -146,6 +148,23 @@ Get your AccessKeyID and SecretAccessKey by following [Google Credentials Guide] mc config host add gcs https://storage.googleapis.com BKIKJAA5BMMU2RHO6IBB V8f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 ``` +### Example - Specify keys using standard input + +1. Prompt + + ``` + mc config host add minio http://192.168.1.51 --api S3v4 + Enter Access Key: BKIKJAA5BMMU2RHO6IBB + Enter Secret Key: V7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12 + ``` + +2. Pipe + + ``` + echo -e "BKIKJAA5BMMU2RHO6IBB\nV7f1CwQqAcwo80UEIJEjc5gVQUSSx5ohQ9GSrr12" | \ + mc config host add minio http://192.168.1.51 --api S3v4 + ``` + ### Specify host configuration through environment variable ``` export MC_HOST_=https://:@ diff --git a/go.mod b/go.mod index f1c94bb540..10158260bf 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/rjeczalik/notify v0.9.2 github.com/ugorji/go v1.1.7 // indirect go.uber.org/zap v1.11.0 // indirect - golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 // indirect + golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 golang.org/x/net v0.0.0-20200202094626-16171245cfb2 golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 // indirect golang.org/x/text v0.3.2