github.com/hernad/nomad@v1.6.112/command/acl_auth_method_create.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package command
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"io"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/hernad/nomad/api"
    14  	"github.com/mitchellh/cli"
    15  	"github.com/posener/complete"
    16  	"golang.org/x/exp/slices"
    17  )
    18  
    19  // Ensure ACLAuthMethodCreateCommand satisfies the cli.Command interface.
    20  var _ cli.Command = &ACLAuthMethodCreateCommand{}
    21  
    22  // ACLAuthMethodCreateCommand implements cli.Command.
    23  type ACLAuthMethodCreateCommand struct {
    24  	Meta
    25  
    26  	name          string
    27  	methodType    string
    28  	tokenLocality string
    29  	maxTokenTTL   time.Duration
    30  	isDefault     bool
    31  	config        string
    32  	json          bool
    33  	tmpl          string
    34  
    35  	testStdin io.Reader
    36  }
    37  
    38  // Help satisfies the cli.Command Help function.
    39  func (a *ACLAuthMethodCreateCommand) Help() string {
    40  	helpText := `
    41  Usage: nomad acl auth-method create [options]
    42  
    43    Create is used to create new ACL auth methods. Use requires a management token.
    44  
    45  General Options:
    46  
    47    ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + `
    48  
    49  ACL Auth Method Create Options:
    50  
    51    -name
    52      Sets the human readable name for the ACL auth method. The name must be
    53      between 1-128 characters and is a required parameter.
    54  
    55    -type
    56      Sets the type of the auth method. Supported types are 'OIDC' and 'JWT'.
    57  
    58    -max-token-ttl
    59      Sets the duration of time all tokens created by this auth method should be
    60      valid for.
    61  
    62    -token-locality
    63      Defines the kind of token that this auth method should produce. This can be
    64      either 'local' or 'global'.
    65  
    66    -default
    67      Specifies whether this auth method should be treated as a default one in
    68      case no auth method is explicitly specified for a login command.
    69  
    70    -config
    71      Auth method configuration in JSON format. May be prefixed with '@' to
    72      indicate that the value is a file path to load the config from. '-' may also
    73      be given to indicate that the config is available on stdin.
    74  
    75    -json
    76      Output the ACL auth-method in a JSON format.
    77  
    78    -t
    79      Format and display the ACL auth-method using a Go template.
    80  `
    81  	return strings.TrimSpace(helpText)
    82  }
    83  
    84  func (a *ACLAuthMethodCreateCommand) AutocompleteFlags() complete.Flags {
    85  	return mergeAutocompleteFlags(a.Meta.AutocompleteFlags(FlagSetClient),
    86  		complete.Flags{
    87  			"-name":           complete.PredictAnything,
    88  			"-type":           complete.PredictSet("OIDC", "JWT"),
    89  			"-max-token-ttl":  complete.PredictAnything,
    90  			"-token-locality": complete.PredictSet("local", "global"),
    91  			"-default":        complete.PredictSet("true", "false"),
    92  			"-config":         complete.PredictNothing,
    93  			"-json":           complete.PredictNothing,
    94  			"-t":              complete.PredictAnything,
    95  		})
    96  }
    97  
    98  func (a *ACLAuthMethodCreateCommand) AutocompleteArgs() complete.Predictor {
    99  	return complete.PredictNothing
   100  }
   101  
   102  // Synopsis satisfies the cli.Command Synopsis function.
   103  func (a *ACLAuthMethodCreateCommand) Synopsis() string { return "Create a new ACL auth method" }
   104  
   105  // Name returns the name of this command.
   106  func (a *ACLAuthMethodCreateCommand) Name() string { return "acl auth-method create" }
   107  
   108  // Run satisfies the cli.Command Run function.
   109  func (a *ACLAuthMethodCreateCommand) Run(args []string) int {
   110  
   111  	flags := a.Meta.FlagSet(a.Name(), FlagSetClient)
   112  	flags.Usage = func() { a.Ui.Output(a.Help()) }
   113  	flags.StringVar(&a.name, "name", "", "")
   114  	flags.StringVar(&a.methodType, "type", "", "")
   115  	flags.StringVar(&a.tokenLocality, "token-locality", "", "")
   116  	flags.DurationVar(&a.maxTokenTTL, "max-token-ttl", 0, "")
   117  	flags.BoolVar(&a.isDefault, "default", false, "")
   118  	flags.StringVar(&a.config, "config", "", "")
   119  	flags.BoolVar(&a.json, "json", false, "")
   120  	flags.StringVar(&a.tmpl, "t", "", "")
   121  	if err := flags.Parse(args); err != nil {
   122  		return 1
   123  	}
   124  
   125  	// Check that we got no arguments.
   126  	if len(flags.Args()) != 0 {
   127  		a.Ui.Error("This command takes no arguments")
   128  		a.Ui.Error(commandErrorText(a))
   129  		return 1
   130  	}
   131  
   132  	// Perform some basic validation
   133  	if a.name == "" {
   134  		a.Ui.Error("ACL auth method name must be specified using the -name flag")
   135  		return 1
   136  	}
   137  	if !slices.Contains([]string{"global", "local"}, a.tokenLocality) {
   138  		a.Ui.Error("Token locality must be set to either 'local' or 'global'")
   139  		return 1
   140  	}
   141  	if a.maxTokenTTL < 1 {
   142  		a.Ui.Error("Max token TTL must be set to a value between min and max TTL configured for the server.")
   143  		return 1
   144  	}
   145  	if !slices.Contains([]string{"OIDC", "JWT"}, strings.ToUpper(a.methodType)) {
   146  		a.Ui.Error("ACL auth method type must be set to 'OIDC' or 'JWT'")
   147  		return 1
   148  	}
   149  	if len(a.config) == 0 {
   150  		a.Ui.Error("Must provide ACL auth method config in JSON format")
   151  		return 1
   152  	}
   153  
   154  	config, err := loadDataSource(a.config, a.testStdin)
   155  	if err != nil {
   156  		a.Ui.Error(fmt.Sprintf("Error loading configuration: %v", err))
   157  		return 1
   158  	}
   159  
   160  	configJSON := api.ACLAuthMethodConfig{}
   161  	err = json.Unmarshal([]byte(config), &configJSON)
   162  	if err != nil {
   163  		a.Ui.Error(fmt.Sprintf("Unable to parse config: %v", err))
   164  		return 1
   165  	}
   166  
   167  	// Set up the auth method with the passed parameters.
   168  	authMethod := api.ACLAuthMethod{
   169  		Name:          a.name,
   170  		Type:          strings.ToUpper(a.methodType),
   171  		TokenLocality: a.tokenLocality,
   172  		MaxTokenTTL:   a.maxTokenTTL,
   173  		Default:       a.isDefault,
   174  		Config:        &configJSON,
   175  	}
   176  
   177  	// Get the HTTP client.
   178  	client, err := a.Meta.Client()
   179  	if err != nil {
   180  		a.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
   181  		return 1
   182  	}
   183  
   184  	// Create the auth method via the API.
   185  	method, _, err := client.ACLAuthMethods().Create(&authMethod, nil)
   186  	if err != nil {
   187  		a.Ui.Error(fmt.Sprintf("Error creating ACL auth method: %v", err))
   188  		return 1
   189  	}
   190  
   191  	if a.json || len(a.tmpl) > 0 {
   192  		out, err := Format(a.json, a.tmpl, method)
   193  		if err != nil {
   194  			a.Ui.Error(err.Error())
   195  			return 1
   196  		}
   197  
   198  		a.Ui.Output(out)
   199  		return 0
   200  	}
   201  
   202  	outputAuthMethod(a.Meta, method)
   203  	return 0
   204  }