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 }