github.com/hernad/nomad@v1.6.112/command/acl_auth_method_update.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 "flag" 9 "fmt" 10 "io" 11 "strings" 12 "time" 13 14 "github.com/hernad/nomad/api" 15 "github.com/mitchellh/cli" 16 "github.com/posener/complete" 17 "golang.org/x/exp/slices" 18 ) 19 20 // Ensure ACLAuthMethodUpdateCommand satisfies the cli.Command interface. 21 var _ cli.Command = &ACLAuthMethodUpdateCommand{} 22 23 // ACLAuthMethodUpdateCommand implements cli.Command. 24 type ACLAuthMethodUpdateCommand struct { 25 Meta 26 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 *ACLAuthMethodUpdateCommand) Help() string { 40 helpText := ` 41 Usage: nomad acl auth-method update [options] <acl_auth_method_name> 42 43 Update is used to update ACL auth methods. Use requires a management token. 44 45 General Options: 46 47 ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + ` 48 49 ACL Auth Method Update Options: 50 51 -type 52 Updates the type of the auth method. Supported types are 'OIDC' and 'JWT'. 53 54 -max-token-ttl 55 Updates the duration of time all tokens created by this auth method should be 56 valid for. 57 58 -token-locality 59 Updates the kind of token that this auth method should produce. This can be 60 either 'local' or 'global'. 61 62 -default 63 Specifies whether this auth method should be treated as a default one in 64 case no auth method is explicitly specified for a login command. 65 66 -config 67 Updates auth method configuration (in JSON format). May be prefixed with 68 '@' to indicate that the value is a file path to load the config from. '-' 69 may also be given to indicate that the config is available on stdin. 70 71 -json 72 Output the ACL auth-method in a JSON format. 73 74 -t 75 Format and display the ACL auth-method using a Go template. 76 ` 77 78 return strings.TrimSpace(helpText) 79 } 80 81 func (a *ACLAuthMethodUpdateCommand) AutocompleteFlags() complete.Flags { 82 return mergeAutocompleteFlags(a.Meta.AutocompleteFlags(FlagSetClient), 83 complete.Flags{ 84 "-type": complete.PredictSet("OIDC", "JWT"), 85 "-max-token-ttl": complete.PredictAnything, 86 "-token-locality": complete.PredictSet("local", "global"), 87 "-default": complete.PredictSet("true", "false"), 88 "-config": complete.PredictNothing, 89 "-json": complete.PredictNothing, 90 "-t": complete.PredictAnything, 91 }) 92 } 93 94 func (a *ACLAuthMethodUpdateCommand) AutocompleteArgs() complete.Predictor { 95 return complete.PredictNothing 96 } 97 98 // Synopsis satisfies the cli.Command Synopsis function. 99 func (a *ACLAuthMethodUpdateCommand) Synopsis() string { return "Update an existing ACL auth method" } 100 101 // Name returns the name of this command. 102 func (*ACLAuthMethodUpdateCommand) Name() string { return "acl auth-method update" } 103 104 // Run satisfies the cli.Command Run function. 105 func (a *ACLAuthMethodUpdateCommand) Run(args []string) int { 106 107 flags := a.Meta.FlagSet(a.Name(), FlagSetClient) 108 flags.Usage = func() { a.Ui.Output(a.Help()) } 109 flags.StringVar(&a.methodType, "type", "", "") 110 flags.StringVar(&a.tokenLocality, "token-locality", "", "") 111 flags.DurationVar(&a.maxTokenTTL, "max-token-ttl", 0, "") 112 flags.StringVar(&a.config, "config", "", "") 113 flags.BoolVar(&a.isDefault, "default", false, "") 114 flags.BoolVar(&a.json, "json", false, "") 115 flags.StringVar(&a.tmpl, "t", "", "") 116 if err := flags.Parse(args); err != nil { 117 return 1 118 } 119 120 // Check that the last argument is the auth method name to delete. 121 if len(flags.Args()) != 1 { 122 a.Ui.Error("This command takes one argument: <acl_auth_method_name>") 123 a.Ui.Error(commandErrorText(a)) 124 return 1 125 } 126 127 originalMethodName := flags.Args()[0] 128 129 // Get the HTTP client. 130 client, err := a.Meta.Client() 131 if err != nil { 132 a.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 133 return 1 134 } 135 136 // Check if the method we want to update exists 137 originalMethod, _, err := client.ACLAuthMethods().Get(originalMethodName, nil) 138 if err != nil { 139 a.Ui.Error(fmt.Sprintf("Error when retrieving ACL auth method: %v", err)) 140 return 1 141 } 142 143 // Check if any command-specific flags were set 144 setFlags := []string{} 145 for _, f := range []string{"type", "token-locality", "max-token-ttl", "config", "default"} { 146 if flagPassed(flags, f) { 147 setFlags = append(setFlags, f) 148 } 149 } 150 if len(setFlags) == 0 { 151 a.Ui.Error("Please provide at least one flag to update the ACL auth method") 152 return 1 153 } 154 155 updatedMethod := *originalMethod 156 157 if slices.Contains(setFlags, "token-locality") { 158 if !slices.Contains([]string{"global", "local"}, a.tokenLocality) { 159 a.Ui.Error("Token locality must be set to either 'local' or 'global'") 160 return 1 161 } 162 updatedMethod.TokenLocality = a.tokenLocality 163 } 164 165 if slices.Contains(setFlags, "type") { 166 if !slices.Contains([]string{"OIDC", "JWT"}, strings.ToUpper(a.methodType)) { 167 a.Ui.Error("ACL auth method type must be set to 'OIDC' or 'JWT'") 168 return 1 169 } 170 updatedMethod.Type = a.methodType 171 } 172 173 if slices.Contains(setFlags, "max-token-ttl") { 174 if a.maxTokenTTL < 1 { 175 a.Ui.Error("Max token TTL must be set to a value between min and max TTL configured for the server.") 176 return 1 177 } 178 updatedMethod.MaxTokenTTL = a.maxTokenTTL 179 } 180 181 if slices.Contains(setFlags, "default") { 182 updatedMethod.Default = a.isDefault 183 } 184 185 if len(a.config) != 0 { 186 config, err := loadDataSource(a.config, a.testStdin) 187 if err != nil { 188 a.Ui.Error(fmt.Sprintf("Error loading configuration: %v", err)) 189 return 1 190 } 191 192 configJSON := api.ACLAuthMethodConfig{} 193 err = json.Unmarshal([]byte(config), &configJSON) 194 if err != nil { 195 a.Ui.Error(fmt.Sprintf("Unable to parse config: %v", err)) 196 return 1 197 } 198 updatedMethod.Config = &configJSON 199 } 200 201 // Update the auth method via the API. 202 method, _, err := client.ACLAuthMethods().Update(&updatedMethod, nil) 203 if err != nil { 204 a.Ui.Error(fmt.Sprintf("Error updating ACL auth method: %v", err)) 205 return 1 206 } 207 208 if a.json || len(a.tmpl) > 0 { 209 out, err := Format(a.json, a.tmpl, method) 210 if err != nil { 211 a.Ui.Error(err.Error()) 212 return 1 213 } 214 215 a.Ui.Output(out) 216 return 0 217 } 218 219 outputAuthMethod(a.Meta, method) 220 return 0 221 } 222 223 func flagPassed(flags *flag.FlagSet, name string) bool { 224 found := false 225 flags.Visit(func(f *flag.Flag) { 226 if f.Name == name { 227 found = true 228 } 229 }) 230 return found 231 }