github.com/bigcommerce/nomad@v0.9.3-bc/command/agent/agent_test.go (about) 1 package agent 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 "time" 10 11 cstructs "github.com/hashicorp/nomad/client/structs" 12 "github.com/hashicorp/nomad/helper" 13 "github.com/hashicorp/nomad/helper/testlog" 14 "github.com/hashicorp/nomad/nomad/structs" 15 sconfig "github.com/hashicorp/nomad/nomad/structs/config" 16 "github.com/stretchr/testify/assert" 17 "github.com/stretchr/testify/require" 18 ) 19 20 func tmpDir(t testing.TB) string { 21 dir, err := ioutil.TempDir("", "nomad") 22 if err != nil { 23 t.Fatalf("err: %v", err) 24 } 25 return dir 26 } 27 28 func TestAgent_RPC_Ping(t *testing.T) { 29 t.Parallel() 30 agent := NewTestAgent(t, t.Name(), nil) 31 defer agent.Shutdown() 32 33 var out struct{} 34 if err := agent.RPC("Status.Ping", struct{}{}, &out); err != nil { 35 t.Fatalf("err: %v", err) 36 } 37 } 38 39 func TestAgent_ServerConfig(t *testing.T) { 40 t.Parallel() 41 conf := DefaultConfig() 42 conf.DevMode = true // allow localhost for advertise addrs 43 conf.Server.Enabled = true 44 a := &Agent{config: conf} 45 46 conf.AdvertiseAddrs.Serf = "127.0.0.1:4000" 47 conf.AdvertiseAddrs.RPC = "127.0.0.1:4001" 48 conf.AdvertiseAddrs.HTTP = "10.10.11.1:4005" 49 conf.ACL.Enabled = true 50 51 // Parses the advertise addrs correctly 52 if err := conf.normalizeAddrs(); err != nil { 53 t.Fatalf("error normalizing config: %v", err) 54 } 55 out, err := a.serverConfig() 56 if err != nil { 57 t.Fatalf("err: %s", err) 58 } 59 serfAddr := out.SerfConfig.MemberlistConfig.AdvertiseAddr 60 if serfAddr != "127.0.0.1" { 61 t.Fatalf("expect 127.0.0.1, got: %s", serfAddr) 62 } 63 serfPort := out.SerfConfig.MemberlistConfig.AdvertisePort 64 if serfPort != 4000 { 65 t.Fatalf("expected 4000, got: %d", serfPort) 66 } 67 if out.AuthoritativeRegion != "global" { 68 t.Fatalf("bad: %#v", out.AuthoritativeRegion) 69 } 70 if !out.ACLEnabled { 71 t.Fatalf("ACL not enabled") 72 } 73 74 // Assert addresses weren't changed 75 if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.1:4001" { 76 t.Fatalf("bad rpc advertise addr: %#v", addr) 77 } 78 if addr := conf.AdvertiseAddrs.HTTP; addr != "10.10.11.1:4005" { 79 t.Fatalf("expect 10.11.11.1:4005, got: %v", addr) 80 } 81 if addr := conf.Addresses.RPC; addr != "0.0.0.0" { 82 t.Fatalf("expect 0.0.0.0, got: %v", addr) 83 } 84 85 // Sets up the ports properly 86 conf.Addresses.RPC = "" 87 conf.Addresses.Serf = "" 88 conf.Ports.RPC = 4003 89 conf.Ports.Serf = 4004 90 91 if err := conf.normalizeAddrs(); err != nil { 92 t.Fatalf("error normalizing config: %v", err) 93 } 94 out, err = a.serverConfig() 95 if err != nil { 96 t.Fatalf("err: %s", err) 97 } 98 if addr := out.RPCAddr.Port; addr != 4003 { 99 t.Fatalf("expect 4003, got: %d", out.RPCAddr.Port) 100 } 101 if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 { 102 t.Fatalf("expect 4004, got: %d", port) 103 } 104 105 // Prefers advertise over bind addr 106 conf.BindAddr = "127.0.0.3" 107 conf.Addresses.HTTP = "127.0.0.2" 108 conf.Addresses.RPC = "127.0.0.2" 109 conf.Addresses.Serf = "127.0.0.2" 110 conf.AdvertiseAddrs.HTTP = "10.0.0.10" 111 conf.AdvertiseAddrs.RPC = "" 112 conf.AdvertiseAddrs.Serf = "10.0.0.12:4004" 113 114 if err := conf.normalizeAddrs(); err != nil { 115 t.Fatalf("error normalizing config: %v", err) 116 } 117 out, err = a.serverConfig() 118 if err != nil { 119 t.Fatalf("err: %s", err) 120 } 121 if addr := out.RPCAddr.IP.String(); addr != "127.0.0.2" { 122 t.Fatalf("expect 127.0.0.2, got: %s", addr) 123 } 124 if port := out.RPCAddr.Port; port != 4003 { 125 t.Fatalf("expect 4647, got: %d", port) 126 } 127 if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.2" { 128 t.Fatalf("expect 127.0.0.2, got: %s", addr) 129 } 130 if port := out.SerfConfig.MemberlistConfig.BindPort; port != 4004 { 131 t.Fatalf("expect 4648, got: %d", port) 132 } 133 if addr := conf.Addresses.HTTP; addr != "127.0.0.2" { 134 t.Fatalf("expect 127.0.0.2, got: %s", addr) 135 } 136 if addr := conf.Addresses.RPC; addr != "127.0.0.2" { 137 t.Fatalf("expect 127.0.0.2, got: %s", addr) 138 } 139 if addr := conf.Addresses.Serf; addr != "127.0.0.2" { 140 t.Fatalf("expect 10.0.0.12, got: %s", addr) 141 } 142 if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.2:4646" { 143 t.Fatalf("expect 127.0.0.2:4646, got: %s", addr) 144 } 145 if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.2:4003" { 146 t.Fatalf("expect 127.0.0.2:4003, got: %s", addr) 147 } 148 if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.2:4004" { 149 t.Fatalf("expect 10.0.0.12:4004, got: %s", addr) 150 } 151 if addr := conf.AdvertiseAddrs.HTTP; addr != "10.0.0.10:4646" { 152 t.Fatalf("expect 10.0.0.10:4646, got: %s", addr) 153 } 154 if addr := conf.AdvertiseAddrs.RPC; addr != "127.0.0.2:4003" { 155 t.Fatalf("expect 127.0.0.2:4003, got: %s", addr) 156 } 157 if addr := conf.AdvertiseAddrs.Serf; addr != "10.0.0.12:4004" { 158 t.Fatalf("expect 10.0.0.12:4004, got: %s", addr) 159 } 160 161 conf.Server.NodeGCThreshold = "42g" 162 if err := conf.normalizeAddrs(); err != nil { 163 t.Fatalf("error normalizing config: %v", err) 164 } 165 out, err = a.serverConfig() 166 if err == nil || !strings.Contains(err.Error(), "unknown unit") { 167 t.Fatalf("expected unknown unit error, got: %#v", err) 168 } 169 170 conf.Server.NodeGCThreshold = "10s" 171 if err := conf.normalizeAddrs(); err != nil { 172 t.Fatalf("error normalizing config: %v", err) 173 } 174 out, err = a.serverConfig() 175 if threshold := out.NodeGCThreshold; threshold != time.Second*10 { 176 t.Fatalf("expect 10s, got: %s", threshold) 177 } 178 179 conf.Server.HeartbeatGrace = 37 * time.Second 180 out, err = a.serverConfig() 181 if threshold := out.HeartbeatGrace; threshold != time.Second*37 { 182 t.Fatalf("expect 37s, got: %s", threshold) 183 } 184 185 conf.Server.MinHeartbeatTTL = 37 * time.Second 186 out, err = a.serverConfig() 187 if min := out.MinHeartbeatTTL; min != time.Second*37 { 188 t.Fatalf("expect 37s, got: %s", min) 189 } 190 191 conf.Server.MaxHeartbeatsPerSecond = 11.0 192 out, err = a.serverConfig() 193 if max := out.MaxHeartbeatsPerSecond; max != 11.0 { 194 t.Fatalf("expect 11, got: %v", max) 195 } 196 197 // Defaults to the global bind addr 198 conf.Addresses.RPC = "" 199 conf.Addresses.Serf = "" 200 conf.Addresses.HTTP = "" 201 conf.AdvertiseAddrs.RPC = "" 202 conf.AdvertiseAddrs.HTTP = "" 203 conf.AdvertiseAddrs.Serf = "" 204 conf.Ports.HTTP = 4646 205 conf.Ports.RPC = 4647 206 conf.Ports.Serf = 4648 207 if err := conf.normalizeAddrs(); err != nil { 208 t.Fatalf("error normalizing config: %v", err) 209 } 210 out, err = a.serverConfig() 211 if err != nil { 212 t.Fatalf("err: %s", err) 213 } 214 if addr := out.RPCAddr.IP.String(); addr != "127.0.0.3" { 215 t.Fatalf("expect 127.0.0.3, got: %s", addr) 216 } 217 if addr := out.SerfConfig.MemberlistConfig.BindAddr; addr != "127.0.0.3" { 218 t.Fatalf("expect 127.0.0.3, got: %s", addr) 219 } 220 if addr := conf.Addresses.HTTP; addr != "127.0.0.3" { 221 t.Fatalf("expect 127.0.0.3, got: %s", addr) 222 } 223 if addr := conf.Addresses.RPC; addr != "127.0.0.3" { 224 t.Fatalf("expect 127.0.0.3, got: %s", addr) 225 } 226 if addr := conf.Addresses.Serf; addr != "127.0.0.3" { 227 t.Fatalf("expect 127.0.0.3, got: %s", addr) 228 } 229 if addr := conf.normalizedAddrs.HTTP; addr != "127.0.0.3:4646" { 230 t.Fatalf("expect 127.0.0.3:4646, got: %s", addr) 231 } 232 if addr := conf.normalizedAddrs.RPC; addr != "127.0.0.3:4647" { 233 t.Fatalf("expect 127.0.0.3:4647, got: %s", addr) 234 } 235 if addr := conf.normalizedAddrs.Serf; addr != "127.0.0.3:4648" { 236 t.Fatalf("expect 127.0.0.3:4648, got: %s", addr) 237 } 238 239 // Properly handles the bootstrap flags 240 conf.Server.BootstrapExpect = 1 241 out, err = a.serverConfig() 242 if err != nil { 243 t.Fatalf("err: %s", err) 244 } 245 if !out.Bootstrap { 246 t.Fatalf("should have set bootstrap mode") 247 } 248 if out.BootstrapExpect != 0 { 249 t.Fatalf("bootstrap expect should be 0") 250 } 251 252 conf.Server.BootstrapExpect = 3 253 out, err = a.serverConfig() 254 if err != nil { 255 t.Fatalf("err: %s", err) 256 } 257 if out.Bootstrap { 258 t.Fatalf("bootstrap mode should be disabled") 259 } 260 if out.BootstrapExpect != 3 { 261 t.Fatalf("should have bootstrap-expect = 3") 262 } 263 } 264 265 func TestAgent_ClientConfig(t *testing.T) { 266 t.Parallel() 267 conf := DefaultConfig() 268 conf.Client.Enabled = true 269 270 // For Clients HTTP and RPC must be set (Serf can be skipped) 271 conf.Addresses.HTTP = "169.254.0.1" 272 conf.Addresses.RPC = "169.254.0.1" 273 conf.Ports.HTTP = 5678 274 a := &Agent{config: conf} 275 276 if err := conf.normalizeAddrs(); err != nil { 277 t.Fatalf("error normalizing config: %v", err) 278 } 279 c, err := a.clientConfig() 280 if err != nil { 281 t.Fatalf("got err: %v", err) 282 } 283 284 expectedHttpAddr := "169.254.0.1:5678" 285 if c.Node.HTTPAddr != expectedHttpAddr { 286 t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr) 287 } 288 289 conf = DefaultConfig() 290 conf.DevMode = true 291 a = &Agent{config: conf} 292 conf.Client.Enabled = true 293 conf.Addresses.HTTP = "169.254.0.1" 294 295 if err := conf.normalizeAddrs(); err != nil { 296 t.Fatalf("error normalizing config: %v", err) 297 } 298 c, err = a.clientConfig() 299 if err != nil { 300 t.Fatalf("got err: %v", err) 301 } 302 303 expectedHttpAddr = "169.254.0.1:4646" 304 if c.Node.HTTPAddr != expectedHttpAddr { 305 t.Fatalf("Expected http addr: %v, got: %v", expectedHttpAddr, c.Node.HTTPAddr) 306 } 307 } 308 309 // Clients should inherit telemetry configuration 310 func TestAget_Client_TelemetryConfiguration(t *testing.T) { 311 assert := assert.New(t) 312 313 conf := DefaultConfig() 314 conf.DevMode = true 315 conf.Telemetry.DisableTaggedMetrics = true 316 conf.Telemetry.BackwardsCompatibleMetrics = true 317 318 a := &Agent{config: conf} 319 320 c, err := a.clientConfig() 321 assert.Nil(err) 322 323 telemetry := conf.Telemetry 324 325 assert.Equal(c.StatsCollectionInterval, telemetry.collectionInterval) 326 assert.Equal(c.PublishNodeMetrics, telemetry.PublishNodeMetrics) 327 assert.Equal(c.PublishAllocationMetrics, telemetry.PublishAllocationMetrics) 328 assert.Equal(c.DisableTaggedMetrics, telemetry.DisableTaggedMetrics) 329 assert.Equal(c.BackwardsCompatibleMetrics, telemetry.BackwardsCompatibleMetrics) 330 } 331 332 // TestAgent_HTTPCheck asserts Agent.agentHTTPCheck properly alters the HTTP 333 // API health check depending on configuration. 334 func TestAgent_HTTPCheck(t *testing.T) { 335 t.Parallel() 336 logger := testlog.HCLogger(t) 337 agent := func() *Agent { 338 return &Agent{ 339 logger: logger, 340 config: &Config{ 341 AdvertiseAddrs: &AdvertiseAddrs{HTTP: "advertise:4646"}, 342 normalizedAddrs: &Addresses{HTTP: "normalized:4646"}, 343 Consul: &sconfig.ConsulConfig{ 344 ChecksUseAdvertise: helper.BoolToPtr(false), 345 }, 346 TLSConfig: &sconfig.TLSConfig{EnableHTTP: false}, 347 }, 348 } 349 } 350 351 t.Run("Plain HTTP Check", func(t *testing.T) { 352 a := agent() 353 check := a.agentHTTPCheck(false) 354 if check == nil { 355 t.Fatalf("expected non-nil check") 356 } 357 if check.Type != "http" { 358 t.Errorf("expected http check not: %q", check.Type) 359 } 360 if expected := "/v1/agent/health?type=client"; check.Path != expected { 361 t.Errorf("expected %q path not: %q", expected, check.Path) 362 } 363 if check.Protocol != "http" { 364 t.Errorf("expected http proto not: %q", check.Protocol) 365 } 366 if expected := a.config.normalizedAddrs.HTTP; check.PortLabel != expected { 367 t.Errorf("expected normalized addr not %q", check.PortLabel) 368 } 369 }) 370 371 t.Run("Plain HTTP + ChecksUseAdvertise", func(t *testing.T) { 372 a := agent() 373 a.config.Consul.ChecksUseAdvertise = helper.BoolToPtr(true) 374 check := a.agentHTTPCheck(false) 375 if check == nil { 376 t.Fatalf("expected non-nil check") 377 } 378 if expected := a.config.AdvertiseAddrs.HTTP; check.PortLabel != expected { 379 t.Errorf("expected advertise addr not %q", check.PortLabel) 380 } 381 }) 382 383 t.Run("HTTPS", func(t *testing.T) { 384 a := agent() 385 a.config.TLSConfig.EnableHTTP = true 386 387 check := a.agentHTTPCheck(false) 388 if check == nil { 389 t.Fatalf("expected non-nil check") 390 } 391 if !check.TLSSkipVerify { 392 t.Errorf("expected tls skip verify") 393 } 394 if check.Protocol != "https" { 395 t.Errorf("expected https not: %q", check.Protocol) 396 } 397 }) 398 399 t.Run("HTTPS + VerifyHTTPSClient", func(t *testing.T) { 400 a := agent() 401 a.config.TLSConfig.EnableHTTP = true 402 a.config.TLSConfig.VerifyHTTPSClient = true 403 404 if check := a.agentHTTPCheck(false); check != nil { 405 t.Fatalf("expected nil check not: %#v", check) 406 } 407 }) 408 } 409 410 // TestAgent_HTTPCheckPath asserts clients and servers use different endpoints 411 // for healthchecks. 412 func TestAgent_HTTPCheckPath(t *testing.T) { 413 t.Parallel() 414 // Agent.agentHTTPCheck only needs a config and logger 415 a := &Agent{ 416 config: DevConfig(), 417 logger: testlog.HCLogger(t), 418 } 419 if err := a.config.normalizeAddrs(); err != nil { 420 t.Fatalf("error normalizing config: %v", err) 421 } 422 423 // Assert server check uses /v1/agent/health?type=server 424 isServer := true 425 check := a.agentHTTPCheck(isServer) 426 if expected := "Nomad Server HTTP Check"; check.Name != expected { 427 t.Errorf("expected server check name to be %q but found %q", expected, check.Name) 428 } 429 if expected := "/v1/agent/health?type=server"; check.Path != expected { 430 t.Errorf("expected server check path to be %q but found %q", expected, check.Path) 431 } 432 433 // Assert client check uses /v1/agent/health?type=client 434 isServer = false 435 check = a.agentHTTPCheck(isServer) 436 if expected := "Nomad Client HTTP Check"; check.Name != expected { 437 t.Errorf("expected client check name to be %q but found %q", expected, check.Name) 438 } 439 if expected := "/v1/agent/health?type=client"; check.Path != expected { 440 t.Errorf("expected client check path to be %q but found %q", expected, check.Path) 441 } 442 } 443 444 // This test asserts that the keyloader embedded in the TLS config is shared 445 // across the Agent, Server, and Client. This is essential for certificate 446 // reloading to work. 447 func TestServer_Reload_TLS_Shared_Keyloader(t *testing.T) { 448 t.Parallel() 449 assert := assert.New(t) 450 451 // We will start out with a bad cert and then reload with a good one. 452 const ( 453 cafile = "../../helper/tlsutil/testdata/ca.pem" 454 foocert = "../../helper/tlsutil/testdata/nomad-bad.pem" 455 fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem" 456 foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem" 457 fookey2 = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 458 ) 459 460 agent := NewTestAgent(t, t.Name(), func(c *Config) { 461 c.TLSConfig = &sconfig.TLSConfig{ 462 EnableHTTP: true, 463 EnableRPC: true, 464 VerifyServerHostname: true, 465 CAFile: cafile, 466 CertFile: foocert, 467 KeyFile: fookey, 468 } 469 }) 470 defer agent.Shutdown() 471 472 originalKeyloader := agent.Config.TLSConfig.GetKeyLoader() 473 originalCert, err := originalKeyloader.GetOutgoingCertificate(nil) 474 assert.NotNil(originalKeyloader) 475 if assert.Nil(err) { 476 assert.NotNil(originalCert) 477 } 478 479 // Switch to the correct certificates and reload 480 newConfig := &Config{ 481 TLSConfig: &sconfig.TLSConfig{ 482 EnableHTTP: true, 483 EnableRPC: true, 484 VerifyServerHostname: true, 485 CAFile: cafile, 486 CertFile: foocert2, 487 KeyFile: fookey2, 488 }, 489 } 490 491 assert.Nil(agent.Reload(newConfig)) 492 assert.Equal(agent.Config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile) 493 assert.Equal(agent.Config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile) 494 assert.Equal(agent.Config.TLSConfig.GetKeyLoader(), originalKeyloader) 495 496 // Assert is passed through on the server correctly 497 if assert.NotNil(agent.server.GetConfig().TLSConfig) { 498 serverKeyloader := agent.server.GetConfig().TLSConfig.GetKeyLoader() 499 assert.Equal(serverKeyloader, originalKeyloader) 500 newCert, err := serverKeyloader.GetOutgoingCertificate(nil) 501 assert.Nil(err) 502 assert.NotEqual(originalCert, newCert) 503 } 504 505 // Assert is passed through on the client correctly 506 if assert.NotNil(agent.client.GetConfig().TLSConfig) { 507 clientKeyloader := agent.client.GetConfig().TLSConfig.GetKeyLoader() 508 assert.Equal(clientKeyloader, originalKeyloader) 509 newCert, err := clientKeyloader.GetOutgoingCertificate(nil) 510 assert.Nil(err) 511 assert.NotEqual(originalCert, newCert) 512 } 513 } 514 515 func TestServer_Reload_TLS_Certificate(t *testing.T) { 516 t.Parallel() 517 assert := assert.New(t) 518 519 const ( 520 cafile = "../../helper/tlsutil/testdata/ca.pem" 521 foocert = "../../helper/tlsutil/testdata/nomad-bad.pem" 522 fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem" 523 foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem" 524 fookey2 = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 525 ) 526 527 agentConfig := &Config{ 528 TLSConfig: &sconfig.TLSConfig{ 529 EnableHTTP: true, 530 EnableRPC: true, 531 VerifyServerHostname: true, 532 CAFile: cafile, 533 CertFile: foocert, 534 KeyFile: fookey, 535 }, 536 } 537 538 agent := &Agent{ 539 config: agentConfig, 540 } 541 542 newConfig := &Config{ 543 TLSConfig: &sconfig.TLSConfig{ 544 EnableHTTP: true, 545 EnableRPC: true, 546 VerifyServerHostname: true, 547 CAFile: cafile, 548 CertFile: foocert2, 549 KeyFile: fookey2, 550 }, 551 } 552 553 originalKeyloader := agentConfig.TLSConfig.GetKeyLoader() 554 assert.NotNil(originalKeyloader) 555 556 err := agent.Reload(newConfig) 557 assert.Nil(err) 558 assert.Equal(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile) 559 assert.Equal(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile) 560 assert.Equal(agent.config.TLSConfig.GetKeyLoader(), originalKeyloader) 561 } 562 563 func TestServer_Reload_TLS_Certificate_Invalid(t *testing.T) { 564 t.Parallel() 565 assert := assert.New(t) 566 567 const ( 568 cafile = "../../helper/tlsutil/testdata/ca.pem" 569 foocert = "../../helper/tlsutil/testdata/nomad-bad.pem" 570 fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem" 571 foocert2 = "invalid_cert_path" 572 fookey2 = "invalid_key_path" 573 ) 574 575 agentConfig := &Config{ 576 TLSConfig: &sconfig.TLSConfig{ 577 EnableHTTP: true, 578 EnableRPC: true, 579 VerifyServerHostname: true, 580 CAFile: cafile, 581 CertFile: foocert, 582 KeyFile: fookey, 583 }, 584 } 585 586 agent := &Agent{ 587 config: agentConfig, 588 } 589 590 newConfig := &Config{ 591 TLSConfig: &sconfig.TLSConfig{ 592 EnableHTTP: true, 593 EnableRPC: true, 594 VerifyServerHostname: true, 595 CAFile: cafile, 596 CertFile: foocert2, 597 KeyFile: fookey2, 598 }, 599 } 600 601 err := agent.Reload(newConfig) 602 assert.NotNil(err) 603 assert.NotEqual(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile) 604 assert.NotEqual(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile) 605 } 606 607 func Test_GetConfig(t *testing.T) { 608 assert := assert.New(t) 609 610 agentConfig := &Config{ 611 Telemetry: &Telemetry{}, 612 Client: &ClientConfig{}, 613 Server: &ServerConfig{}, 614 ACL: &ACLConfig{}, 615 Ports: &Ports{}, 616 Addresses: &Addresses{}, 617 AdvertiseAddrs: &AdvertiseAddrs{}, 618 Vault: &sconfig.VaultConfig{}, 619 Consul: &sconfig.ConsulConfig{}, 620 Sentinel: &sconfig.SentinelConfig{}, 621 } 622 623 agent := &Agent{ 624 config: agentConfig, 625 } 626 627 actualAgentConfig := agent.GetConfig() 628 assert.Equal(actualAgentConfig, agentConfig) 629 } 630 631 func TestServer_Reload_TLS_WithNilConfiguration(t *testing.T) { 632 t.Parallel() 633 assert := assert.New(t) 634 635 logger := testlog.HCLogger(t) 636 637 agent := &Agent{ 638 logger: logger, 639 config: &Config{}, 640 } 641 642 err := agent.Reload(nil) 643 assert.NotNil(err) 644 assert.Equal(err.Error(), "cannot reload agent with nil configuration") 645 } 646 647 func TestServer_Reload_TLS_UpgradeToTLS(t *testing.T) { 648 t.Parallel() 649 assert := assert.New(t) 650 651 const ( 652 cafile = "../../helper/tlsutil/testdata/ca.pem" 653 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 654 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 655 ) 656 dir := tmpDir(t) 657 defer os.RemoveAll(dir) 658 659 logger := testlog.HCLogger(t) 660 661 agentConfig := &Config{ 662 TLSConfig: &sconfig.TLSConfig{}, 663 } 664 665 agent := &Agent{ 666 logger: logger, 667 config: agentConfig, 668 } 669 670 newConfig := &Config{ 671 TLSConfig: &sconfig.TLSConfig{ 672 EnableHTTP: true, 673 EnableRPC: true, 674 VerifyServerHostname: true, 675 CAFile: cafile, 676 CertFile: foocert, 677 KeyFile: fookey, 678 }, 679 } 680 681 err := agent.Reload(newConfig) 682 assert.Nil(err) 683 684 assert.Equal(agent.config.TLSConfig.CAFile, newConfig.TLSConfig.CAFile) 685 assert.Equal(agent.config.TLSConfig.CertFile, newConfig.TLSConfig.CertFile) 686 assert.Equal(agent.config.TLSConfig.KeyFile, newConfig.TLSConfig.KeyFile) 687 } 688 689 func TestServer_Reload_TLS_DowngradeFromTLS(t *testing.T) { 690 t.Parallel() 691 assert := assert.New(t) 692 693 const ( 694 cafile = "../../helper/tlsutil/testdata/ca.pem" 695 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 696 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 697 ) 698 dir := tmpDir(t) 699 defer os.RemoveAll(dir) 700 701 logger := testlog.HCLogger(t) 702 703 agentConfig := &Config{ 704 TLSConfig: &sconfig.TLSConfig{ 705 EnableHTTP: true, 706 EnableRPC: true, 707 VerifyServerHostname: true, 708 CAFile: cafile, 709 CertFile: foocert, 710 KeyFile: fookey, 711 }, 712 } 713 714 agent := &Agent{ 715 logger: logger, 716 config: agentConfig, 717 } 718 719 newConfig := &Config{ 720 TLSConfig: &sconfig.TLSConfig{}, 721 } 722 723 assert.False(agentConfig.TLSConfig.IsEmpty()) 724 725 err := agent.Reload(newConfig) 726 assert.Nil(err) 727 728 assert.True(agentConfig.TLSConfig.IsEmpty()) 729 } 730 731 func TestServer_ShouldReload_ReturnFalseForNoChanges(t *testing.T) { 732 t.Parallel() 733 assert := assert.New(t) 734 735 const ( 736 cafile = "../../helper/tlsutil/testdata/ca.pem" 737 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 738 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 739 ) 740 dir := tmpDir(t) 741 defer os.RemoveAll(dir) 742 743 sameAgentConfig := &Config{ 744 TLSConfig: &sconfig.TLSConfig{ 745 EnableHTTP: true, 746 EnableRPC: true, 747 VerifyServerHostname: true, 748 CAFile: cafile, 749 CertFile: foocert, 750 KeyFile: fookey, 751 }, 752 } 753 754 agent := NewTestAgent(t, t.Name(), func(c *Config) { 755 c.TLSConfig = &sconfig.TLSConfig{ 756 EnableHTTP: true, 757 EnableRPC: true, 758 VerifyServerHostname: true, 759 CAFile: cafile, 760 CertFile: foocert, 761 KeyFile: fookey, 762 } 763 }) 764 defer agent.Shutdown() 765 766 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(sameAgentConfig) 767 assert.False(shouldReloadAgent) 768 assert.False(shouldReloadHTTP) 769 } 770 771 func TestServer_ShouldReload_ReturnTrueForOnlyHTTPChanges(t *testing.T) { 772 t.Parallel() 773 require := require.New(t) 774 775 const ( 776 cafile = "../../helper/tlsutil/testdata/ca.pem" 777 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 778 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 779 ) 780 dir := tmpDir(t) 781 defer os.RemoveAll(dir) 782 783 sameAgentConfig := &Config{ 784 TLSConfig: &sconfig.TLSConfig{ 785 EnableHTTP: false, 786 EnableRPC: true, 787 VerifyServerHostname: true, 788 CAFile: cafile, 789 CertFile: foocert, 790 KeyFile: fookey, 791 }, 792 } 793 794 agent := NewTestAgent(t, t.Name(), func(c *Config) { 795 c.TLSConfig = &sconfig.TLSConfig{ 796 EnableHTTP: true, 797 EnableRPC: true, 798 VerifyServerHostname: true, 799 CAFile: cafile, 800 CertFile: foocert, 801 KeyFile: fookey, 802 } 803 }) 804 defer agent.Shutdown() 805 806 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(sameAgentConfig) 807 require.True(shouldReloadAgent) 808 require.True(shouldReloadHTTP) 809 } 810 811 func TestServer_ShouldReload_ReturnTrueForOnlyRPCChanges(t *testing.T) { 812 t.Parallel() 813 assert := assert.New(t) 814 815 const ( 816 cafile = "../../helper/tlsutil/testdata/ca.pem" 817 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 818 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 819 ) 820 dir := tmpDir(t) 821 defer os.RemoveAll(dir) 822 823 sameAgentConfig := &Config{ 824 TLSConfig: &sconfig.TLSConfig{ 825 EnableHTTP: true, 826 EnableRPC: true, 827 VerifyServerHostname: true, 828 CAFile: cafile, 829 CertFile: foocert, 830 KeyFile: fookey, 831 }, 832 } 833 834 agent := NewTestAgent(t, t.Name(), func(c *Config) { 835 c.TLSConfig = &sconfig.TLSConfig{ 836 EnableHTTP: true, 837 EnableRPC: false, 838 VerifyServerHostname: true, 839 CAFile: cafile, 840 CertFile: foocert, 841 KeyFile: fookey, 842 } 843 }) 844 defer agent.Shutdown() 845 846 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(sameAgentConfig) 847 assert.True(shouldReloadAgent) 848 assert.False(shouldReloadHTTP) 849 } 850 851 func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) { 852 t.Parallel() 853 assert := assert.New(t) 854 855 const ( 856 cafile = "../../helper/tlsutil/testdata/ca.pem" 857 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 858 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 859 foocert2 = "../../helper/tlsutil/testdata/nomad-bad.pem" 860 fookey2 = "../../helper/tlsutil/testdata/nomad-bad-key.pem" 861 ) 862 dir := tmpDir(t) 863 defer os.RemoveAll(dir) 864 865 agent := NewTestAgent(t, t.Name(), func(c *Config) { 866 c.TLSConfig = &sconfig.TLSConfig{ 867 EnableHTTP: true, 868 EnableRPC: true, 869 VerifyServerHostname: true, 870 CAFile: cafile, 871 CertFile: foocert, 872 KeyFile: fookey, 873 } 874 }) 875 defer agent.Shutdown() 876 877 newConfig := &Config{ 878 TLSConfig: &sconfig.TLSConfig{ 879 EnableHTTP: true, 880 EnableRPC: true, 881 VerifyServerHostname: true, 882 CAFile: cafile, 883 CertFile: foocert2, 884 KeyFile: fookey2, 885 }, 886 } 887 888 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(newConfig) 889 assert.True(shouldReloadAgent) 890 assert.True(shouldReloadHTTP) 891 } 892 893 func TestServer_ShouldReload_ReturnTrueForFileChanges(t *testing.T) { 894 t.Parallel() 895 require := require.New(t) 896 897 oldCertificate := ` 898 -----BEGIN CERTIFICATE----- 899 MIICrzCCAlagAwIBAgIUN+4rYZ6wqQCIBzYYd0sfX2e8hDowCgYIKoZIzj0EAwIw 900 eDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh 901 biBGcmFuY2lzY28xEjAQBgNVBAoTCUhhc2hpQ29ycDEOMAwGA1UECxMFTm9tYWQx 902 GDAWBgNVBAMTD25vbWFkLmhhc2hpY29ycDAgFw0xNjExMTAxOTU2MDBaGA8yMTE2 903 MTAxNzE5NTYwMFoweDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx 904 FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEjAQBgNVBAoTCUhhc2hpQ29ycDEOMAwG 905 A1UECxMFTm9tYWQxGDAWBgNVBAMTD3JlZ2lvbkZvby5ub21hZDBZMBMGByqGSM49 906 AgEGCCqGSM49AwEHA0IABOqGSFNjm+EBlLYlxmIP6SQTdX8U/6hbPWObB0ffkEO/ 907 CFweeYIVWb3FKNPqYAlhMqg1K0ileD0FbhEzarP0sL6jgbswgbgwDgYDVR0PAQH/ 908 BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8E 909 AjAAMB0GA1UdDgQWBBQnMcjU4yI3k0AoMtapACpO+w9QMTAfBgNVHSMEGDAWgBQ6 910 NWr8F5y2eFwqfoQdQPg0kWb9QDA5BgNVHREEMjAwghZzZXJ2ZXIucmVnaW9uRm9v 911 Lm5vbWFkghZjbGllbnQucmVnaW9uRm9vLm5vbWFkMAoGCCqGSM49BAMCA0cAMEQC 912 ICrvzc5NzqhdT/HkazAx5OOUU8hqoptnmhRmwn6X+0y9AiA8bNvMUxHz3ZLjGBiw 913 PLBDC2UaSDqJqiiYpYegLhbQtw== 914 -----END CERTIFICATE----- 915 ` 916 917 content := []byte(oldCertificate) 918 dir, err := ioutil.TempDir("", "certificate") 919 if err != nil { 920 t.Fatal(err) 921 } 922 defer os.RemoveAll(dir) // clean up 923 924 tmpfn := filepath.Join(dir, "testcert") 925 err = ioutil.WriteFile(tmpfn, content, 0666) 926 require.Nil(err) 927 928 const ( 929 cafile = "../../helper/tlsutil/testdata/ca.pem" 930 key = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 931 ) 932 933 logger := testlog.HCLogger(t) 934 935 agentConfig := &Config{ 936 TLSConfig: &sconfig.TLSConfig{ 937 EnableHTTP: true, 938 EnableRPC: true, 939 VerifyServerHostname: true, 940 CAFile: cafile, 941 CertFile: tmpfn, 942 KeyFile: key, 943 }, 944 } 945 946 agent := &Agent{ 947 logger: logger, 948 config: agentConfig, 949 } 950 agent.config.TLSConfig.SetChecksum() 951 952 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(agentConfig) 953 require.False(shouldReloadAgent) 954 require.False(shouldReloadHTTP) 955 956 newCertificate := ` 957 -----BEGIN CERTIFICATE----- 958 MIICtTCCAlqgAwIBAgIUQp/L2szbgE4b1ASlPOZMReFE27owCgYIKoZIzj0EAwIw 959 fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh 960 biBGcmFuY2lzY28xEjAQBgNVBAoTCUhhc2hpQ29ycDEOMAwGA1UECxMFTm9tYWQx 961 HDAaBgNVBAMTE2JhZC5ub21hZC5oYXNoaWNvcnAwIBcNMTYxMTEwMjAxMDAwWhgP 962 MjExNjEwMTcyMDEwMDBaMHgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y 963 bmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRIwEAYDVQQKEwlIYXNoaUNvcnAx 964 DjAMBgNVBAsTBU5vbWFkMRgwFgYDVQQDEw9yZWdpb25CYWQubm9tYWQwWTATBgcq 965 hkjOPQIBBggqhkjOPQMBBwNCAAQk6oXJwlxNrKvl6kpeeR4NJc5EYFI2b3y7odjY 966 u55Jp4sI91JVDqnpyatkyGmavdAWa4t0U6HkeaWqKk16/ZcYo4G7MIG4MA4GA1Ud 967 DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T 968 AQH/BAIwADAdBgNVHQ4EFgQUxhzOftFR2L0QAPx8LOuP99WPbpgwHwYDVR0jBBgw 969 FoAUHPDLSgzlHqBEh+c4A7HeT0GWygIwOQYDVR0RBDIwMIIWc2VydmVyLnJlZ2lv 970 bkJhZC5ub21hZIIWY2xpZW50LnJlZ2lvbkJhZC5ub21hZDAKBggqhkjOPQQDAgNJ 971 ADBGAiEAq2rnBeX/St/8i9Cab7Yw0C7pjcaE+mrFYeQByng1Uc0CIQD/o4BrZdkX 972 Nm7QGTRZbUFZTHYZr0ULz08Iaz2aHQ6Mcw== 973 -----END CERTIFICATE----- 974 ` 975 976 os.Remove(tmpfn) 977 err = ioutil.WriteFile(tmpfn, []byte(newCertificate), 0666) 978 require.Nil(err) 979 980 newAgentConfig := &Config{ 981 TLSConfig: &sconfig.TLSConfig{ 982 EnableHTTP: true, 983 EnableRPC: true, 984 VerifyServerHostname: true, 985 CAFile: cafile, 986 CertFile: tmpfn, 987 KeyFile: key, 988 }, 989 } 990 991 shouldReloadAgent, shouldReloadHTTP = agent.ShouldReload(newAgentConfig) 992 require.True(shouldReloadAgent) 993 require.True(shouldReloadHTTP) 994 } 995 996 func TestServer_ShouldReload_ShouldHandleMultipleChanges(t *testing.T) { 997 t.Parallel() 998 require := require.New(t) 999 1000 const ( 1001 cafile = "../../helper/tlsutil/testdata/ca.pem" 1002 foocert = "../../helper/tlsutil/testdata/nomad-foo.pem" 1003 fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem" 1004 foocert2 = "../../helper/tlsutil/testdata/nomad-bad.pem" 1005 fookey2 = "../../helper/tlsutil/testdata/nomad-bad-key.pem" 1006 ) 1007 dir := tmpDir(t) 1008 defer os.RemoveAll(dir) 1009 1010 sameAgentConfig := &Config{ 1011 TLSConfig: &sconfig.TLSConfig{ 1012 EnableHTTP: true, 1013 EnableRPC: true, 1014 VerifyServerHostname: true, 1015 CAFile: cafile, 1016 CertFile: foocert, 1017 KeyFile: fookey, 1018 }, 1019 } 1020 1021 agent := NewTestAgent(t, t.Name(), func(c *Config) { 1022 c.TLSConfig = &sconfig.TLSConfig{ 1023 EnableHTTP: true, 1024 EnableRPC: true, 1025 VerifyServerHostname: true, 1026 CAFile: cafile, 1027 CertFile: foocert2, 1028 KeyFile: fookey2, 1029 } 1030 }) 1031 defer agent.Shutdown() 1032 1033 { 1034 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(sameAgentConfig) 1035 require.True(shouldReloadAgent) 1036 require.True(shouldReloadHTTP) 1037 } 1038 1039 err := agent.Reload(sameAgentConfig) 1040 require.Nil(err) 1041 1042 { 1043 shouldReloadAgent, shouldReloadHTTP := agent.ShouldReload(sameAgentConfig) 1044 require.False(shouldReloadAgent) 1045 require.False(shouldReloadHTTP) 1046 } 1047 } 1048 1049 func TestAgent_ProxyRPC_Dev(t *testing.T) { 1050 t.Parallel() 1051 agent := NewTestAgent(t, t.Name(), nil) 1052 defer agent.Shutdown() 1053 1054 id := agent.client.NodeID() 1055 req := &structs.NodeSpecificRequest{ 1056 NodeID: id, 1057 QueryOptions: structs.QueryOptions{ 1058 Region: agent.server.Region(), 1059 }, 1060 } 1061 1062 time.Sleep(100 * time.Millisecond) 1063 1064 var resp cstructs.ClientStatsResponse 1065 if err := agent.RPC("ClientStats.Stats", req, &resp); err != nil { 1066 t.Fatalf("err: %v", err) 1067 } 1068 }