github.com/manicqin/nomad@v0.9.5/command/agent/agent_endpoint_test.go (about)

     1  package agent
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"net/url"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	msgpackrpc "github.com/hashicorp/net-rpc-msgpackrpc"
    17  	"github.com/hashicorp/nomad/acl"
    18  	"github.com/hashicorp/nomad/helper"
    19  	"github.com/hashicorp/nomad/helper/pool"
    20  	"github.com/hashicorp/nomad/nomad/mock"
    21  	"github.com/hashicorp/nomad/nomad/structs"
    22  	"github.com/hashicorp/nomad/testutil"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func TestHTTP_AgentSelf(t *testing.T) {
    27  	t.Parallel()
    28  	require := require.New(t)
    29  
    30  	httpTest(t, nil, func(s *TestAgent) {
    31  		// Make the HTTP request
    32  		req, err := http.NewRequest("GET", "/v1/agent/self", nil)
    33  		require.NoError(err)
    34  		respW := httptest.NewRecorder()
    35  
    36  		// Make the request
    37  		obj, err := s.Server.AgentSelfRequest(respW, req)
    38  		require.NoError(err)
    39  
    40  		// Check the job
    41  		self := obj.(agentSelf)
    42  		require.NotNil(self.Config)
    43  		require.NotNil(self.Config.ACL)
    44  		require.NotEmpty(self.Stats)
    45  
    46  		// Check the Vault config
    47  		require.Empty(self.Config.Vault.Token)
    48  
    49  		// Assign a Vault token and require it is redacted.
    50  		s.Config.Vault.Token = "badc0deb-adc0-deba-dc0d-ebadc0debadc"
    51  		respW = httptest.NewRecorder()
    52  		obj, err = s.Server.AgentSelfRequest(respW, req)
    53  		require.NoError(err)
    54  		self = obj.(agentSelf)
    55  		require.Equal("<redacted>", self.Config.Vault.Token)
    56  
    57  		// Assign a ReplicationToken token and require it is redacted.
    58  		s.Config.ACL.ReplicationToken = "badc0deb-adc0-deba-dc0d-ebadc0debadc"
    59  		respW = httptest.NewRecorder()
    60  		obj, err = s.Server.AgentSelfRequest(respW, req)
    61  		require.NoError(err)
    62  		self = obj.(agentSelf)
    63  		require.Equal("<redacted>", self.Config.ACL.ReplicationToken)
    64  
    65  		// Check the Consul config
    66  		require.Empty(self.Config.Consul.Token)
    67  
    68  		// Assign a Consul token and require it is redacted.
    69  		s.Config.Consul.Token = "badc0deb-adc0-deba-dc0d-ebadc0debadc"
    70  		respW = httptest.NewRecorder()
    71  		obj, err = s.Server.AgentSelfRequest(respW, req)
    72  		require.NoError(err)
    73  		self = obj.(agentSelf)
    74  		require.Equal("<redacted>", self.Config.Consul.Token)
    75  
    76  		// Check the Circonus config
    77  		require.Empty(self.Config.Telemetry.CirconusAPIToken)
    78  
    79  		// Assign a Consul token and require it is redacted.
    80  		s.Config.Telemetry.CirconusAPIToken = "badc0deb-adc0-deba-dc0d-ebadc0debadc"
    81  		respW = httptest.NewRecorder()
    82  		obj, err = s.Server.AgentSelfRequest(respW, req)
    83  		require.NoError(err)
    84  		self = obj.(agentSelf)
    85  		require.Equal("<redacted>", self.Config.Telemetry.CirconusAPIToken)
    86  	})
    87  }
    88  
    89  func TestHTTP_AgentSelf_ACL(t *testing.T) {
    90  	t.Parallel()
    91  	require := require.New(t)
    92  
    93  	httpACLTest(t, nil, func(s *TestAgent) {
    94  		state := s.Agent.server.State()
    95  
    96  		// Make the HTTP request
    97  		req, err := http.NewRequest("GET", "/v1/agent/self", nil)
    98  		require.Nil(err)
    99  
   100  		// Try request without a token and expect failure
   101  		{
   102  			respW := httptest.NewRecorder()
   103  			_, err := s.Server.AgentSelfRequest(respW, req)
   104  			require.NotNil(err)
   105  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   106  		}
   107  
   108  		// Try request with an invalid token and expect failure
   109  		{
   110  			respW := httptest.NewRecorder()
   111  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.NodePolicy(acl.PolicyWrite))
   112  			setToken(req, token)
   113  			_, err := s.Server.AgentSelfRequest(respW, req)
   114  			require.NotNil(err)
   115  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   116  		}
   117  
   118  		// Try request with a valid token
   119  		{
   120  			respW := httptest.NewRecorder()
   121  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyWrite))
   122  			setToken(req, token)
   123  			obj, err := s.Server.AgentSelfRequest(respW, req)
   124  			require.Nil(err)
   125  
   126  			self := obj.(agentSelf)
   127  			require.NotNil(self.Config)
   128  			require.NotNil(self.Stats)
   129  		}
   130  
   131  		// Try request with a root token
   132  		{
   133  			respW := httptest.NewRecorder()
   134  			setToken(req, s.RootToken)
   135  			obj, err := s.Server.AgentSelfRequest(respW, req)
   136  			require.Nil(err)
   137  
   138  			self := obj.(agentSelf)
   139  			require.NotNil(self.Config)
   140  			require.NotNil(self.Stats)
   141  		}
   142  	})
   143  }
   144  
   145  func TestHTTP_AgentJoin(t *testing.T) {
   146  	t.Parallel()
   147  	httpTest(t, nil, func(s *TestAgent) {
   148  		// Determine the join address
   149  		member := s.Agent.Server().LocalMember()
   150  		addr := fmt.Sprintf("%s:%d", member.Addr, member.Port)
   151  
   152  		// Make the HTTP request
   153  		req, err := http.NewRequest("PUT",
   154  			fmt.Sprintf("/v1/agent/join?address=%s&address=%s", addr, addr), nil)
   155  		if err != nil {
   156  			t.Fatalf("err: %v", err)
   157  		}
   158  		respW := httptest.NewRecorder()
   159  
   160  		// Make the request
   161  		obj, err := s.Server.AgentJoinRequest(respW, req)
   162  		if err != nil {
   163  			t.Fatalf("err: %v", err)
   164  		}
   165  
   166  		// Check the job
   167  		join := obj.(joinResult)
   168  		if join.NumJoined != 2 {
   169  			t.Fatalf("bad: %#v", join)
   170  		}
   171  		if join.Error != "" {
   172  			t.Fatalf("bad: %#v", join)
   173  		}
   174  	})
   175  }
   176  
   177  func TestHTTP_AgentMembers(t *testing.T) {
   178  	t.Parallel()
   179  	httpTest(t, nil, func(s *TestAgent) {
   180  		// Make the HTTP request
   181  		req, err := http.NewRequest("GET", "/v1/agent/members", nil)
   182  		if err != nil {
   183  			t.Fatalf("err: %v", err)
   184  		}
   185  		respW := httptest.NewRecorder()
   186  
   187  		// Make the request
   188  		obj, err := s.Server.AgentMembersRequest(respW, req)
   189  		if err != nil {
   190  			t.Fatalf("err: %v", err)
   191  		}
   192  
   193  		// Check the job
   194  		members := obj.(structs.ServerMembersResponse)
   195  		if len(members.Members) != 1 {
   196  			t.Fatalf("bad: %#v", members.Members)
   197  		}
   198  	})
   199  }
   200  
   201  func TestHTTP_AgentMembers_ACL(t *testing.T) {
   202  	t.Parallel()
   203  	require := require.New(t)
   204  
   205  	httpACLTest(t, nil, func(s *TestAgent) {
   206  		state := s.Agent.server.State()
   207  
   208  		// Make the HTTP request
   209  		req, err := http.NewRequest("GET", "/v1/agent/members", nil)
   210  		require.Nil(err)
   211  
   212  		// Try request without a token and expect failure
   213  		{
   214  			respW := httptest.NewRecorder()
   215  			_, err := s.Server.AgentMembersRequest(respW, req)
   216  			require.NotNil(err)
   217  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   218  		}
   219  
   220  		// Try request with an invalid token and expect failure
   221  		{
   222  			respW := httptest.NewRecorder()
   223  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.AgentPolicy(acl.PolicyWrite))
   224  			setToken(req, token)
   225  			_, err := s.Server.AgentMembersRequest(respW, req)
   226  			require.NotNil(err)
   227  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   228  		}
   229  
   230  		// Try request with a valid token
   231  		{
   232  			respW := httptest.NewRecorder()
   233  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.NodePolicy(acl.PolicyRead))
   234  			setToken(req, token)
   235  			obj, err := s.Server.AgentMembersRequest(respW, req)
   236  			require.Nil(err)
   237  
   238  			members := obj.(structs.ServerMembersResponse)
   239  			require.Len(members.Members, 1)
   240  		}
   241  
   242  		// Try request with a root token
   243  		{
   244  			respW := httptest.NewRecorder()
   245  			setToken(req, s.RootToken)
   246  			obj, err := s.Server.AgentMembersRequest(respW, req)
   247  			require.Nil(err)
   248  
   249  			members := obj.(structs.ServerMembersResponse)
   250  			require.Len(members.Members, 1)
   251  		}
   252  	})
   253  }
   254  
   255  func TestHTTP_AgentMonitor(t *testing.T) {
   256  	t.Parallel()
   257  
   258  	httpTest(t, nil, func(s *TestAgent) {
   259  		// invalid log_json
   260  		{
   261  			req, err := http.NewRequest("GET", "/v1/agent/monitor?log_json=no", nil)
   262  			require.Nil(t, err)
   263  			resp := newClosableRecorder()
   264  
   265  			// Make the request
   266  			_, err = s.Server.AgentMonitor(resp, req)
   267  			if err.(HTTPCodedError).Code() != 400 {
   268  				t.Fatalf("expected 400 response, got: %v", resp.Code)
   269  			}
   270  		}
   271  
   272  		// unknown log_level
   273  		{
   274  			req, err := http.NewRequest("GET", "/v1/agent/monitor?log_level=unknown", nil)
   275  			require.Nil(t, err)
   276  			resp := newClosableRecorder()
   277  
   278  			// Make the request
   279  			_, err = s.Server.AgentMonitor(resp, req)
   280  			if err.(HTTPCodedError).Code() != 400 {
   281  				t.Fatalf("expected 400 response, got: %v", resp.Code)
   282  			}
   283  		}
   284  
   285  		// check for a specific log
   286  		{
   287  			req, err := http.NewRequest("GET", "/v1/agent/monitor?log_level=warn", nil)
   288  			require.Nil(t, err)
   289  			resp := newClosableRecorder()
   290  			defer resp.Close()
   291  
   292  			go func() {
   293  				_, err = s.Server.AgentMonitor(resp, req)
   294  				require.NoError(t, err)
   295  			}()
   296  
   297  			// send the same log until monitor sink is set up
   298  			maxLogAttempts := 10
   299  			tried := 0
   300  			testutil.WaitForResult(func() (bool, error) {
   301  				if tried < maxLogAttempts {
   302  					s.Server.logger.Warn("log that should be sent")
   303  					tried++
   304  				}
   305  
   306  				got := resp.Body.String()
   307  				want := `{"Data":"`
   308  				if strings.Contains(got, want) {
   309  					return true, nil
   310  				}
   311  
   312  				return false, fmt.Errorf("missing expected log, got: %v, want: %v", got, want)
   313  			}, func(err error) {
   314  				require.Fail(t, err.Error())
   315  			})
   316  		}
   317  
   318  		// plain param set to true
   319  		{
   320  			req, err := http.NewRequest("GET", "/v1/agent/monitor?log_level=debug&plain=true", nil)
   321  			require.Nil(t, err)
   322  			resp := newClosableRecorder()
   323  			defer resp.Close()
   324  
   325  			go func() {
   326  				_, err = s.Server.AgentMonitor(resp, req)
   327  				require.NoError(t, err)
   328  			}()
   329  
   330  			// send the same log until monitor sink is set up
   331  			maxLogAttempts := 10
   332  			tried := 0
   333  			testutil.WaitForResult(func() (bool, error) {
   334  				if tried < maxLogAttempts {
   335  					s.Server.logger.Debug("log that should be sent")
   336  					tried++
   337  				}
   338  
   339  				got := resp.Body.String()
   340  				want := `[DEBUG] http: log that should be sent`
   341  				if strings.Contains(got, want) {
   342  					return true, nil
   343  				}
   344  
   345  				return false, fmt.Errorf("missing expected log, got: %v, want: %v", got, want)
   346  			}, func(err error) {
   347  				require.Fail(t, err.Error())
   348  			})
   349  		}
   350  
   351  		// stream logs for a given node
   352  		{
   353  			req, err := http.NewRequest("GET", "/v1/agent/monitor?log_level=warn&node_id="+s.client.NodeID(), nil)
   354  			require.Nil(t, err)
   355  			resp := newClosableRecorder()
   356  			defer resp.Close()
   357  
   358  			go func() {
   359  				_, err = s.Server.AgentMonitor(resp, req)
   360  				require.NoError(t, err)
   361  			}()
   362  
   363  			// send the same log until monitor sink is set up
   364  			maxLogAttempts := 10
   365  			tried := 0
   366  			out := ""
   367  			testutil.WaitForResult(func() (bool, error) {
   368  				if tried < maxLogAttempts {
   369  					s.Server.logger.Debug("log that should not be sent")
   370  					s.Server.logger.Warn("log that should be sent")
   371  					tried++
   372  				}
   373  				output, err := ioutil.ReadAll(resp.Body)
   374  				if err != nil {
   375  					return false, err
   376  				}
   377  
   378  				out += string(output)
   379  				want := `{"Data":"`
   380  				if strings.Contains(out, want) {
   381  					return true, nil
   382  				}
   383  
   384  				return false, fmt.Errorf("missing expected log, got: %v, want: %v", out, want)
   385  			}, func(err error) {
   386  				require.Fail(t, err.Error())
   387  			})
   388  		}
   389  	})
   390  }
   391  
   392  // Scenarios when Pprof requests should be available
   393  // see https://github.com/hashicorp/nomad/issues/6496
   394  // +---------------+------------------+--------+------------------+
   395  // |   Endpoint    |  `enable_debug`  |  ACLs  |  **Available?**  |
   396  // +---------------+------------------+--------+------------------+
   397  // | /debug/pprof  |  unset           |  n/a   |  no              |
   398  // | /debug/pprof  |  `true`          |  n/a   |  yes             |
   399  // | /debug/pprof  |  `false`         |  n/a   |  no              |
   400  // | /agent/pprof  |  unset           |  off   |  no              |
   401  // | /agent/pprof  |  unset           |  on    |  **yes**         |
   402  // | /agent/pprof  |  `true`          |  off   |  yes             |
   403  // | /agent/pprof  |  `false`         |  on    |  **yes**         |
   404  // +---------------+------------------+--------+------------------+
   405  func TestAgent_PprofRequest_Permissions(t *testing.T) {
   406  	trueP, falseP := helper.BoolToPtr(true), helper.BoolToPtr(false)
   407  	cases := []struct {
   408  		acl   *bool
   409  		debug *bool
   410  		ok    bool
   411  	}{
   412  		// manually set to false because test helpers
   413  		// enable to true by default
   414  		// enableDebug:       helper.BoolToPtr(false),
   415  		{debug: nil, ok: false},
   416  		{debug: trueP, ok: true},
   417  		{debug: falseP, ok: false},
   418  		{debug: falseP, acl: falseP, ok: false},
   419  		{acl: trueP, ok: true},
   420  		{acl: falseP, debug: trueP, ok: true},
   421  		{debug: falseP, acl: trueP, ok: true},
   422  	}
   423  
   424  	for _, tc := range cases {
   425  		ptrToStr := func(val *bool) string {
   426  			if val == nil {
   427  				return "unset"
   428  			} else if *val == true {
   429  				return "true"
   430  			} else {
   431  				return "false"
   432  			}
   433  		}
   434  
   435  		t.Run(
   436  			fmt.Sprintf("debug %s, acl %s",
   437  				ptrToStr(tc.debug),
   438  				ptrToStr(tc.acl)),
   439  			func(t *testing.T) {
   440  				cb := func(c *Config) {
   441  					if tc.acl != nil {
   442  						c.ACL.Enabled = *tc.acl
   443  					}
   444  					if tc.debug == nil {
   445  						var nodebug bool
   446  						c.EnableDebug = nodebug
   447  					} else {
   448  						c.EnableDebug = *tc.debug
   449  					}
   450  				}
   451  
   452  				httpTest(t, cb, func(s *TestAgent) {
   453  					state := s.Agent.server.State()
   454  					url := "/v1/agent/pprof/cmdline"
   455  					req, err := http.NewRequest("GET", url, nil)
   456  					require.NoError(t, err)
   457  					respW := httptest.NewRecorder()
   458  
   459  					if tc.acl != nil && *tc.acl {
   460  						token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyWrite))
   461  						setToken(req, token)
   462  					}
   463  
   464  					resp, err := s.Server.AgentPprofRequest(respW, req)
   465  					if tc.ok {
   466  						require.NoError(t, err)
   467  						require.NotNil(t, resp)
   468  					} else {
   469  						require.Error(t, err)
   470  						require.Equal(t, structs.ErrPermissionDenied.Error(), err.Error())
   471  					}
   472  				})
   473  			})
   474  	}
   475  }
   476  
   477  func TestAgent_PprofRequest(t *testing.T) {
   478  	cases := []struct {
   479  		desc        string
   480  		url         string
   481  		addNodeID   bool
   482  		addServerID bool
   483  		expectedErr string
   484  	}{
   485  		{
   486  			desc: "cmdline local request",
   487  			url:  "/v1/agent/pprof/cmdline",
   488  		},
   489  		{
   490  			desc:      "cmdline node request",
   491  			url:       "/v1/agent/pprof/cmdline",
   492  			addNodeID: true,
   493  		},
   494  		{
   495  			desc:        "cmdline server request",
   496  			url:         "/v1/agent/pprof/cmdline",
   497  			addServerID: true,
   498  		},
   499  		{
   500  			desc:        "invalid server request",
   501  			url:         "/v1/agent/pprof/unknown",
   502  			addServerID: true,
   503  			expectedErr: "RPC Error:: 404,Pprof profile not found profile: unknown",
   504  		},
   505  		{
   506  			desc:      "cpu profile request",
   507  			url:       "/v1/agent/pprof/profile",
   508  			addNodeID: true,
   509  		},
   510  		{
   511  			desc:      "trace request",
   512  			url:       "/v1/agent/pprof/trace",
   513  			addNodeID: true,
   514  		},
   515  		{
   516  			desc:      "pprof lookup request",
   517  			url:       "/v1/agent/pprof/goroutine",
   518  			addNodeID: true,
   519  		},
   520  		{
   521  			desc:        "unknown pprof lookup request",
   522  			url:         "/v1/agent/pprof/latency",
   523  			addNodeID:   true,
   524  			expectedErr: "RPC Error:: 404,Pprof profile not found profile: latency",
   525  		},
   526  	}
   527  
   528  	for _, tc := range cases {
   529  		t.Run(tc.desc, func(t *testing.T) {
   530  			httpTest(t, nil, func(s *TestAgent) {
   531  
   532  				// add node or server id query param
   533  				url := tc.url
   534  				if tc.addNodeID {
   535  					url = url + "?node_id=" + s.client.NodeID()
   536  				} else if tc.addServerID {
   537  					url = url + "?server_id=" + s.server.LocalMember().Name
   538  				}
   539  
   540  				req, err := http.NewRequest("GET", url, nil)
   541  				require.Nil(t, err)
   542  				respW := httptest.NewRecorder()
   543  
   544  				resp, err := s.Server.AgentPprofRequest(respW, req)
   545  
   546  				if tc.expectedErr != "" {
   547  					require.Error(t, err)
   548  					require.EqualError(t, err, tc.expectedErr)
   549  				} else {
   550  					require.NoError(t, err)
   551  					require.NotNil(t, resp)
   552  				}
   553  			})
   554  		})
   555  	}
   556  }
   557  
   558  type closableRecorder struct {
   559  	*httptest.ResponseRecorder
   560  	closer chan bool
   561  }
   562  
   563  func newClosableRecorder() *closableRecorder {
   564  	r := httptest.NewRecorder()
   565  	closer := make(chan bool)
   566  	return &closableRecorder{r, closer}
   567  }
   568  
   569  func (r *closableRecorder) Close() {
   570  	close(r.closer)
   571  }
   572  
   573  func (r *closableRecorder) CloseNotify() <-chan bool {
   574  	return r.closer
   575  }
   576  
   577  func TestHTTP_AgentForceLeave(t *testing.T) {
   578  	t.Parallel()
   579  	httpTest(t, nil, func(s *TestAgent) {
   580  		// Make the HTTP request
   581  		req, err := http.NewRequest("PUT", "/v1/agent/force-leave?node=foo", nil)
   582  		if err != nil {
   583  			t.Fatalf("err: %v", err)
   584  		}
   585  		respW := httptest.NewRecorder()
   586  
   587  		// Make the request
   588  		_, err = s.Server.AgentForceLeaveRequest(respW, req)
   589  		if err != nil {
   590  			t.Fatalf("err: %v", err)
   591  		}
   592  	})
   593  }
   594  
   595  func TestHTTP_AgentForceLeave_ACL(t *testing.T) {
   596  	t.Parallel()
   597  	require := require.New(t)
   598  
   599  	httpACLTest(t, nil, func(s *TestAgent) {
   600  		state := s.Agent.server.State()
   601  
   602  		// Make the HTTP request
   603  		req, err := http.NewRequest("PUT", "/v1/agent/force-leave?node=foo", nil)
   604  		require.Nil(err)
   605  
   606  		// Try request without a token and expect failure
   607  		{
   608  			respW := httptest.NewRecorder()
   609  			_, err := s.Server.AgentForceLeaveRequest(respW, req)
   610  			require.NotNil(err)
   611  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   612  		}
   613  
   614  		// Try request with an invalid token and expect failure
   615  		{
   616  			respW := httptest.NewRecorder()
   617  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.NodePolicy(acl.PolicyRead))
   618  			setToken(req, token)
   619  			_, err := s.Server.AgentForceLeaveRequest(respW, req)
   620  			require.NotNil(err)
   621  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   622  		}
   623  
   624  		// Try request with a valid token
   625  		{
   626  			respW := httptest.NewRecorder()
   627  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyWrite))
   628  			setToken(req, token)
   629  			_, err := s.Server.AgentForceLeaveRequest(respW, req)
   630  			require.Nil(err)
   631  			require.Equal(http.StatusOK, respW.Code)
   632  		}
   633  
   634  		// Try request with a root token
   635  		{
   636  			respW := httptest.NewRecorder()
   637  			setToken(req, s.RootToken)
   638  			_, err := s.Server.AgentForceLeaveRequest(respW, req)
   639  			require.Nil(err)
   640  			require.Equal(http.StatusOK, respW.Code)
   641  		}
   642  	})
   643  }
   644  
   645  func TestHTTP_AgentSetServers(t *testing.T) {
   646  	t.Parallel()
   647  	require := require.New(t)
   648  	httpTest(t, nil, func(s *TestAgent) {
   649  		addr := s.Config.AdvertiseAddrs.RPC
   650  		testutil.WaitForResult(func() (bool, error) {
   651  			conn, err := net.DialTimeout("tcp", addr, 100*time.Millisecond)
   652  			if err != nil {
   653  				return false, err
   654  			}
   655  			defer conn.Close()
   656  
   657  			// Write the Consul RPC byte to set the mode
   658  			if _, err := conn.Write([]byte{byte(pool.RpcNomad)}); err != nil {
   659  				return false, err
   660  			}
   661  
   662  			codec := pool.NewClientCodec(conn)
   663  			args := &structs.GenericRequest{}
   664  			var leader string
   665  			err = msgpackrpc.CallWithCodec(codec, "Status.Leader", args, &leader)
   666  			return leader != "", err
   667  		}, func(err error) {
   668  			t.Fatalf("failed to find leader: %v", err)
   669  		})
   670  
   671  		// Create the request
   672  		req, err := http.NewRequest("PUT", "/v1/agent/servers", nil)
   673  		require.Nil(err)
   674  
   675  		// Send the request
   676  		respW := httptest.NewRecorder()
   677  		_, err = s.Server.AgentServersRequest(respW, req)
   678  		require.NotNil(err)
   679  		require.Contains(err.Error(), "missing server address")
   680  
   681  		// Create a valid request
   682  		req, err = http.NewRequest("PUT", "/v1/agent/servers?address=127.0.0.1%3A4647&address=127.0.0.2%3A4647&address=127.0.0.3%3A4647", nil)
   683  		require.Nil(err)
   684  
   685  		// Send the request which should fail
   686  		respW = httptest.NewRecorder()
   687  		_, err = s.Server.AgentServersRequest(respW, req)
   688  		require.NotNil(err)
   689  
   690  		// Retrieve the servers again
   691  		req, err = http.NewRequest("GET", "/v1/agent/servers", nil)
   692  		require.Nil(err)
   693  		respW = httptest.NewRecorder()
   694  
   695  		// Make the request and check the result
   696  		expected := []string{
   697  			s.GetConfig().AdvertiseAddrs.RPC,
   698  		}
   699  		out, err := s.Server.AgentServersRequest(respW, req)
   700  		require.Nil(err)
   701  		servers := out.([]string)
   702  		require.Len(servers, len(expected))
   703  		require.Equal(expected, servers)
   704  	})
   705  }
   706  
   707  func TestHTTP_AgentSetServers_ACL(t *testing.T) {
   708  	t.Parallel()
   709  	require := require.New(t)
   710  
   711  	httpACLTest(t, nil, func(s *TestAgent) {
   712  		state := s.Agent.server.State()
   713  		addr := s.Config.AdvertiseAddrs.RPC
   714  		testutil.WaitForResult(func() (bool, error) {
   715  			conn, err := net.DialTimeout("tcp", addr, 100*time.Millisecond)
   716  			if err != nil {
   717  				return false, err
   718  			}
   719  			defer conn.Close()
   720  
   721  			// Write the Consul RPC byte to set the mode
   722  			if _, err := conn.Write([]byte{byte(pool.RpcNomad)}); err != nil {
   723  				return false, err
   724  			}
   725  
   726  			codec := pool.NewClientCodec(conn)
   727  			args := &structs.GenericRequest{}
   728  			var leader string
   729  			err = msgpackrpc.CallWithCodec(codec, "Status.Leader", args, &leader)
   730  			return leader != "", err
   731  		}, func(err error) {
   732  			t.Fatalf("failed to find leader: %v", err)
   733  		})
   734  
   735  		// Make the HTTP request
   736  		path := fmt.Sprintf("/v1/agent/servers?address=%s", url.QueryEscape(s.GetConfig().AdvertiseAddrs.RPC))
   737  		req, err := http.NewRequest("PUT", path, nil)
   738  		require.Nil(err)
   739  
   740  		// Try request without a token and expect failure
   741  		{
   742  			respW := httptest.NewRecorder()
   743  			_, err := s.Server.AgentServersRequest(respW, req)
   744  			require.NotNil(err)
   745  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   746  		}
   747  
   748  		// Try request with an invalid token and expect failure
   749  		{
   750  			respW := httptest.NewRecorder()
   751  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.NodePolicy(acl.PolicyRead))
   752  			setToken(req, token)
   753  			_, err := s.Server.AgentServersRequest(respW, req)
   754  			require.NotNil(err)
   755  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   756  		}
   757  
   758  		// Try request with a valid token
   759  		{
   760  			respW := httptest.NewRecorder()
   761  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyWrite))
   762  			setToken(req, token)
   763  			_, err := s.Server.AgentServersRequest(respW, req)
   764  			require.Nil(err)
   765  			require.Equal(http.StatusOK, respW.Code)
   766  		}
   767  
   768  		// Try request with a root token
   769  		{
   770  			respW := httptest.NewRecorder()
   771  			setToken(req, s.RootToken)
   772  			_, err := s.Server.AgentServersRequest(respW, req)
   773  			require.Nil(err)
   774  			require.Equal(http.StatusOK, respW.Code)
   775  		}
   776  	})
   777  }
   778  
   779  func TestHTTP_AgentListServers_ACL(t *testing.T) {
   780  	t.Parallel()
   781  	require := require.New(t)
   782  
   783  	httpACLTest(t, nil, func(s *TestAgent) {
   784  		state := s.Agent.server.State()
   785  
   786  		// Create list request
   787  		req, err := http.NewRequest("GET", "/v1/agent/servers", nil)
   788  		require.Nil(err)
   789  
   790  		expected := []string{
   791  			s.GetConfig().AdvertiseAddrs.RPC,
   792  		}
   793  
   794  		// Try request without a token and expect failure
   795  		{
   796  			respW := httptest.NewRecorder()
   797  			_, err := s.Server.AgentServersRequest(respW, req)
   798  			require.NotNil(err)
   799  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   800  		}
   801  
   802  		// Try request with an invalid token and expect failure
   803  		{
   804  			respW := httptest.NewRecorder()
   805  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.NodePolicy(acl.PolicyRead))
   806  			setToken(req, token)
   807  			_, err := s.Server.AgentServersRequest(respW, req)
   808  			require.NotNil(err)
   809  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   810  		}
   811  
   812  		// Wait for client to have a server
   813  		testutil.WaitForResult(func() (bool, error) {
   814  			return len(s.client.GetServers()) != 0, fmt.Errorf("no servers")
   815  		}, func(err error) {
   816  			t.Fatal(err)
   817  		})
   818  
   819  		// Try request with a valid token
   820  		{
   821  			respW := httptest.NewRecorder()
   822  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyRead))
   823  			setToken(req, token)
   824  			out, err := s.Server.AgentServersRequest(respW, req)
   825  			require.Nil(err)
   826  			servers := out.([]string)
   827  			require.Len(servers, len(expected))
   828  			require.Equal(expected, servers)
   829  		}
   830  
   831  		// Try request with a root token
   832  		{
   833  			respW := httptest.NewRecorder()
   834  			setToken(req, s.RootToken)
   835  			out, err := s.Server.AgentServersRequest(respW, req)
   836  			require.Nil(err)
   837  			servers := out.([]string)
   838  			require.Len(servers, len(expected))
   839  			require.Equal(expected, servers)
   840  		}
   841  	})
   842  }
   843  
   844  func TestHTTP_AgentListKeys(t *testing.T) {
   845  	t.Parallel()
   846  
   847  	key1 := "HS5lJ+XuTlYKWaeGYyG+/A=="
   848  
   849  	httpTest(t, func(c *Config) {
   850  		c.Server.EncryptKey = key1
   851  	}, func(s *TestAgent) {
   852  		req, err := http.NewRequest("GET", "/v1/agent/keyring/list", nil)
   853  		if err != nil {
   854  			t.Fatalf("err: %s", err)
   855  		}
   856  		respW := httptest.NewRecorder()
   857  
   858  		out, err := s.Server.KeyringOperationRequest(respW, req)
   859  		require.Nil(t, err)
   860  		kresp := out.(structs.KeyringResponse)
   861  		require.Len(t, kresp.Keys, 1)
   862  	})
   863  }
   864  
   865  func TestHTTP_AgentListKeys_ACL(t *testing.T) {
   866  	t.Parallel()
   867  	require := require.New(t)
   868  
   869  	key1 := "HS5lJ+XuTlYKWaeGYyG+/A=="
   870  
   871  	cb := func(c *Config) {
   872  		c.Server.EncryptKey = key1
   873  	}
   874  
   875  	httpACLTest(t, cb, func(s *TestAgent) {
   876  		state := s.Agent.server.State()
   877  
   878  		// Make the HTTP request
   879  		req, err := http.NewRequest("GET", "/v1/agent/keyring/list", nil)
   880  		require.Nil(err)
   881  
   882  		// Try request without a token and expect failure
   883  		{
   884  			respW := httptest.NewRecorder()
   885  			_, err := s.Server.KeyringOperationRequest(respW, req)
   886  			require.NotNil(err)
   887  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   888  		}
   889  
   890  		// Try request with an invalid token and expect failure
   891  		{
   892  			respW := httptest.NewRecorder()
   893  			token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.AgentPolicy(acl.PolicyRead))
   894  			setToken(req, token)
   895  			_, err := s.Server.KeyringOperationRequest(respW, req)
   896  			require.NotNil(err)
   897  			require.Equal(err.Error(), structs.ErrPermissionDenied.Error())
   898  		}
   899  
   900  		// Try request with a valid token
   901  		{
   902  			respW := httptest.NewRecorder()
   903  			token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.AgentPolicy(acl.PolicyWrite))
   904  			setToken(req, token)
   905  			out, err := s.Server.KeyringOperationRequest(respW, req)
   906  			require.Nil(err)
   907  			kresp := out.(structs.KeyringResponse)
   908  			require.Len(kresp.Keys, 1)
   909  			require.Contains(kresp.Keys, key1)
   910  		}
   911  
   912  		// Try request with a root token
   913  		{
   914  			respW := httptest.NewRecorder()
   915  			setToken(req, s.RootToken)
   916  			out, err := s.Server.KeyringOperationRequest(respW, req)
   917  			require.Nil(err)
   918  			kresp := out.(structs.KeyringResponse)
   919  			require.Len(kresp.Keys, 1)
   920  			require.Contains(kresp.Keys, key1)
   921  		}
   922  	})
   923  }
   924  
   925  func TestHTTP_AgentInstallKey(t *testing.T) {
   926  	t.Parallel()
   927  
   928  	key1 := "HS5lJ+XuTlYKWaeGYyG+/A=="
   929  	key2 := "wH1Bn9hlJ0emgWB1JttVRA=="
   930  
   931  	httpTest(t, func(c *Config) {
   932  		c.Server.EncryptKey = key1
   933  	}, func(s *TestAgent) {
   934  		b, err := json.Marshal(&structs.KeyringRequest{Key: key2})
   935  		if err != nil {
   936  			t.Fatalf("err: %v", err)
   937  		}
   938  		req, err := http.NewRequest("GET", "/v1/agent/keyring/install", bytes.NewReader(b))
   939  		if err != nil {
   940  			t.Fatalf("err: %s", err)
   941  		}
   942  		respW := httptest.NewRecorder()
   943  
   944  		_, err = s.Server.KeyringOperationRequest(respW, req)
   945  		if err != nil {
   946  			t.Fatalf("err: %s", err)
   947  		}
   948  		req, err = http.NewRequest("GET", "/v1/agent/keyring/list", bytes.NewReader(b))
   949  		if err != nil {
   950  			t.Fatalf("err: %s", err)
   951  		}
   952  		respW = httptest.NewRecorder()
   953  
   954  		out, err := s.Server.KeyringOperationRequest(respW, req)
   955  		if err != nil {
   956  			t.Fatalf("err: %s", err)
   957  		}
   958  		kresp := out.(structs.KeyringResponse)
   959  		if len(kresp.Keys) != 2 {
   960  			t.Fatalf("bad: %v", kresp)
   961  		}
   962  	})
   963  }
   964  
   965  func TestHTTP_AgentRemoveKey(t *testing.T) {
   966  	t.Parallel()
   967  
   968  	key1 := "HS5lJ+XuTlYKWaeGYyG+/A=="
   969  	key2 := "wH1Bn9hlJ0emgWB1JttVRA=="
   970  
   971  	httpTest(t, func(c *Config) {
   972  		c.Server.EncryptKey = key1
   973  	}, func(s *TestAgent) {
   974  		b, err := json.Marshal(&structs.KeyringRequest{Key: key2})
   975  		if err != nil {
   976  			t.Fatalf("err: %v", err)
   977  		}
   978  
   979  		req, err := http.NewRequest("GET", "/v1/agent/keyring/install", bytes.NewReader(b))
   980  		if err != nil {
   981  			t.Fatalf("err: %s", err)
   982  		}
   983  		respW := httptest.NewRecorder()
   984  		_, err = s.Server.KeyringOperationRequest(respW, req)
   985  		if err != nil {
   986  			t.Fatalf("err: %s", err)
   987  		}
   988  
   989  		req, err = http.NewRequest("GET", "/v1/agent/keyring/remove", bytes.NewReader(b))
   990  		if err != nil {
   991  			t.Fatalf("err: %s", err)
   992  		}
   993  		respW = httptest.NewRecorder()
   994  		if _, err = s.Server.KeyringOperationRequest(respW, req); err != nil {
   995  			t.Fatalf("err: %s", err)
   996  		}
   997  
   998  		req, err = http.NewRequest("GET", "/v1/agent/keyring/list", nil)
   999  		if err != nil {
  1000  			t.Fatalf("err: %s", err)
  1001  		}
  1002  		respW = httptest.NewRecorder()
  1003  		out, err := s.Server.KeyringOperationRequest(respW, req)
  1004  		if err != nil {
  1005  			t.Fatalf("err: %s", err)
  1006  		}
  1007  		kresp := out.(structs.KeyringResponse)
  1008  		if len(kresp.Keys) != 1 {
  1009  			t.Fatalf("bad: %v", kresp)
  1010  		}
  1011  	})
  1012  }
  1013  
  1014  func TestHTTP_AgentHealth_Ok(t *testing.T) {
  1015  	t.Parallel()
  1016  	require := require.New(t)
  1017  
  1018  	// Enable ACLs to ensure they're not enforced
  1019  	httpACLTest(t, nil, func(s *TestAgent) {
  1020  		// No ?type=
  1021  		{
  1022  			req, err := http.NewRequest("GET", "/v1/agent/health", nil)
  1023  			require.Nil(err)
  1024  
  1025  			respW := httptest.NewRecorder()
  1026  			healthI, err := s.Server.HealthRequest(respW, req)
  1027  			require.Nil(err)
  1028  			require.Equal(http.StatusOK, respW.Code)
  1029  			require.NotNil(healthI)
  1030  			health := healthI.(*healthResponse)
  1031  			require.NotNil(health.Client)
  1032  			require.True(health.Client.Ok)
  1033  			require.Equal("ok", health.Client.Message)
  1034  			require.NotNil(health.Server)
  1035  			require.True(health.Server.Ok)
  1036  			require.Equal("ok", health.Server.Message)
  1037  		}
  1038  
  1039  		// type=client
  1040  		{
  1041  			req, err := http.NewRequest("GET", "/v1/agent/health?type=client", nil)
  1042  			require.Nil(err)
  1043  
  1044  			respW := httptest.NewRecorder()
  1045  			healthI, err := s.Server.HealthRequest(respW, req)
  1046  			require.Nil(err)
  1047  			require.Equal(http.StatusOK, respW.Code)
  1048  			require.NotNil(healthI)
  1049  			health := healthI.(*healthResponse)
  1050  			require.NotNil(health.Client)
  1051  			require.True(health.Client.Ok)
  1052  			require.Equal("ok", health.Client.Message)
  1053  			require.Nil(health.Server)
  1054  		}
  1055  
  1056  		// type=server
  1057  		{
  1058  			req, err := http.NewRequest("GET", "/v1/agent/health?type=server", nil)
  1059  			require.Nil(err)
  1060  
  1061  			respW := httptest.NewRecorder()
  1062  			healthI, err := s.Server.HealthRequest(respW, req)
  1063  			require.Nil(err)
  1064  			require.Equal(http.StatusOK, respW.Code)
  1065  			require.NotNil(healthI)
  1066  			health := healthI.(*healthResponse)
  1067  			require.NotNil(health.Server)
  1068  			require.True(health.Server.Ok)
  1069  			require.Equal("ok", health.Server.Message)
  1070  			require.Nil(health.Client)
  1071  		}
  1072  
  1073  		// type=client&type=server
  1074  		{
  1075  			req, err := http.NewRequest("GET", "/v1/agent/health?type=client&type=server", nil)
  1076  			require.Nil(err)
  1077  
  1078  			respW := httptest.NewRecorder()
  1079  			healthI, err := s.Server.HealthRequest(respW, req)
  1080  			require.Nil(err)
  1081  			require.Equal(http.StatusOK, respW.Code)
  1082  			require.NotNil(healthI)
  1083  			health := healthI.(*healthResponse)
  1084  			require.NotNil(health.Client)
  1085  			require.True(health.Client.Ok)
  1086  			require.Equal("ok", health.Client.Message)
  1087  			require.NotNil(health.Server)
  1088  			require.True(health.Server.Ok)
  1089  			require.Equal("ok", health.Server.Message)
  1090  		}
  1091  	})
  1092  }
  1093  
  1094  func TestHTTP_AgentHealth_BadServer(t *testing.T) {
  1095  	t.Parallel()
  1096  	require := require.New(t)
  1097  
  1098  	// Enable ACLs to ensure they're not enforced
  1099  	httpACLTest(t, nil, func(s *TestAgent) {
  1100  
  1101  		// Set s.Agent.server=nil to make server unhealthy if requested
  1102  		s.Agent.server = nil
  1103  
  1104  		// No ?type= means server is just skipped
  1105  		{
  1106  			req, err := http.NewRequest("GET", "/v1/agent/health", nil)
  1107  			require.Nil(err)
  1108  
  1109  			respW := httptest.NewRecorder()
  1110  			healthI, err := s.Server.HealthRequest(respW, req)
  1111  			require.Nil(err)
  1112  			require.Equal(http.StatusOK, respW.Code)
  1113  			require.NotNil(healthI)
  1114  			health := healthI.(*healthResponse)
  1115  			require.NotNil(health.Client)
  1116  			require.True(health.Client.Ok)
  1117  			require.Equal("ok", health.Client.Message)
  1118  			require.Nil(health.Server)
  1119  		}
  1120  
  1121  		// type=server means server is considered unhealthy
  1122  		{
  1123  			req, err := http.NewRequest("GET", "/v1/agent/health?type=server", nil)
  1124  			require.Nil(err)
  1125  
  1126  			respW := httptest.NewRecorder()
  1127  			_, err = s.Server.HealthRequest(respW, req)
  1128  			require.NotNil(err)
  1129  			httpErr, ok := err.(HTTPCodedError)
  1130  			require.True(ok)
  1131  			require.Equal(500, httpErr.Code())
  1132  			require.Equal(`{"server":{"ok":false,"message":"server not enabled"}}`, err.Error())
  1133  		}
  1134  	})
  1135  }
  1136  
  1137  func TestHTTP_AgentHealth_BadClient(t *testing.T) {
  1138  	t.Parallel()
  1139  	require := require.New(t)
  1140  
  1141  	// Enable ACLs to ensure they're not enforced
  1142  	httpACLTest(t, nil, func(s *TestAgent) {
  1143  
  1144  		// Set s.Agent.client=nil to make server unhealthy if requested
  1145  		s.Agent.client = nil
  1146  
  1147  		// No ?type= means client is just skipped
  1148  		{
  1149  			req, err := http.NewRequest("GET", "/v1/agent/health", nil)
  1150  			require.Nil(err)
  1151  
  1152  			respW := httptest.NewRecorder()
  1153  			healthI, err := s.Server.HealthRequest(respW, req)
  1154  			require.Nil(err)
  1155  			require.Equal(http.StatusOK, respW.Code)
  1156  			require.NotNil(healthI)
  1157  			health := healthI.(*healthResponse)
  1158  			require.NotNil(health.Server)
  1159  			require.True(health.Server.Ok)
  1160  			require.Equal("ok", health.Server.Message)
  1161  			require.Nil(health.Client)
  1162  		}
  1163  
  1164  		// type=client means client is considered unhealthy
  1165  		{
  1166  			req, err := http.NewRequest("GET", "/v1/agent/health?type=client", nil)
  1167  			require.Nil(err)
  1168  
  1169  			respW := httptest.NewRecorder()
  1170  			_, err = s.Server.HealthRequest(respW, req)
  1171  			require.NotNil(err)
  1172  			httpErr, ok := err.(HTTPCodedError)
  1173  			require.True(ok)
  1174  			require.Equal(500, httpErr.Code())
  1175  			require.Equal(`{"client":{"ok":false,"message":"client not enabled"}}`, err.Error())
  1176  		}
  1177  	})
  1178  }