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