github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/kvs_endpoint_test.go (about)

     1  package consul
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/hashicorp/consul/acl"
     9  	"github.com/hashicorp/consul/agent/structs"
    10  	"github.com/hashicorp/consul/api"
    11  	"github.com/hashicorp/consul/testrpc"
    12  	"github.com/hashicorp/net-rpc-msgpackrpc"
    13  	"github.com/pascaldekloe/goe/verify"
    14  )
    15  
    16  func TestKVS_Apply(t *testing.T) {
    17  	t.Parallel()
    18  	dir1, s1 := testServer(t)
    19  	defer os.RemoveAll(dir1)
    20  	defer s1.Shutdown()
    21  	codec := rpcClient(t, s1)
    22  	defer codec.Close()
    23  
    24  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    25  
    26  	arg := structs.KVSRequest{
    27  		Datacenter: "dc1",
    28  		Op:         api.KVSet,
    29  		DirEnt: structs.DirEntry{
    30  			Key:   "test",
    31  			Flags: 42,
    32  			Value: []byte("test"),
    33  		},
    34  	}
    35  	var out bool
    36  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
    37  		t.Fatalf("err: %v", err)
    38  	}
    39  
    40  	// Verify
    41  	state := s1.fsm.State()
    42  	_, d, err := state.KVSGet(nil, "test")
    43  	if err != nil {
    44  		t.Fatalf("err: %v", err)
    45  	}
    46  	if d == nil {
    47  		t.Fatalf("should not be nil")
    48  	}
    49  
    50  	// Do a check and set
    51  	arg.Op = api.KVCAS
    52  	arg.DirEnt.ModifyIndex = d.ModifyIndex
    53  	arg.DirEnt.Flags = 43
    54  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
    55  		t.Fatalf("err: %v", err)
    56  	}
    57  
    58  	// Check this was applied
    59  	if out != true {
    60  		t.Fatalf("bad: %v", out)
    61  	}
    62  
    63  	// Verify
    64  	_, d, err = state.KVSGet(nil, "test")
    65  	if err != nil {
    66  		t.Fatalf("err: %v", err)
    67  	}
    68  	if d.Flags != 43 {
    69  		t.Fatalf("bad: %v", d)
    70  	}
    71  }
    72  
    73  func TestKVS_Apply_ACLDeny(t *testing.T) {
    74  	t.Parallel()
    75  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
    76  		c.ACLDatacenter = "dc1"
    77  		c.ACLsEnabled = true
    78  		c.ACLMasterToken = "root"
    79  		c.ACLDefaultPolicy = "deny"
    80  	})
    81  	defer os.RemoveAll(dir1)
    82  	defer s1.Shutdown()
    83  	codec := rpcClient(t, s1)
    84  	defer codec.Close()
    85  
    86  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    87  
    88  	// Create the ACL
    89  	arg := structs.ACLRequest{
    90  		Datacenter: "dc1",
    91  		Op:         structs.ACLSet,
    92  		ACL: structs.ACL{
    93  			Name:  "User token",
    94  			Type:  structs.ACLTokenTypeClient,
    95  			Rules: testListRules,
    96  		},
    97  		WriteRequest: structs.WriteRequest{Token: "root"},
    98  	}
    99  	var out string
   100  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil {
   101  		t.Fatalf("err: %v", err)
   102  	}
   103  	id := out
   104  
   105  	// Try a write
   106  	argR := structs.KVSRequest{
   107  		Datacenter: "dc1",
   108  		Op:         api.KVSet,
   109  		DirEnt: structs.DirEntry{
   110  			Key:   "foo/bar",
   111  			Flags: 42,
   112  			Value: []byte("test"),
   113  		},
   114  		WriteRequest: structs.WriteRequest{Token: id},
   115  	}
   116  	var outR bool
   117  	err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &argR, &outR)
   118  	if !acl.IsErrPermissionDenied(err) {
   119  		t.Fatalf("err: %v", err)
   120  	}
   121  
   122  	// Try a recursive delete
   123  	argR = structs.KVSRequest{
   124  		Datacenter: "dc1",
   125  		Op:         api.KVDeleteTree,
   126  		DirEnt: structs.DirEntry{
   127  			Key: "test",
   128  		},
   129  		WriteRequest: structs.WriteRequest{Token: id},
   130  	}
   131  	err = msgpackrpc.CallWithCodec(codec, "KVS.Apply", &argR, &outR)
   132  	if !acl.IsErrPermissionDenied(err) {
   133  		t.Fatalf("err: %v", err)
   134  	}
   135  }
   136  
   137  func TestKVS_Get(t *testing.T) {
   138  	t.Parallel()
   139  	dir1, s1 := testServer(t)
   140  	defer os.RemoveAll(dir1)
   141  	defer s1.Shutdown()
   142  	codec := rpcClient(t, s1)
   143  	defer codec.Close()
   144  
   145  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   146  
   147  	arg := structs.KVSRequest{
   148  		Datacenter: "dc1",
   149  		Op:         api.KVSet,
   150  		DirEnt: structs.DirEntry{
   151  			Key:   "test",
   152  			Flags: 42,
   153  			Value: []byte("test"),
   154  		},
   155  	}
   156  	var out bool
   157  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   158  		t.Fatalf("err: %v", err)
   159  	}
   160  
   161  	getR := structs.KeyRequest{
   162  		Datacenter: "dc1",
   163  		Key:        "test",
   164  	}
   165  	var dirent structs.IndexedDirEntries
   166  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil {
   167  		t.Fatalf("err: %v", err)
   168  	}
   169  
   170  	if dirent.Index == 0 {
   171  		t.Fatalf("Bad: %v", dirent)
   172  	}
   173  	if len(dirent.Entries) != 1 {
   174  		t.Fatalf("Bad: %v", dirent)
   175  	}
   176  	d := dirent.Entries[0]
   177  	if d.Flags != 42 {
   178  		t.Fatalf("bad: %v", d)
   179  	}
   180  	if string(d.Value) != "test" {
   181  		t.Fatalf("bad: %v", d)
   182  	}
   183  }
   184  
   185  func TestKVS_Get_ACLDeny(t *testing.T) {
   186  	t.Parallel()
   187  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   188  		c.ACLDatacenter = "dc1"
   189  		c.ACLsEnabled = true
   190  		c.ACLMasterToken = "root"
   191  		c.ACLDefaultPolicy = "deny"
   192  	})
   193  	defer os.RemoveAll(dir1)
   194  	defer s1.Shutdown()
   195  	codec := rpcClient(t, s1)
   196  	defer codec.Close()
   197  
   198  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   199  
   200  	arg := structs.KVSRequest{
   201  		Datacenter: "dc1",
   202  		Op:         api.KVSet,
   203  		DirEnt: structs.DirEntry{
   204  			Key:   "zip",
   205  			Flags: 42,
   206  			Value: []byte("test"),
   207  		},
   208  		WriteRequest: structs.WriteRequest{Token: "root"},
   209  	}
   210  	var out bool
   211  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   212  		t.Fatalf("err: %v", err)
   213  	}
   214  
   215  	getR := structs.KeyRequest{
   216  		Datacenter: "dc1",
   217  		Key:        "zip",
   218  	}
   219  	var dirent structs.IndexedDirEntries
   220  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); !acl.IsErrPermissionDenied(err) {
   221  		t.Fatalf("Expected %v, got err: %v", acl.ErrPermissionDenied, err)
   222  	}
   223  
   224  }
   225  
   226  func TestKVSEndpoint_List(t *testing.T) {
   227  	t.Parallel()
   228  	dir1, s1 := testServer(t)
   229  	defer os.RemoveAll(dir1)
   230  	defer s1.Shutdown()
   231  	codec := rpcClient(t, s1)
   232  	defer codec.Close()
   233  
   234  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   235  
   236  	keys := []string{
   237  		"/test/key1",
   238  		"/test/key2",
   239  		"/test/sub/key3",
   240  	}
   241  
   242  	for _, key := range keys {
   243  		arg := structs.KVSRequest{
   244  			Datacenter: "dc1",
   245  			Op:         api.KVSet,
   246  			DirEnt: structs.DirEntry{
   247  				Key:   key,
   248  				Flags: 1,
   249  			},
   250  		}
   251  		var out bool
   252  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   253  			t.Fatalf("err: %v", err)
   254  		}
   255  	}
   256  
   257  	getR := structs.KeyRequest{
   258  		Datacenter: "dc1",
   259  		Key:        "/test",
   260  	}
   261  	var dirent structs.IndexedDirEntries
   262  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil {
   263  		t.Fatalf("err: %v", err)
   264  	}
   265  
   266  	if dirent.Index == 0 {
   267  		t.Fatalf("Bad: %v", dirent)
   268  	}
   269  	if len(dirent.Entries) != 3 {
   270  		t.Fatalf("Bad: %v", dirent.Entries)
   271  	}
   272  	for i := 0; i < len(dirent.Entries); i++ {
   273  		d := dirent.Entries[i]
   274  		if d.Key != keys[i] {
   275  			t.Fatalf("bad: %v", d)
   276  		}
   277  		if d.Flags != 1 {
   278  			t.Fatalf("bad: %v", d)
   279  		}
   280  		if d.Value != nil {
   281  			t.Fatalf("bad: %v", d)
   282  		}
   283  	}
   284  
   285  	// Try listing a nonexistent prefix
   286  	getR.Key = "/nope"
   287  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil {
   288  		t.Fatalf("err: %v", err)
   289  	}
   290  	if dirent.Index == 0 {
   291  		t.Fatalf("Bad: %v", dirent)
   292  	}
   293  	if len(dirent.Entries) != 0 {
   294  		t.Fatalf("Bad: %v", dirent.Entries)
   295  	}
   296  }
   297  
   298  func TestKVSEndpoint_List_Blocking(t *testing.T) {
   299  	t.Parallel()
   300  	dir1, s1 := testServer(t)
   301  	defer os.RemoveAll(dir1)
   302  	defer s1.Shutdown()
   303  	codec := rpcClient(t, s1)
   304  	defer codec.Close()
   305  
   306  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   307  
   308  	keys := []string{
   309  		"/test/key1",
   310  		"/test/key2",
   311  		"/test/sub/key3",
   312  	}
   313  
   314  	for _, key := range keys {
   315  		arg := structs.KVSRequest{
   316  			Datacenter: "dc1",
   317  			Op:         api.KVSet,
   318  			DirEnt: structs.DirEntry{
   319  				Key:   key,
   320  				Flags: 1,
   321  			},
   322  		}
   323  		var out bool
   324  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   325  			t.Fatalf("err: %v", err)
   326  		}
   327  	}
   328  
   329  	getR := structs.KeyRequest{
   330  		Datacenter: "dc1",
   331  		Key:        "/test",
   332  	}
   333  	var dirent structs.IndexedDirEntries
   334  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil {
   335  		t.Fatalf("err: %v", err)
   336  	}
   337  
   338  	// Setup a blocking query
   339  	getR.MinQueryIndex = dirent.Index
   340  	getR.MaxQueryTime = time.Second
   341  
   342  	// Async cause a change
   343  	start := time.Now()
   344  	go func() {
   345  		time.Sleep(100 * time.Millisecond)
   346  		codec := rpcClient(t, s1)
   347  		defer codec.Close()
   348  		arg := structs.KVSRequest{
   349  			Datacenter: "dc1",
   350  			Op:         api.KVDelete,
   351  			DirEnt: structs.DirEntry{
   352  				Key: "/test/sub/key3",
   353  			},
   354  		}
   355  		var out bool
   356  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   357  			t.Fatalf("err: %v", err)
   358  		}
   359  	}()
   360  
   361  	// Re-run the query
   362  	dirent = structs.IndexedDirEntries{}
   363  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil {
   364  		t.Fatalf("err: %v", err)
   365  	}
   366  
   367  	// Should block at least 100ms
   368  	if time.Since(start) < 100*time.Millisecond {
   369  		t.Fatalf("too fast")
   370  	}
   371  
   372  	if dirent.Index == 0 {
   373  		t.Fatalf("Bad: %v", dirent)
   374  	}
   375  	if len(dirent.Entries) != 2 {
   376  		for _, ent := range dirent.Entries {
   377  			t.Errorf("Bad: %#v", *ent)
   378  		}
   379  	}
   380  	for i := 0; i < len(dirent.Entries); i++ {
   381  		d := dirent.Entries[i]
   382  		if d.Key != keys[i] {
   383  			t.Fatalf("bad: %v", d)
   384  		}
   385  		if d.Flags != 1 {
   386  			t.Fatalf("bad: %v", d)
   387  		}
   388  		if d.Value != nil {
   389  			t.Fatalf("bad: %v", d)
   390  		}
   391  	}
   392  }
   393  
   394  func TestKVSEndpoint_List_ACLDeny(t *testing.T) {
   395  	t.Parallel()
   396  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   397  		c.ACLDatacenter = "dc1"
   398  		c.ACLsEnabled = true
   399  		c.ACLMasterToken = "root"
   400  		c.ACLDefaultPolicy = "deny"
   401  	})
   402  	defer os.RemoveAll(dir1)
   403  	defer s1.Shutdown()
   404  	codec := rpcClient(t, s1)
   405  	defer codec.Close()
   406  
   407  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   408  
   409  	keys := []string{
   410  		"abe",
   411  		"bar",
   412  		"foo",
   413  		"test",
   414  		"zip",
   415  	}
   416  
   417  	for _, key := range keys {
   418  		arg := structs.KVSRequest{
   419  			Datacenter: "dc1",
   420  			Op:         api.KVSet,
   421  			DirEnt: structs.DirEntry{
   422  				Key:   key,
   423  				Flags: 1,
   424  			},
   425  			WriteRequest: structs.WriteRequest{Token: "root"},
   426  		}
   427  		var out bool
   428  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   429  			t.Fatalf("err: %v", err)
   430  		}
   431  	}
   432  
   433  	arg := structs.ACLRequest{
   434  		Datacenter: "dc1",
   435  		Op:         structs.ACLSet,
   436  		ACL: structs.ACL{
   437  			Name:  "User token",
   438  			Type:  structs.ACLTokenTypeClient,
   439  			Rules: testListRules,
   440  		},
   441  		WriteRequest: structs.WriteRequest{Token: "root"},
   442  	}
   443  	var out string
   444  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil {
   445  		t.Fatalf("err: %v", err)
   446  	}
   447  	id := out
   448  
   449  	getR := structs.KeyRequest{
   450  		Datacenter:   "dc1",
   451  		Key:          "",
   452  		QueryOptions: structs.QueryOptions{Token: id},
   453  	}
   454  	var dirent structs.IndexedDirEntries
   455  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getR, &dirent); err != nil {
   456  		t.Fatalf("err: %v", err)
   457  	}
   458  
   459  	if dirent.Index == 0 {
   460  		t.Fatalf("Bad: %v", dirent)
   461  	}
   462  	if len(dirent.Entries) != 2 {
   463  		t.Fatalf("Bad: %v", dirent.Entries)
   464  	}
   465  	for i := 0; i < len(dirent.Entries); i++ {
   466  		d := dirent.Entries[i]
   467  		switch i {
   468  		case 0:
   469  			if d.Key != "foo" {
   470  				t.Fatalf("bad key")
   471  			}
   472  		case 1:
   473  			if d.Key != "test" {
   474  				t.Fatalf("bad key")
   475  			}
   476  		}
   477  	}
   478  }
   479  
   480  func TestKVSEndpoint_List_ACLEnableKeyListPolicy(t *testing.T) {
   481  	t.Parallel()
   482  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   483  		c.ACLDatacenter = "dc1"
   484  		c.ACLsEnabled = true
   485  		c.ACLMasterToken = "root"
   486  		c.ACLDefaultPolicy = "deny"
   487  		c.ACLEnableKeyListPolicy = true
   488  	})
   489  	defer os.RemoveAll(dir1)
   490  	defer s1.Shutdown()
   491  	codec := rpcClient(t, s1)
   492  	defer codec.Close()
   493  
   494  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   495  
   496  	keys := []string{
   497  		"abe",
   498  		"bar/bar1",
   499  		"bar/bar2",
   500  		"zip",
   501  	}
   502  
   503  	for _, key := range keys {
   504  		arg := structs.KVSRequest{
   505  			Datacenter: "dc1",
   506  			Op:         api.KVSet,
   507  			DirEnt: structs.DirEntry{
   508  				Key:   key,
   509  				Flags: 1,
   510  			},
   511  			WriteRequest: structs.WriteRequest{Token: "root"},
   512  		}
   513  		var out bool
   514  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   515  			t.Fatalf("err: %v", err)
   516  		}
   517  	}
   518  
   519  	//write acl policy that denies recursive reads on ""
   520  	var testListRules1 = `
   521  key "" {
   522  	policy = "deny"
   523  }
   524  key "bar" {
   525  	policy = "list"
   526  }
   527  key "zip" {
   528  	policy = "read"
   529  }
   530  `
   531  
   532  	arg := structs.ACLRequest{
   533  		Datacenter: "dc1",
   534  		Op:         structs.ACLSet,
   535  		ACL: structs.ACL{
   536  			Name:  "User token",
   537  			Type:  structs.ACLTokenTypeClient,
   538  			Rules: testListRules1,
   539  		},
   540  		WriteRequest: structs.WriteRequest{Token: "root"},
   541  	}
   542  	var out string
   543  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil {
   544  		t.Fatalf("err: %v", err)
   545  	}
   546  	id := out
   547  
   548  	//recursive read on empty prefix should fail
   549  	getReq := structs.KeyRequest{
   550  		Datacenter:   "dc1",
   551  		Key:          "",
   552  		QueryOptions: structs.QueryOptions{Token: id},
   553  	}
   554  	var dirent structs.IndexedDirEntries
   555  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getReq, &dirent); !acl.IsErrPermissionDenied(err) {
   556  		t.Fatalf("expected %v but got err: %v", acl.ErrPermissionDenied, err)
   557  	}
   558  
   559  	//listing keys on empty prefix should fail
   560  	getKeysReq := structs.KeyListRequest{
   561  		Datacenter:   "dc1",
   562  		Prefix:       "",
   563  		Seperator:    "/",
   564  		QueryOptions: structs.QueryOptions{Token: id},
   565  	}
   566  	var keyList structs.IndexedKeyList
   567  	if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getKeysReq, &keyList); !acl.IsErrPermissionDenied(err) {
   568  		t.Fatalf("expected %v but got err: %v", acl.ErrPermissionDenied, err)
   569  	}
   570  
   571  	// recursive read with a prefix that has list permissions should succeed
   572  	getReq2 := structs.KeyRequest{
   573  		Datacenter:   "dc1",
   574  		Key:          "bar",
   575  		QueryOptions: structs.QueryOptions{Token: id},
   576  	}
   577  	if err := msgpackrpc.CallWithCodec(codec, "KVS.List", &getReq2, &dirent); err != nil {
   578  		t.Fatalf("err: %v", err)
   579  	}
   580  
   581  	expectedKeys := []string{"bar/bar1", "bar/bar2"}
   582  	var actualKeys []string
   583  	for _, entry := range dirent.Entries {
   584  		actualKeys = append(actualKeys, entry.Key)
   585  	}
   586  
   587  	verify.Values(t, "", actualKeys, expectedKeys)
   588  
   589  	// list keys with a prefix that has list permissions should succeed
   590  	getKeysReq2 := structs.KeyListRequest{
   591  		Datacenter:   "dc1",
   592  		Prefix:       "bar",
   593  		QueryOptions: structs.QueryOptions{Token: id},
   594  	}
   595  	if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getKeysReq2, &keyList); err != nil {
   596  		t.Fatalf("err: %v", err)
   597  	}
   598  
   599  	actualKeys = []string{}
   600  
   601  	for _, key := range keyList.Keys {
   602  		actualKeys = append(actualKeys, key)
   603  	}
   604  
   605  	verify.Values(t, "", actualKeys, expectedKeys)
   606  
   607  }
   608  
   609  func TestKVSEndpoint_ListKeys(t *testing.T) {
   610  	t.Parallel()
   611  	dir1, s1 := testServer(t)
   612  	defer os.RemoveAll(dir1)
   613  	defer s1.Shutdown()
   614  	codec := rpcClient(t, s1)
   615  	defer codec.Close()
   616  
   617  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   618  
   619  	keys := []string{
   620  		"/test/key1",
   621  		"/test/key2",
   622  		"/test/sub/key3",
   623  	}
   624  
   625  	for _, key := range keys {
   626  		arg := structs.KVSRequest{
   627  			Datacenter: "dc1",
   628  			Op:         api.KVSet,
   629  			DirEnt: structs.DirEntry{
   630  				Key:   key,
   631  				Flags: 1,
   632  			},
   633  		}
   634  		var out bool
   635  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   636  			t.Fatalf("err: %v", err)
   637  		}
   638  	}
   639  
   640  	getR := structs.KeyListRequest{
   641  		Datacenter: "dc1",
   642  		Prefix:     "/test/",
   643  		Seperator:  "/",
   644  	}
   645  	var dirent structs.IndexedKeyList
   646  	if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil {
   647  		t.Fatalf("err: %v", err)
   648  	}
   649  
   650  	if dirent.Index == 0 {
   651  		t.Fatalf("Bad: %v", dirent)
   652  	}
   653  	if len(dirent.Keys) != 3 {
   654  		t.Fatalf("Bad: %v", dirent.Keys)
   655  	}
   656  	if dirent.Keys[0] != "/test/key1" {
   657  		t.Fatalf("Bad: %v", dirent.Keys)
   658  	}
   659  	if dirent.Keys[1] != "/test/key2" {
   660  		t.Fatalf("Bad: %v", dirent.Keys)
   661  	}
   662  	if dirent.Keys[2] != "/test/sub/" {
   663  		t.Fatalf("Bad: %v", dirent.Keys)
   664  	}
   665  
   666  	// Try listing a nonexistent prefix
   667  	getR.Prefix = "/nope"
   668  	if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil {
   669  		t.Fatalf("err: %v", err)
   670  	}
   671  	if dirent.Index == 0 {
   672  		t.Fatalf("Bad: %v", dirent)
   673  	}
   674  	if len(dirent.Keys) != 0 {
   675  		t.Fatalf("Bad: %v", dirent.Keys)
   676  	}
   677  }
   678  
   679  func TestKVSEndpoint_ListKeys_ACLDeny(t *testing.T) {
   680  	t.Parallel()
   681  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   682  		c.ACLDatacenter = "dc1"
   683  		c.ACLsEnabled = true
   684  		c.ACLMasterToken = "root"
   685  		c.ACLDefaultPolicy = "deny"
   686  	})
   687  	defer os.RemoveAll(dir1)
   688  	defer s1.Shutdown()
   689  	codec := rpcClient(t, s1)
   690  	defer codec.Close()
   691  
   692  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   693  
   694  	keys := []string{
   695  		"abe",
   696  		"bar",
   697  		"foo",
   698  		"test",
   699  		"zip",
   700  	}
   701  
   702  	for _, key := range keys {
   703  		arg := structs.KVSRequest{
   704  			Datacenter: "dc1",
   705  			Op:         api.KVSet,
   706  			DirEnt: structs.DirEntry{
   707  				Key:   key,
   708  				Flags: 1,
   709  			},
   710  			WriteRequest: structs.WriteRequest{Token: "root"},
   711  		}
   712  		var out bool
   713  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   714  			t.Fatalf("err: %v", err)
   715  		}
   716  	}
   717  
   718  	arg := structs.ACLRequest{
   719  		Datacenter: "dc1",
   720  		Op:         structs.ACLSet,
   721  		ACL: structs.ACL{
   722  			Name:  "User token",
   723  			Type:  structs.ACLTokenTypeClient,
   724  			Rules: testListRules,
   725  		},
   726  		WriteRequest: structs.WriteRequest{Token: "root"},
   727  	}
   728  	var out string
   729  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &arg, &out); err != nil {
   730  		t.Fatalf("err: %v", err)
   731  	}
   732  	id := out
   733  
   734  	getR := structs.KeyListRequest{
   735  		Datacenter:   "dc1",
   736  		Prefix:       "",
   737  		Seperator:    "/",
   738  		QueryOptions: structs.QueryOptions{Token: id},
   739  	}
   740  	var dirent structs.IndexedKeyList
   741  	if err := msgpackrpc.CallWithCodec(codec, "KVS.ListKeys", &getR, &dirent); err != nil {
   742  		t.Fatalf("err: %v", err)
   743  	}
   744  
   745  	if dirent.Index == 0 {
   746  		t.Fatalf("Bad: %v", dirent)
   747  	}
   748  	if len(dirent.Keys) != 2 {
   749  		t.Fatalf("Bad: %v", dirent.Keys)
   750  	}
   751  	if dirent.Keys[0] != "foo" {
   752  		t.Fatalf("Bad: %v", dirent.Keys)
   753  	}
   754  	if dirent.Keys[1] != "test" {
   755  		t.Fatalf("Bad: %v", dirent.Keys)
   756  	}
   757  }
   758  
   759  func TestKVS_Apply_LockDelay(t *testing.T) {
   760  	t.Parallel()
   761  	dir1, s1 := testServer(t)
   762  	defer os.RemoveAll(dir1)
   763  	defer s1.Shutdown()
   764  	codec := rpcClient(t, s1)
   765  	defer codec.Close()
   766  
   767  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   768  
   769  	// Create and invalidate a session with a lock.
   770  	state := s1.fsm.State()
   771  	if err := state.EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil {
   772  		t.Fatalf("err: %v", err)
   773  	}
   774  	session := &structs.Session{
   775  		ID:        generateUUID(),
   776  		Node:      "foo",
   777  		LockDelay: 50 * time.Millisecond,
   778  	}
   779  	if err := state.SessionCreate(2, session); err != nil {
   780  		t.Fatalf("err: %v", err)
   781  	}
   782  	id := session.ID
   783  	d := &structs.DirEntry{
   784  		Key:     "test",
   785  		Session: id,
   786  	}
   787  	if ok, err := state.KVSLock(3, d); err != nil || !ok {
   788  		t.Fatalf("err: %v", err)
   789  	}
   790  	if err := state.SessionDestroy(4, id); err != nil {
   791  		t.Fatalf("err: %v", err)
   792  	}
   793  
   794  	// Make a new session that is valid.
   795  	if err := state.SessionCreate(5, session); err != nil {
   796  		t.Fatalf("err: %v", err)
   797  	}
   798  	validID := session.ID
   799  
   800  	// Make a lock request.
   801  	arg := structs.KVSRequest{
   802  		Datacenter: "dc1",
   803  		Op:         api.KVLock,
   804  		DirEnt: structs.DirEntry{
   805  			Key:     "test",
   806  			Session: validID,
   807  		},
   808  	}
   809  	var out bool
   810  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   811  		t.Fatalf("err: %v", err)
   812  	}
   813  	if out != false {
   814  		t.Fatalf("should not acquire")
   815  	}
   816  
   817  	// Wait for lock-delay.
   818  	time.Sleep(50 * time.Millisecond)
   819  
   820  	// Should acquire.
   821  	if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   822  		t.Fatalf("err: %v", err)
   823  	}
   824  	if out != true {
   825  		t.Fatalf("should acquire")
   826  	}
   827  }
   828  
   829  func TestKVS_Issue_1626(t *testing.T) {
   830  	t.Parallel()
   831  	dir1, s1 := testServer(t)
   832  	defer os.RemoveAll(dir1)
   833  	defer s1.Shutdown()
   834  	codec := rpcClient(t, s1)
   835  	defer codec.Close()
   836  
   837  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   838  
   839  	// Set up the first key.
   840  	{
   841  		arg := structs.KVSRequest{
   842  			Datacenter: "dc1",
   843  			Op:         api.KVSet,
   844  			DirEnt: structs.DirEntry{
   845  				Key:   "foo/test",
   846  				Value: []byte("test"),
   847  			},
   848  		}
   849  		var out bool
   850  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   851  			t.Fatalf("err: %v", err)
   852  		}
   853  	}
   854  
   855  	// Retrieve the base key and snag the index.
   856  	var index uint64
   857  	{
   858  		getR := structs.KeyRequest{
   859  			Datacenter: "dc1",
   860  			Key:        "foo/test",
   861  		}
   862  		var dirent structs.IndexedDirEntries
   863  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil {
   864  			t.Fatalf("err: %v", err)
   865  		}
   866  		if dirent.Index == 0 {
   867  			t.Fatalf("Bad: %v", dirent)
   868  		}
   869  		if len(dirent.Entries) != 1 {
   870  			t.Fatalf("Bad: %v", dirent)
   871  		}
   872  		d := dirent.Entries[0]
   873  		if string(d.Value) != "test" {
   874  			t.Fatalf("bad: %v", d)
   875  		}
   876  
   877  		index = dirent.Index
   878  	}
   879  
   880  	// Set up a blocking query on the base key.
   881  	doneCh := make(chan *structs.IndexedDirEntries, 1)
   882  	go func() {
   883  		codec := rpcClient(t, s1)
   884  		defer codec.Close()
   885  
   886  		getR := structs.KeyRequest{
   887  			Datacenter: "dc1",
   888  			Key:        "foo/test",
   889  			QueryOptions: structs.QueryOptions{
   890  				MinQueryIndex: index,
   891  				MaxQueryTime:  3 * time.Second,
   892  			},
   893  		}
   894  		var dirent structs.IndexedDirEntries
   895  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Get", &getR, &dirent); err != nil {
   896  			t.Fatalf("err: %v", err)
   897  		}
   898  		doneCh <- &dirent
   899  	}()
   900  
   901  	// Now update a second key with a prefix that has the first key name
   902  	// as part of it.
   903  	{
   904  		arg := structs.KVSRequest{
   905  			Datacenter: "dc1",
   906  			Op:         api.KVSet,
   907  			DirEnt: structs.DirEntry{
   908  				Key:   "foo/test2",
   909  				Value: []byte("test"),
   910  			},
   911  		}
   912  		var out bool
   913  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   914  			t.Fatalf("err: %v", err)
   915  		}
   916  	}
   917  
   918  	// Make sure the blocking query didn't wake up for this update.
   919  	select {
   920  	case <-doneCh:
   921  		t.Fatalf("Blocking query should not have completed")
   922  	case <-time.After(1 * time.Second):
   923  	}
   924  
   925  	// Now update the first key's payload.
   926  	{
   927  		arg := structs.KVSRequest{
   928  			Datacenter: "dc1",
   929  			Op:         api.KVSet,
   930  			DirEnt: structs.DirEntry{
   931  				Key:   "foo/test",
   932  				Value: []byte("updated"),
   933  			},
   934  		}
   935  		var out bool
   936  		if err := msgpackrpc.CallWithCodec(codec, "KVS.Apply", &arg, &out); err != nil {
   937  			t.Fatalf("err: %v", err)
   938  		}
   939  	}
   940  
   941  	// Make sure the blocking query wakes up for the final update.
   942  	select {
   943  	case dirent := <-doneCh:
   944  		if dirent.Index <= index {
   945  			t.Fatalf("Bad: %v", dirent)
   946  		}
   947  		if len(dirent.Entries) != 1 {
   948  			t.Fatalf("Bad: %v", dirent)
   949  		}
   950  		d := dirent.Entries[0]
   951  		if string(d.Value) != "updated" {
   952  			t.Fatalf("bad: %v", d)
   953  		}
   954  	case <-time.After(1 * time.Second):
   955  		t.Fatalf("Blocking query should have completed")
   956  	}
   957  }
   958  
   959  var testListRules = `
   960  key "" {
   961  	policy = "deny"
   962  }
   963  key "foo" {
   964  	policy = "read"
   965  }
   966  key "test" {
   967  	policy = "write"
   968  }
   969  key "test/priv" {
   970  	policy = "read"
   971  }
   972  `