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