update acl token

This commit is contained in:
Chelsea Holland Komlo
2017-09-15 23:54:41 +00:00
parent 5c44105b64
commit edf14142de
5 changed files with 242 additions and 0 deletions

129
command/acl_token_update.go Normal file
View File

@@ -0,0 +1,129 @@
package command
import (
"fmt"
"strings"
"github.com/posener/complete"
)
type ACLTokenUpdateCommand struct {
Meta
}
func (c *ACLTokenUpdateCommand) Help() string {
helpText := `
Usage: nomad acl token update <token_accessor_id>
Update is used to update an existing ACL token. Requires a management token.
General Options:
` + generalOptionsUsage() + `
Update Options:
-name=""
Sets the human readable name for the ACL token.
-type="client"
Sets the type of token. Must be one of "client" (default), or "management".
-global=false
Toggles the global mode of the token. Global tokens are replicated to all regions.
-policy=""
Specifies a policy to associate with the token. Can be specified multiple times,
but only with client type tokens.
`
return strings.TrimSpace(helpText)
}
func (c *ACLTokenUpdateCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"name": complete.PredictAnything,
"type": complete.PredictAnything,
"global": complete.PredictNothing,
"policy": complete.PredictAnything,
})
}
func (c *ACLTokenUpdateCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}
func (c *ACLTokenUpdateCommand) Synopsis() string {
return "Update an existing ACL token"
}
func (c *ACLTokenUpdateCommand) Run(args []string) int {
var name, tokenType string
var global bool
var policies []string
flags := c.Meta.FlagSet("acl token update", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.StringVar(&name, "name", "", "")
flags.StringVar(&tokenType, "type", "client", "")
flags.BoolVar(&global, "global", false, "")
flags.Var((funcVar)(func(s string) error {
policies = append(policies, s)
return nil
}), "policy", "")
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we got exactly one argument
args = flags.Args()
if l := len(args); l != 1 {
c.Ui.Error(c.Help())
return 1
}
tokenAccessorID := args[0]
// Get the HTTP client
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Get the specified token
token, _, err := client.ACLTokens().Info(tokenAccessorID, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error fetching token: %s", err))
return 1
}
// Create the updated token
if name != "" {
token.Name = name
}
if tokenType != "" {
token.Type = tokenType
}
// This will default to false if the user does not specify it
if global != token.Global {
token.Global = global
}
if len(policies) != 0 {
token.Policies = policies
}
// Update the token
updatedToken, _, err := client.ACLTokens().Update(token, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Error updating token: %s", err))
return 1
}
// Format the output
c.Ui.Output(formatKVACLToken(updatedToken))
return 0
}

View File

@@ -0,0 +1,55 @@
package command
import (
"os"
"testing"
"github.com/hashicorp/nomad/acl"
"github.com/hashicorp/nomad/command/agent"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
)
func TestACLTokenUpdateCommand(t *testing.T) {
assert := assert.New(t)
t.Parallel()
config := func(c *agent.Config) {
c.ACL.Enabled = true
}
srv, _, url := testServer(t, true, config)
defer srv.Shutdown()
// Bootstrap an initial ACL token
token := srv.Token
assert.NotNil(token, "failed to bootstrap ACL token")
ui := new(cli.MockUi)
cmd := &ACLTokenUpdateCommand{Meta: Meta{Ui: ui, flagAddress: url}}
state := srv.Agent.Server().State()
// Create a valid token
mockToken := mock.ACLToken()
mockToken.Policies = []string{acl.PolicyWrite}
mockToken.SetHash()
assert.Nil(state.UpsertACLTokens(1000, []*structs.ACLToken{mockToken}))
// Request to update a new token without providing a valid management token
invalidToken := mock.ACLToken()
os.Setenv("NOMAD_TOKEN", invalidToken.SecretID)
code := cmd.Run([]string{"-address=" + url, "-name=bar", mockToken.AccessorID})
//code := cmd.Run([]string{"-address=" + url, "-policy=foo", "-type=client"})
assert.Equal(1, code)
// Request to update a new token with a valid management token
os.Setenv("NOMAD_TOKEN", token.SecretID)
code = cmd.Run([]string{"-address=" + url, "-name=bar", mockToken.AccessorID})
assert.Equal(0, code)
// Check the output
out := ui.OutputWriter.String()
assert.Contains(out, mockToken.AccessorID)
assert.Contains(out, "bar")
}

View File

@@ -66,6 +66,11 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"acl token update": func() (cli.Command, error) {
return &command.ACLTokenUpdateCommand{
Meta: meta,
}, nil
},
"acl token delete": func() (cli.Command, error) {
return &command.ACLTokenDeleteCommand{
Meta: meta,

View File

@@ -24,6 +24,7 @@ subcommands are available:
* [`acl policy delete`][policydelete] - Delete an existing ACL policies
* [`acl policy info`][policyinfo] - Fetch information on an existing ACL policy
* [`acl token create`][tokencreate] - Create new ACL token
* [`acl token update`][tokenupdate] - Update existing ACL token
* [`acl token delete`][tokendelete] - Delete an existing ACL token
* [`acl token info`][tokeninfo] - Get info on an existing ACL token
@@ -32,6 +33,7 @@ subcommands are available:
[policydelete]: /docs/commands/acl/policy-delete.html
[policyinfo]: /docs/commands/acl/policy-info.html
[tokencreate]: /docs/commands/acl/token-create.html
[tokenupdate]: /docs/commands/acl/token-update.html
[tokendelete]: /docs/commands/acl/token-delete.html
[tokeninfo]: /docs/commands/acl/token-info.html

View File

@@ -0,0 +1,51 @@
---
layout: "docs"
page_title: "Commands: acl token create"
sidebar_current: "docs-commands-acl-token-create"
description: >
The token create command is used to update existing ACL tokens.
---
# Command: acl token update
The `acl token update` command is used to update existing ACL tokens.
## Usage
```
nomad acl token update [options] <token_accessor_id>
```
The `acl token update` command requires an existing token's accessor ID.
## General Options
<%= partial "docs/commands/_general_options" %>
## Create Options
* `-name`: Sets the human readable name for the ACL token.
* `-type`: Sets the type of token. Must be one of "client" (default), or "management".
* `-global`: Toggles the global mode of the token. Global tokens are replicated to all regions. Defaults false.
* `-policy`: Specifies a policy to associate with the token. Can be specified multiple times,
but only with client type tokens.
## Examples
Update an existing ACL token:
```
$ nomad acl token update -name="my updated token" -policy=foo -policy=bar d532c40a-30f1-695c-19e5-c35b882b0efd
Accessor ID = d532c40a-30f1-695c-19e5-c35b882b0efd
Secret ID = 85310d07-9afa-ef53-0933-0c043cd673c7
Name = my updated token
Type = client
Global = false
Policies = [foo bar]
Create Time = 2017-09-15 05:04:41.814954949 +0000 UTC
Create Index = 8
Modify Index = 8
```