github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/alias-import.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"encoding/json"
    22  	"os"
    23  	"strings"
    24  
    25  	"github.com/minio/cli"
    26  	"github.com/minio/mc/pkg/probe"
    27  )
    28  
    29  var aliasImportCmd = cli.Command{
    30  	Name:            "import",
    31  	ShortName:       "i",
    32  	Usage:           "import configuration info to configuration file from a JSON formatted string ",
    33  	Action:          mainAliasImport,
    34  	OnUsageError:    onUsageError,
    35  	Before:          setGlobalsFromContext,
    36  	Flags:           globalFlags,
    37  	HideHelpCommand: true,
    38  	CustomHelpTemplate: `NAME:
    39    {{.HelpName}} - {{.Usage}}
    40  
    41  USAGE:
    42    {{.HelpName}} ALIAS ./credentials.json
    43  
    44    Credentials to be imported must be in the following JSON format:
    45    
    46    {
    47      "url": "http://localhost:9000",
    48      "accessKey": "YJ0RI0F4R5HWY38MD873",
    49      "secretKey": "OHz5CT7xdMHiXnKZP0BmZ5P4G5UvWvVaxR8gljLG",
    50      "api": "s3v4",
    51      "path": "auto"
    52    }
    53  
    54  FLAGS:
    55    {{range .VisibleFlags}}{{.}}
    56    {{end}}
    57  EXAMPLES:
    58    1. Import the provided credentials.json file as 'myminio' to the config:
    59       {{ .Prompt }} {{ .HelpName }} myminio/ ./credentials.json
    60  
    61    2. Import the credentials through standard input as 'myminio' to the config:
    62       {{ .Prompt }} cat credentials.json | {{ .HelpName }} myminio/
    63  `,
    64  }
    65  
    66  // checkAliasImportSyntax - verifies input arguments to 'alias import'.
    67  func checkAliasImportSyntax(ctx *cli.Context) {
    68  	args := ctx.Args()
    69  	argsNr := len(args)
    70  
    71  	if argsNr == 0 {
    72  		showCommandHelpAndExit(ctx, 1)
    73  	}
    74  	if argsNr > 2 {
    75  		fatalIf(errInvalidArgument().Trace(ctx.Args().Tail()...),
    76  			"Incorrect number of arguments for alias Import command.")
    77  	}
    78  
    79  	alias := cleanAlias(args.Get(0))
    80  
    81  	if !isValidAlias(alias) {
    82  		fatalIf(errInvalidAlias(alias), "Invalid alias.")
    83  	}
    84  }
    85  
    86  func checkCredentialsSyntax(credentials aliasConfigV10) {
    87  	if !isValidHostURL(credentials.URL) {
    88  		fatalIf(errInvalidURL(credentials.URL), "Invalid URL.")
    89  	}
    90  
    91  	if !isValidAccessKey(credentials.AccessKey) {
    92  		fatalIf(errInvalidArgument().Trace(credentials.AccessKey),
    93  			"Invalid access key `"+credentials.AccessKey+"`.")
    94  	}
    95  
    96  	if !isValidSecretKey(credentials.SecretKey) {
    97  		fatalIf(errInvalidArgument().Trace(),
    98  			"Invalid secret key.")
    99  	}
   100  
   101  	if credentials.API != "" && !isValidAPI(credentials.API) { // Empty value set to default "S3v4".
   102  		fatalIf(errInvalidArgument().Trace(credentials.API),
   103  			"Unrecognized API signature. Valid options are `[S3v4, S3v2]`.")
   104  	}
   105  	if !isValidPath(credentials.Path) {
   106  		fatalIf(errInvalidArgument().Trace(credentials.Path),
   107  			"Unrecognized path value. Valid options are `[auto, on, off]`.")
   108  	}
   109  }
   110  
   111  // importAlias - set an alias config based on imported values.
   112  func importAlias(alias string, aliasCfgV10 aliasConfigV10) aliasMessage {
   113  	checkCredentialsSyntax(aliasCfgV10)
   114  
   115  	mcCfgV10, err := loadMcConfig()
   116  	fatalIf(err.Trace(globalMCConfigVersion), "Unable to load config `"+mustGetMcConfigPath()+"`.")
   117  
   118  	// Add new host.
   119  	mcCfgV10.Aliases[alias] = aliasCfgV10
   120  	fatalIf(saveMcConfig(mcCfgV10).Trace(alias), "Unable to import credentials to `"+mustGetMcConfigPath()+"`.")
   121  	return aliasMessage{
   122  		Alias:     alias,
   123  		URL:       mcCfgV10.Aliases[alias].URL,
   124  		AccessKey: mcCfgV10.Aliases[alias].AccessKey,
   125  		SecretKey: mcCfgV10.Aliases[alias].SecretKey,
   126  		API:       mcCfgV10.Aliases[alias].API,
   127  		Path:      mcCfgV10.Aliases[alias].Path,
   128  	}
   129  }
   130  
   131  func mainAliasImport(cli *cli.Context) error {
   132  	var (
   133  		args  = cli.Args()
   134  		alias = cleanAlias(args.Get(0))
   135  	)
   136  
   137  	checkAliasImportSyntax(cli)
   138  	var credentialsJSON aliasConfigV10
   139  
   140  	credsFile := strings.TrimSpace(args.Get(1))
   141  	if credsFile == "" {
   142  		credsFile = os.Stdin.Name()
   143  	}
   144  	input, e := os.ReadFile(credsFile)
   145  	fatalIf(probe.NewError(e).Trace(args...), "Unable to parse credentials file")
   146  
   147  	e = json.Unmarshal(input, &credentialsJSON)
   148  	fatalIf(probe.NewError(e).Trace(args...), "Unable to parse input credentials")
   149  
   150  	msg := importAlias(alias, credentialsJSON)
   151  	msg.op = cli.Command.Name
   152  
   153  	printMsg(msg)
   154  
   155  	return nil
   156  }