github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/command/acl/token/update/token_update_test.go (about)

     1  package tokenupdate
     2  
     3  import (
     4  	"os"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/hashicorp/consul/agent"
    11  	"github.com/hashicorp/consul/api"
    12  	"github.com/hashicorp/consul/logger"
    13  	"github.com/hashicorp/consul/testrpc"
    14  	"github.com/hashicorp/consul/testutil"
    15  	"github.com/hashicorp/consul/testutil/retry"
    16  	"github.com/mitchellh/cli"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  func TestTokenUpdateCommand_noTabs(t *testing.T) {
    21  	t.Parallel()
    22  
    23  	if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') {
    24  		t.Fatal("help has tabs")
    25  	}
    26  }
    27  
    28  func TestTokenUpdateCommand(t *testing.T) {
    29  	t.Parallel()
    30  	assert := assert.New(t)
    31  	// Alias because we need to access require package in Retry below
    32  	req := require.New(t)
    33  
    34  	testDir := testutil.TempDir(t, "acl")
    35  	defer os.RemoveAll(testDir)
    36  
    37  	a := agent.NewTestAgent(t, t.Name(), `
    38  	primary_datacenter = "dc1"
    39  	acl {
    40  		enabled = true
    41  		tokens {
    42  			master = "root"
    43  		}
    44  	}`)
    45  
    46  	a.Agent.LogWriter = logger.NewLogWriter(512)
    47  
    48  	defer a.Shutdown()
    49  	testrpc.WaitForLeader(t, a.RPC, "dc1")
    50  
    51  	ui := cli.NewMockUi()
    52  
    53  	// Create a policy
    54  	client := a.Client()
    55  
    56  	policy, _, err := client.ACL().PolicyCreate(
    57  		&api.ACLPolicy{Name: "test-policy"},
    58  		&api.WriteOptions{Token: "root"},
    59  	)
    60  	req.NoError(err)
    61  
    62  	// create a token
    63  	token, _, err := client.ACL().TokenCreate(
    64  		&api.ACLToken{Description: "test"},
    65  		&api.WriteOptions{Token: "root"},
    66  	)
    67  	req.NoError(err)
    68  
    69  	// create a legacy token
    70  	legacyTokenSecretID, _, err := client.ACL().Create(&api.ACLEntry{
    71  		Name:  "Legacy token",
    72  		Type:  "client",
    73  		Rules: "service \"test\" { policy = \"write\" }",
    74  	},
    75  		&api.WriteOptions{Token: "root"},
    76  	)
    77  	req.NoError(err)
    78  
    79  	// We fetch the legacy token later to give server time to async background
    80  	// upgrade it.
    81  
    82  	// update with policy by name
    83  	{
    84  		cmd := New(ui)
    85  		args := []string{
    86  			"-http-addr=" + a.HTTPAddr(),
    87  			"-id=" + token.AccessorID,
    88  			"-token=root",
    89  			"-policy-name=" + policy.Name,
    90  			"-description=test token",
    91  		}
    92  
    93  		code := cmd.Run(args)
    94  		assert.Equal(code, 0)
    95  		assert.Empty(ui.ErrorWriter.String())
    96  
    97  		token, _, err := client.ACL().TokenRead(
    98  			token.AccessorID,
    99  			&api.QueryOptions{Token: "root"},
   100  		)
   101  		assert.NoError(err)
   102  		assert.NotNil(token)
   103  	}
   104  
   105  	// update with policy by id
   106  	{
   107  		cmd := New(ui)
   108  		args := []string{
   109  			"-http-addr=" + a.HTTPAddr(),
   110  			"-id=" + token.AccessorID,
   111  			"-token=root",
   112  			"-policy-id=" + policy.ID,
   113  			"-description=test token",
   114  		}
   115  
   116  		code := cmd.Run(args)
   117  		assert.Equal(code, 0)
   118  		assert.Empty(ui.ErrorWriter.String())
   119  
   120  		token, _, err := client.ACL().TokenRead(
   121  			token.AccessorID,
   122  			&api.QueryOptions{Token: "root"},
   123  		)
   124  		assert.NoError(err)
   125  		assert.NotNil(token)
   126  	}
   127  
   128  	// update with no description shouldn't delete the current description
   129  	{
   130  		cmd := New(ui)
   131  		args := []string{
   132  			"-http-addr=" + a.HTTPAddr(),
   133  			"-id=" + token.AccessorID,
   134  			"-token=root",
   135  			"-policy-name=" + policy.Name,
   136  		}
   137  
   138  		code := cmd.Run(args)
   139  		assert.Equal(code, 0)
   140  		assert.Empty(ui.ErrorWriter.String())
   141  
   142  		token, _, err := client.ACL().TokenRead(
   143  			token.AccessorID,
   144  			&api.QueryOptions{Token: "root"},
   145  		)
   146  		assert.NoError(err)
   147  		assert.NotNil(token)
   148  		assert.Equal("test token", token.Description)
   149  	}
   150  
   151  	// Need legacy token now, hopefully server had time to generate an accessor ID
   152  	// in the background but wait for it if not.
   153  	var legacyToken *api.ACLToken
   154  	retry.Run(t, func(r *retry.R) {
   155  		// Fetch the legacy token via new API so we can use it's accessor ID
   156  		legacyToken, _, err = client.ACL().TokenReadSelf(
   157  			&api.QueryOptions{Token: legacyTokenSecretID})
   158  		r.Check(err)
   159  		require.NotEmpty(r, legacyToken.AccessorID)
   160  	})
   161  
   162  	// upgrade legacy token should replace rules and leave token in a "new" state!
   163  	{
   164  		cmd := New(ui)
   165  		args := []string{
   166  			"-http-addr=" + a.HTTPAddr(),
   167  			"-id=" + legacyToken.AccessorID,
   168  			"-token=root",
   169  			"-policy-name=" + policy.Name,
   170  			"-upgrade-legacy",
   171  		}
   172  
   173  		code := cmd.Run(args)
   174  		assert.Equal(code, 0)
   175  		assert.Empty(ui.ErrorWriter.String())
   176  
   177  		gotToken, _, err := client.ACL().TokenRead(
   178  			legacyToken.AccessorID,
   179  			&api.QueryOptions{Token: "root"},
   180  		)
   181  		assert.NoError(err)
   182  		assert.NotNil(gotToken)
   183  		// Description shouldn't change
   184  		assert.Equal("Legacy token", gotToken.Description)
   185  		assert.Len(gotToken.Policies, 1)
   186  		// Rules should now be empty meaning this is no longer a legacy token
   187  		assert.Empty(gotToken.Rules)
   188  		// Secret should not have changes
   189  		assert.Equal(legacyToken.SecretID, gotToken.SecretID)
   190  	}
   191  }