github.phpd.cn/hashicorp/consul@v1.4.5/agent/consul/session_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/lib"
    11  	"github.com/hashicorp/consul/testrpc"
    12  	"github.com/hashicorp/net-rpc-msgpackrpc"
    13  )
    14  
    15  func TestSession_Apply(t *testing.T) {
    16  	t.Parallel()
    17  	dir1, s1 := testServer(t)
    18  	defer os.RemoveAll(dir1)
    19  	defer s1.Shutdown()
    20  	codec := rpcClient(t, s1)
    21  	defer codec.Close()
    22  
    23  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    24  
    25  	// Just add a node
    26  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
    27  
    28  	arg := structs.SessionRequest{
    29  		Datacenter: "dc1",
    30  		Op:         structs.SessionCreate,
    31  		Session: structs.Session{
    32  			Node: "foo",
    33  			Name: "my-session",
    34  		},
    35  	}
    36  	var out string
    37  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
    38  		t.Fatalf("err: %v", err)
    39  	}
    40  	id := out
    41  
    42  	// Verify
    43  	state := s1.fsm.State()
    44  	_, s, err := state.SessionGet(nil, out)
    45  	if err != nil {
    46  		t.Fatalf("err: %v", err)
    47  	}
    48  	if s == nil {
    49  		t.Fatalf("should not be nil")
    50  	}
    51  	if s.Node != "foo" {
    52  		t.Fatalf("bad: %v", s)
    53  	}
    54  	if s.Name != "my-session" {
    55  		t.Fatalf("bad: %v", s)
    56  	}
    57  
    58  	// Do a delete
    59  	arg.Op = structs.SessionDestroy
    60  	arg.Session.ID = out
    61  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
    62  		t.Fatalf("err: %v", err)
    63  	}
    64  
    65  	// Verify
    66  	_, s, err = state.SessionGet(nil, id)
    67  	if err != nil {
    68  		t.Fatalf("err: %v", err)
    69  	}
    70  	if s != nil {
    71  		t.Fatalf("bad: %v", s)
    72  	}
    73  }
    74  
    75  func TestSession_DeleteApply(t *testing.T) {
    76  	t.Parallel()
    77  	dir1, s1 := testServer(t)
    78  	defer os.RemoveAll(dir1)
    79  	defer s1.Shutdown()
    80  	codec := rpcClient(t, s1)
    81  	defer codec.Close()
    82  
    83  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
    84  
    85  	// Just add a node
    86  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
    87  
    88  	arg := structs.SessionRequest{
    89  		Datacenter: "dc1",
    90  		Op:         structs.SessionCreate,
    91  		Session: structs.Session{
    92  			Node:     "foo",
    93  			Name:     "my-session",
    94  			Behavior: structs.SessionKeysDelete,
    95  		},
    96  	}
    97  	var out string
    98  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
    99  		t.Fatalf("err: %v", err)
   100  	}
   101  	id := out
   102  
   103  	// Verify
   104  	state := s1.fsm.State()
   105  	_, s, err := state.SessionGet(nil, out)
   106  	if err != nil {
   107  		t.Fatalf("err: %v", err)
   108  	}
   109  	if s == nil {
   110  		t.Fatalf("should not be nil")
   111  	}
   112  	if s.Node != "foo" {
   113  		t.Fatalf("bad: %v", s)
   114  	}
   115  	if s.Name != "my-session" {
   116  		t.Fatalf("bad: %v", s)
   117  	}
   118  	if s.Behavior != structs.SessionKeysDelete {
   119  		t.Fatalf("bad: %v", s)
   120  	}
   121  
   122  	// Do a delete
   123  	arg.Op = structs.SessionDestroy
   124  	arg.Session.ID = out
   125  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   126  		t.Fatalf("err: %v", err)
   127  	}
   128  
   129  	// Verify
   130  	_, s, err = state.SessionGet(nil, id)
   131  	if err != nil {
   132  		t.Fatalf("err: %v", err)
   133  	}
   134  	if s != nil {
   135  		t.Fatalf("bad: %v", s)
   136  	}
   137  }
   138  
   139  func TestSession_Apply_ACLDeny(t *testing.T) {
   140  	t.Parallel()
   141  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   142  		c.ACLDatacenter = "dc1"
   143  		c.ACLsEnabled = true
   144  		c.ACLMasterToken = "root"
   145  		c.ACLDefaultPolicy = "deny"
   146  		c.ACLEnforceVersion8 = false
   147  	})
   148  	defer os.RemoveAll(dir1)
   149  	defer s1.Shutdown()
   150  	codec := rpcClient(t, s1)
   151  	defer codec.Close()
   152  
   153  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   154  
   155  	// Create the ACL.
   156  	req := structs.ACLRequest{
   157  		Datacenter: "dc1",
   158  		Op:         structs.ACLSet,
   159  		ACL: structs.ACL{
   160  			Name: "User token",
   161  			Type: structs.ACLTokenTypeClient,
   162  			Rules: `
   163  session "foo" {
   164  	policy = "write"
   165  }
   166  `,
   167  		},
   168  		WriteRequest: structs.WriteRequest{Token: "root"},
   169  	}
   170  
   171  	var token string
   172  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &req, &token); err != nil {
   173  		t.Fatalf("err: %v", err)
   174  	}
   175  
   176  	// Just add a node.
   177  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   178  
   179  	// Try to create without a token, which will go through since version 8
   180  	// enforcement isn't enabled.
   181  	arg := structs.SessionRequest{
   182  		Datacenter: "dc1",
   183  		Op:         structs.SessionCreate,
   184  		Session: structs.Session{
   185  			Node: "foo",
   186  			Name: "my-session",
   187  		},
   188  	}
   189  	var id1 string
   190  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &id1); err != nil {
   191  		t.Fatalf("err: %v", err)
   192  	}
   193  
   194  	// Now turn on version 8 enforcement and try again, it should be denied.
   195  	var id2 string
   196  	s1.config.ACLEnforceVersion8 = true
   197  	err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &id2)
   198  	if !acl.IsErrPermissionDenied(err) {
   199  		t.Fatalf("err: %v", err)
   200  	}
   201  
   202  	// Now set a token and try again. This should go through.
   203  	arg.Token = token
   204  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &id2); err != nil {
   205  		t.Fatalf("err: %v", err)
   206  	}
   207  
   208  	// Do a delete on the first session with version 8 enforcement off and
   209  	// no token. This should go through.
   210  	var out string
   211  	s1.config.ACLEnforceVersion8 = false
   212  	arg.Op = structs.SessionDestroy
   213  	arg.Token = ""
   214  	arg.Session.ID = id1
   215  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   216  		t.Fatalf("err: %v", err)
   217  	}
   218  
   219  	// Turn on version 8 enforcement and make sure the delete of the second
   220  	// session fails.
   221  	s1.config.ACLEnforceVersion8 = true
   222  	arg.Session.ID = id2
   223  	err = msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out)
   224  	if !acl.IsErrPermissionDenied(err) {
   225  		t.Fatalf("err: %v", err)
   226  	}
   227  
   228  	// Now set a token and try again. This should go through.
   229  	arg.Token = token
   230  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   231  		t.Fatalf("err: %v", err)
   232  	}
   233  }
   234  
   235  func TestSession_Get(t *testing.T) {
   236  	t.Parallel()
   237  	dir1, s1 := testServer(t)
   238  	defer os.RemoveAll(dir1)
   239  	defer s1.Shutdown()
   240  	codec := rpcClient(t, s1)
   241  	defer codec.Close()
   242  
   243  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   244  
   245  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   246  	arg := structs.SessionRequest{
   247  		Datacenter: "dc1",
   248  		Op:         structs.SessionCreate,
   249  		Session: structs.Session{
   250  			Node: "foo",
   251  		},
   252  	}
   253  	var out string
   254  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   255  		t.Fatalf("err: %v", err)
   256  	}
   257  
   258  	getR := structs.SessionSpecificRequest{
   259  		Datacenter: "dc1",
   260  		Session:    out,
   261  	}
   262  	var sessions structs.IndexedSessions
   263  	if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil {
   264  		t.Fatalf("err: %v", err)
   265  	}
   266  
   267  	if sessions.Index == 0 {
   268  		t.Fatalf("Bad: %v", sessions)
   269  	}
   270  	if len(sessions.Sessions) != 1 {
   271  		t.Fatalf("Bad: %v", sessions)
   272  	}
   273  	s := sessions.Sessions[0]
   274  	if s.ID != out {
   275  		t.Fatalf("bad: %v", s)
   276  	}
   277  }
   278  
   279  func TestSession_List(t *testing.T) {
   280  	t.Parallel()
   281  	dir1, s1 := testServer(t)
   282  	defer os.RemoveAll(dir1)
   283  	defer s1.Shutdown()
   284  	codec := rpcClient(t, s1)
   285  	defer codec.Close()
   286  
   287  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   288  
   289  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   290  	ids := []string{}
   291  	for i := 0; i < 5; i++ {
   292  		arg := structs.SessionRequest{
   293  			Datacenter: "dc1",
   294  			Op:         structs.SessionCreate,
   295  			Session: structs.Session{
   296  				Node: "foo",
   297  			},
   298  		}
   299  		var out string
   300  		if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   301  			t.Fatalf("err: %v", err)
   302  		}
   303  		ids = append(ids, out)
   304  	}
   305  
   306  	getR := structs.DCSpecificRequest{
   307  		Datacenter: "dc1",
   308  	}
   309  	var sessions structs.IndexedSessions
   310  	if err := msgpackrpc.CallWithCodec(codec, "Session.List", &getR, &sessions); err != nil {
   311  		t.Fatalf("err: %v", err)
   312  	}
   313  
   314  	if sessions.Index == 0 {
   315  		t.Fatalf("Bad: %v", sessions)
   316  	}
   317  	if len(sessions.Sessions) != 5 {
   318  		t.Fatalf("Bad: %v", sessions.Sessions)
   319  	}
   320  	for i := 0; i < len(sessions.Sessions); i++ {
   321  		s := sessions.Sessions[i]
   322  		if !lib.StrContains(ids, s.ID) {
   323  			t.Fatalf("bad: %v", s)
   324  		}
   325  		if s.Node != "foo" {
   326  			t.Fatalf("bad: %v", s)
   327  		}
   328  	}
   329  }
   330  
   331  func TestSession_Get_List_NodeSessions_ACLFilter(t *testing.T) {
   332  	t.Parallel()
   333  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   334  		c.ACLDatacenter = "dc1"
   335  		c.ACLsEnabled = true
   336  		c.ACLMasterToken = "root"
   337  		c.ACLDefaultPolicy = "deny"
   338  		c.ACLEnforceVersion8 = false
   339  	})
   340  	defer os.RemoveAll(dir1)
   341  	defer s1.Shutdown()
   342  	codec := rpcClient(t, s1)
   343  	defer codec.Close()
   344  
   345  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   346  
   347  	// Create the ACL.
   348  	req := structs.ACLRequest{
   349  		Datacenter: "dc1",
   350  		Op:         structs.ACLSet,
   351  		ACL: structs.ACL{
   352  			Name: "User token",
   353  			Type: structs.ACLTokenTypeClient,
   354  			Rules: `
   355  session "foo" {
   356  	policy = "read"
   357  }
   358  `,
   359  		},
   360  		WriteRequest: structs.WriteRequest{Token: "root"},
   361  	}
   362  
   363  	var token string
   364  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &req, &token); err != nil {
   365  		t.Fatalf("err: %v", err)
   366  	}
   367  
   368  	// Create a node and a session.
   369  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   370  	arg := structs.SessionRequest{
   371  		Datacenter: "dc1",
   372  		Op:         structs.SessionCreate,
   373  		Session: structs.Session{
   374  			Node: "foo",
   375  		},
   376  		WriteRequest: structs.WriteRequest{Token: "root"},
   377  	}
   378  	var out string
   379  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   380  		t.Fatalf("err: %v", err)
   381  	}
   382  
   383  	// Perform all the read operations, which should go through since version
   384  	// 8 ACL enforcement isn't enabled.
   385  	getR := structs.SessionSpecificRequest{
   386  		Datacenter: "dc1",
   387  		Session:    out,
   388  	}
   389  	{
   390  		var sessions structs.IndexedSessions
   391  		if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil {
   392  			t.Fatalf("err: %v", err)
   393  		}
   394  		if len(sessions.Sessions) != 1 {
   395  			t.Fatalf("bad: %v", sessions.Sessions)
   396  		}
   397  	}
   398  	listR := structs.DCSpecificRequest{
   399  		Datacenter: "dc1",
   400  	}
   401  	{
   402  		var sessions structs.IndexedSessions
   403  		if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil {
   404  			t.Fatalf("err: %v", err)
   405  		}
   406  		if len(sessions.Sessions) != 1 {
   407  			t.Fatalf("bad: %v", sessions.Sessions)
   408  		}
   409  	}
   410  	nodeR := structs.NodeSpecificRequest{
   411  		Datacenter: "dc1",
   412  		Node:       "foo",
   413  	}
   414  	{
   415  		var sessions structs.IndexedSessions
   416  		if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil {
   417  			t.Fatalf("err: %v", err)
   418  		}
   419  		if len(sessions.Sessions) != 1 {
   420  			t.Fatalf("bad: %v", sessions.Sessions)
   421  		}
   422  	}
   423  
   424  	// Now turn on version 8 enforcement and make sure everything is empty.
   425  	s1.config.ACLEnforceVersion8 = true
   426  	{
   427  		var sessions structs.IndexedSessions
   428  		if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil {
   429  			t.Fatalf("err: %v", err)
   430  		}
   431  		if len(sessions.Sessions) != 0 {
   432  			t.Fatalf("bad: %v", sessions.Sessions)
   433  		}
   434  	}
   435  	{
   436  		var sessions structs.IndexedSessions
   437  
   438  		if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil {
   439  			t.Fatalf("err: %v", err)
   440  		}
   441  		if len(sessions.Sessions) != 0 {
   442  			t.Fatalf("bad: %v", sessions.Sessions)
   443  		}
   444  	}
   445  	{
   446  		var sessions structs.IndexedSessions
   447  		if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil {
   448  			t.Fatalf("err: %v", err)
   449  		}
   450  		if len(sessions.Sessions) != 0 {
   451  			t.Fatalf("bad: %v", sessions.Sessions)
   452  		}
   453  	}
   454  
   455  	// Finally, supply the token and make sure the reads are allowed.
   456  	getR.Token = token
   457  	{
   458  		var sessions structs.IndexedSessions
   459  		if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil {
   460  			t.Fatalf("err: %v", err)
   461  		}
   462  		if len(sessions.Sessions) != 1 {
   463  			t.Fatalf("bad: %v", sessions.Sessions)
   464  		}
   465  	}
   466  	listR.Token = token
   467  	{
   468  		var sessions structs.IndexedSessions
   469  		if err := msgpackrpc.CallWithCodec(codec, "Session.List", &listR, &sessions); err != nil {
   470  			t.Fatalf("err: %v", err)
   471  		}
   472  		if len(sessions.Sessions) != 1 {
   473  			t.Fatalf("bad: %v", sessions.Sessions)
   474  		}
   475  	}
   476  	nodeR.Token = token
   477  	{
   478  		var sessions structs.IndexedSessions
   479  		if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &nodeR, &sessions); err != nil {
   480  			t.Fatalf("err: %v", err)
   481  		}
   482  		if len(sessions.Sessions) != 1 {
   483  			t.Fatalf("bad: %v", sessions.Sessions)
   484  		}
   485  	}
   486  
   487  	// Try to get a session that doesn't exist to make sure that's handled
   488  	// correctly by the filter (it will get passed a nil slice).
   489  	getR.Session = "adf4238a-882b-9ddc-4a9d-5b6758e4159e"
   490  	{
   491  		var sessions structs.IndexedSessions
   492  		if err := msgpackrpc.CallWithCodec(codec, "Session.Get", &getR, &sessions); err != nil {
   493  			t.Fatalf("err: %v", err)
   494  		}
   495  		if len(sessions.Sessions) != 0 {
   496  			t.Fatalf("bad: %v", sessions.Sessions)
   497  		}
   498  	}
   499  }
   500  
   501  func TestSession_ApplyTimers(t *testing.T) {
   502  	t.Parallel()
   503  	dir1, s1 := testServer(t)
   504  	defer os.RemoveAll(dir1)
   505  	defer s1.Shutdown()
   506  	testrpc.WaitForTestAgent(t, s1.RPC, "dc1")
   507  	codec := rpcClient(t, s1)
   508  	defer codec.Close()
   509  
   510  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   511  	arg := structs.SessionRequest{
   512  		Datacenter: "dc1",
   513  		Op:         structs.SessionCreate,
   514  		Session: structs.Session{
   515  			Node: "foo",
   516  			TTL:  "10s",
   517  		},
   518  	}
   519  	var out string
   520  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   521  		t.Fatalf("err: %v", err)
   522  	}
   523  
   524  	// Check the session map
   525  	if s1.sessionTimers.Get(out) == nil {
   526  		t.Fatalf("missing session timer")
   527  	}
   528  
   529  	// Destroy the session
   530  	arg.Op = structs.SessionDestroy
   531  	arg.Session.ID = out
   532  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   533  		t.Fatalf("err: %v", err)
   534  	}
   535  
   536  	// Check the session map
   537  	if s1.sessionTimers.Get(out) != nil {
   538  		t.Fatalf("session timer exists")
   539  	}
   540  }
   541  
   542  func TestSession_Renew(t *testing.T) {
   543  	// This method is timing sensitive, disable Parallel
   544  	//t.Parallel()
   545  	ttl := 1 * time.Second
   546  	TTL := ttl.String()
   547  
   548  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   549  		c.SessionTTLMin = ttl
   550  	})
   551  	defer os.RemoveAll(dir1)
   552  	defer s1.Shutdown()
   553  	testrpc.WaitForTestAgent(t, s1.RPC, "dc1")
   554  	codec := rpcClient(t, s1)
   555  	defer codec.Close()
   556  
   557  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   558  	ids := []string{}
   559  	for i := 0; i < 5; i++ {
   560  		arg := structs.SessionRequest{
   561  			Datacenter: "dc1",
   562  			Op:         structs.SessionCreate,
   563  			Session: structs.Session{
   564  				Node: "foo",
   565  				TTL:  TTL,
   566  			},
   567  		}
   568  		var out string
   569  		if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   570  			t.Fatalf("err: %v", err)
   571  		}
   572  		ids = append(ids, out)
   573  	}
   574  
   575  	// Verify the timer map is setup
   576  	if s1.sessionTimers.Len() != 5 {
   577  		t.Fatalf("missing session timers")
   578  	}
   579  
   580  	getR := structs.DCSpecificRequest{
   581  		Datacenter: "dc1",
   582  	}
   583  
   584  	var sessions structs.IndexedSessions
   585  	if err := msgpackrpc.CallWithCodec(codec, "Session.List", &getR, &sessions); err != nil {
   586  		t.Fatalf("err: %v", err)
   587  	}
   588  
   589  	if sessions.Index == 0 {
   590  		t.Fatalf("Bad: %v", sessions)
   591  	}
   592  	if len(sessions.Sessions) != 5 {
   593  		t.Fatalf("Bad: %v", sessions.Sessions)
   594  	}
   595  	for i := 0; i < len(sessions.Sessions); i++ {
   596  		s := sessions.Sessions[i]
   597  		if !lib.StrContains(ids, s.ID) {
   598  			t.Fatalf("bad: %v", s)
   599  		}
   600  		if s.Node != "foo" {
   601  			t.Fatalf("bad: %v", s)
   602  		}
   603  		if s.TTL != TTL {
   604  			t.Fatalf("bad session TTL: %s %v", s.TTL, s)
   605  		}
   606  		t.Logf("Created session '%s'", s.ID)
   607  	}
   608  
   609  	// Sleep for time shorter than internal destroy ttl
   610  	time.Sleep(ttl * structs.SessionTTLMultiplier / 2)
   611  
   612  	// renew 3 out of 5 sessions
   613  	for i := 0; i < 3; i++ {
   614  		renewR := structs.SessionSpecificRequest{
   615  			Datacenter: "dc1",
   616  			Session:    ids[i],
   617  		}
   618  		var session structs.IndexedSessions
   619  		if err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session); err != nil {
   620  			t.Fatalf("err: %v", err)
   621  		}
   622  
   623  		if session.Index == 0 {
   624  			t.Fatalf("Bad: %v", session)
   625  		}
   626  		if len(session.Sessions) != 1 {
   627  			t.Fatalf("Bad: %v", session.Sessions)
   628  		}
   629  
   630  		s := session.Sessions[0]
   631  		if !lib.StrContains(ids, s.ID) {
   632  			t.Fatalf("bad: %v", s)
   633  		}
   634  		if s.Node != "foo" {
   635  			t.Fatalf("bad: %v", s)
   636  		}
   637  
   638  		t.Logf("Renewed session '%s'", s.ID)
   639  	}
   640  
   641  	// now sleep for 2/3 the internal destroy TTL time for renewed sessions
   642  	// which is more than the internal destroy TTL time for the non-renewed sessions
   643  	time.Sleep((ttl * structs.SessionTTLMultiplier) * 2.0 / 3.0)
   644  
   645  	var sessionsL1 structs.IndexedSessions
   646  	if err := msgpackrpc.CallWithCodec(codec, "Session.List", &getR, &sessionsL1); err != nil {
   647  		t.Fatalf("err: %v", err)
   648  	}
   649  
   650  	if sessionsL1.Index == 0 {
   651  		t.Fatalf("Bad: %v", sessionsL1)
   652  	}
   653  
   654  	t.Logf("Expect 2 sessions to be destroyed")
   655  
   656  	for i := 0; i < len(sessionsL1.Sessions); i++ {
   657  		s := sessionsL1.Sessions[i]
   658  		if !lib.StrContains(ids, s.ID) {
   659  			t.Fatalf("bad: %v", s)
   660  		}
   661  		if s.Node != "foo" {
   662  			t.Fatalf("bad: %v", s)
   663  		}
   664  		if s.TTL != TTL {
   665  			t.Fatalf("bad: %v", s)
   666  		}
   667  		if i > 2 {
   668  			t.Errorf("session '%s' should be destroyed", s.ID)
   669  		}
   670  	}
   671  
   672  	if len(sessionsL1.Sessions) != 3 {
   673  		t.Fatalf("Bad: %v", sessionsL1.Sessions)
   674  	}
   675  
   676  	// now sleep again for ttl*2 - no sessions should still be alive
   677  	time.Sleep(ttl * structs.SessionTTLMultiplier)
   678  
   679  	var sessionsL2 structs.IndexedSessions
   680  	if err := msgpackrpc.CallWithCodec(codec, "Session.List", &getR, &sessionsL2); err != nil {
   681  		t.Fatalf("err: %v", err)
   682  	}
   683  
   684  	if sessionsL2.Index == 0 {
   685  		t.Fatalf("Bad: %v", sessionsL2)
   686  	}
   687  	if len(sessionsL2.Sessions) != 0 {
   688  		for i := 0; i < len(sessionsL2.Sessions); i++ {
   689  			s := sessionsL2.Sessions[i]
   690  			if !lib.StrContains(ids, s.ID) {
   691  				t.Fatalf("bad: %v", s)
   692  			}
   693  			if s.Node != "foo" {
   694  				t.Fatalf("bad: %v", s)
   695  			}
   696  			if s.TTL != TTL {
   697  				t.Fatalf("bad: %v", s)
   698  			}
   699  			t.Errorf("session '%s' should be destroyed", s.ID)
   700  		}
   701  
   702  		t.Fatalf("Bad: %v", sessionsL2.Sessions)
   703  	}
   704  }
   705  
   706  func TestSession_Renew_ACLDeny(t *testing.T) {
   707  	t.Parallel()
   708  	dir1, s1 := testServerWithConfig(t, func(c *Config) {
   709  		c.ACLDatacenter = "dc1"
   710  		c.ACLsEnabled = true
   711  		c.ACLMasterToken = "root"
   712  		c.ACLDefaultPolicy = "deny"
   713  		c.ACLEnforceVersion8 = false
   714  	})
   715  	defer os.RemoveAll(dir1)
   716  	defer s1.Shutdown()
   717  	testrpc.WaitForTestAgent(t, s1.RPC, "dc1")
   718  	codec := rpcClient(t, s1)
   719  	defer codec.Close()
   720  
   721  	// Create the ACL.
   722  	req := structs.ACLRequest{
   723  		Datacenter: "dc1",
   724  		Op:         structs.ACLSet,
   725  		ACL: structs.ACL{
   726  			Name: "User token",
   727  			Type: structs.ACLTokenTypeClient,
   728  			Rules: `
   729  session "foo" {
   730  	policy = "write"
   731  }
   732  `,
   733  		},
   734  		WriteRequest: structs.WriteRequest{Token: "root"},
   735  	}
   736  
   737  	var token string
   738  	if err := msgpackrpc.CallWithCodec(codec, "ACL.Apply", &req, &token); err != nil {
   739  		t.Fatalf("err: %v", err)
   740  	}
   741  
   742  	// Just add a node.
   743  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   744  
   745  	// Create a session. The token won't matter here since we don't have
   746  	// version 8 ACL enforcement on yet.
   747  	arg := structs.SessionRequest{
   748  		Datacenter: "dc1",
   749  		Op:         structs.SessionCreate,
   750  		Session: structs.Session{
   751  			Node: "foo",
   752  			Name: "my-session",
   753  		},
   754  	}
   755  	var id string
   756  	if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &id); err != nil {
   757  		t.Fatalf("err: %v", err)
   758  	}
   759  
   760  	// Renew without a token should go through without version 8 ACL
   761  	// enforcement.
   762  	renewR := structs.SessionSpecificRequest{
   763  		Datacenter: "dc1",
   764  		Session:    id,
   765  	}
   766  	var session structs.IndexedSessions
   767  	if err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session); err != nil {
   768  		t.Fatalf("err: %v", err)
   769  	}
   770  
   771  	// Now turn on version 8 enforcement and the renew should be rejected.
   772  	s1.config.ACLEnforceVersion8 = true
   773  	err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session)
   774  	if !acl.IsErrPermissionDenied(err) {
   775  		t.Fatalf("err: %v", err)
   776  	}
   777  
   778  	// Set the token and it should go through.
   779  	renewR.Token = token
   780  	if err := msgpackrpc.CallWithCodec(codec, "Session.Renew", &renewR, &session); err != nil {
   781  		t.Fatalf("err: %v", err)
   782  	}
   783  }
   784  
   785  func TestSession_NodeSessions(t *testing.T) {
   786  	t.Parallel()
   787  	dir1, s1 := testServer(t)
   788  	defer os.RemoveAll(dir1)
   789  	defer s1.Shutdown()
   790  	codec := rpcClient(t, s1)
   791  	defer codec.Close()
   792  
   793  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   794  
   795  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "foo", Address: "127.0.0.1"})
   796  	s1.fsm.State().EnsureNode(1, &structs.Node{Node: "bar", Address: "127.0.0.1"})
   797  	ids := []string{}
   798  	for i := 0; i < 10; i++ {
   799  		arg := structs.SessionRequest{
   800  			Datacenter: "dc1",
   801  			Op:         structs.SessionCreate,
   802  			Session: structs.Session{
   803  				Node: "bar",
   804  			},
   805  		}
   806  		if i < 5 {
   807  			arg.Session.Node = "foo"
   808  		}
   809  		var out string
   810  		if err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out); err != nil {
   811  			t.Fatalf("err: %v", err)
   812  		}
   813  		if i < 5 {
   814  			ids = append(ids, out)
   815  		}
   816  	}
   817  
   818  	getR := structs.NodeSpecificRequest{
   819  		Datacenter: "dc1",
   820  		Node:       "foo",
   821  	}
   822  	var sessions structs.IndexedSessions
   823  	if err := msgpackrpc.CallWithCodec(codec, "Session.NodeSessions", &getR, &sessions); err != nil {
   824  		t.Fatalf("err: %v", err)
   825  	}
   826  
   827  	if sessions.Index == 0 {
   828  		t.Fatalf("Bad: %v", sessions)
   829  	}
   830  	if len(sessions.Sessions) != 5 {
   831  		t.Fatalf("Bad: %v", sessions.Sessions)
   832  	}
   833  	for i := 0; i < len(sessions.Sessions); i++ {
   834  		s := sessions.Sessions[i]
   835  		if !lib.StrContains(ids, s.ID) {
   836  			t.Fatalf("bad: %v", s)
   837  		}
   838  		if s.Node != "foo" {
   839  			t.Fatalf("bad: %v", s)
   840  		}
   841  	}
   842  }
   843  
   844  func TestSession_Apply_BadTTL(t *testing.T) {
   845  	t.Parallel()
   846  	dir1, s1 := testServer(t)
   847  	defer os.RemoveAll(dir1)
   848  	defer s1.Shutdown()
   849  	codec := rpcClient(t, s1)
   850  	defer codec.Close()
   851  
   852  	testrpc.WaitForLeader(t, s1.RPC, "dc1")
   853  
   854  	arg := structs.SessionRequest{
   855  		Datacenter: "dc1",
   856  		Op:         structs.SessionCreate,
   857  		Session: structs.Session{
   858  			Node: "foo",
   859  			Name: "my-session",
   860  		},
   861  	}
   862  
   863  	// Session with illegal TTL
   864  	arg.Session.TTL = "10z"
   865  
   866  	var out string
   867  	err := msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out)
   868  	if err == nil {
   869  		t.Fatal("expected error")
   870  	}
   871  	if err.Error() != "Session TTL '10z' invalid: time: unknown unit z in duration 10z" {
   872  		t.Fatalf("incorrect error message: %s", err.Error())
   873  	}
   874  
   875  	// less than SessionTTLMin
   876  	arg.Session.TTL = "5s"
   877  
   878  	err = msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out)
   879  	if err == nil {
   880  		t.Fatal("expected error")
   881  	}
   882  	if err.Error() != "Invalid Session TTL '5000000000', must be between [10s=24h0m0s]" {
   883  		t.Fatalf("incorrect error message: %s", err.Error())
   884  	}
   885  
   886  	// more than SessionTTLMax
   887  	arg.Session.TTL = "100000s"
   888  
   889  	err = msgpackrpc.CallWithCodec(codec, "Session.Apply", &arg, &out)
   890  	if err == nil {
   891  		t.Fatal("expected error")
   892  	}
   893  	if err.Error() != "Invalid Session TTL '100000000000000', must be between [10s=24h0m0s]" {
   894  		t.Fatalf("incorrect error message: %s", err.Error())
   895  	}
   896  }