github.com/diptanu/nomad@v0.5.7-0.20170516172507-d72e86cbe3d9/nomad/vault_test.go (about) 1 package nomad 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "log" 8 "os" 9 "reflect" 10 "strings" 11 "testing" 12 "time" 13 14 "golang.org/x/time/rate" 15 16 "github.com/hashicorp/nomad/nomad/mock" 17 "github.com/hashicorp/nomad/nomad/structs" 18 "github.com/hashicorp/nomad/nomad/structs/config" 19 "github.com/hashicorp/nomad/testutil" 20 vapi "github.com/hashicorp/vault/api" 21 ) 22 23 const ( 24 // nomadRoleManagementPolicy is a policy that allows nomad to manage tokens 25 nomadRoleManagementPolicy = ` 26 path "auth/token/renew-self" { 27 capabilities = ["update"] 28 } 29 30 path "auth/token/lookup" { 31 capabilities = ["update"] 32 } 33 34 path "auth/token/roles/test" { 35 capabilities = ["read"] 36 } 37 38 path "auth/token/revoke-accessor" { 39 capabilities = ["update"] 40 } 41 ` 42 43 // tokenLookupPolicy allows a token to be looked up 44 tokenLookupPolicy = ` 45 path "auth/token/lookup" { 46 capabilities = ["update"] 47 } 48 ` 49 50 // nomadRoleCreatePolicy gives the ability to create the role and derive tokens 51 // from the test role 52 nomadRoleCreatePolicy = ` 53 path "auth/token/create/test" { 54 capabilities = ["create", "update"] 55 } 56 ` 57 58 // secretPolicy gives access to the secret mount 59 secretPolicy = ` 60 path "secret/*" { 61 capabilities = ["create", "read", "update", "delete", "list"] 62 } 63 ` 64 ) 65 66 // defaultTestVaultWhitelistRoleAndToken creates a test Vault role and returns a token 67 // created in that role 68 func defaultTestVaultWhitelistRoleAndToken(v *testutil.TestVault, t *testing.T, rolePeriod int) string { 69 vaultPolicies := map[string]string{ 70 "nomad-role-create": nomadRoleCreatePolicy, 71 "nomad-role-management": nomadRoleManagementPolicy, 72 } 73 d := make(map[string]interface{}, 2) 74 d["allowed_policies"] = "nomad-role-create,nomad-role-management" 75 d["period"] = rolePeriod 76 return testVaultRoleAndToken(v, t, vaultPolicies, d, 77 []string{"nomad-role-create", "nomad-role-management"}) 78 } 79 80 // defaultTestVaultBlacklistRoleAndToken creates a test Vault role using 81 // disallowed_policies and returns a token created in that role 82 func defaultTestVaultBlacklistRoleAndToken(v *testutil.TestVault, t *testing.T, rolePeriod int) string { 83 vaultPolicies := map[string]string{ 84 "nomad-role-create": nomadRoleCreatePolicy, 85 "nomad-role-management": nomadRoleManagementPolicy, 86 "secrets": secretPolicy, 87 } 88 89 // Create the role 90 d := make(map[string]interface{}, 2) 91 d["disallowed_policies"] = "nomad-role-create" 92 d["period"] = rolePeriod 93 testVaultRoleAndToken(v, t, vaultPolicies, d, []string{"default"}) 94 95 // Create a token that can use the role 96 a := v.Client.Auth().Token() 97 req := &vapi.TokenCreateRequest{ 98 Policies: []string{"nomad-role-create", "nomad-role-management"}, 99 } 100 s, err := a.Create(req) 101 if err != nil { 102 t.Fatalf("failed to create child token: %v", err) 103 } 104 105 if s == nil || s.Auth == nil { 106 t.Fatalf("bad secret response: %+v", s) 107 } 108 109 return s.Auth.ClientToken 110 } 111 112 // testVaultRoleAndToken writes the vaultPolicies to vault and then creates a 113 // test role with the passed data. After that it derives a token from the role 114 // with the tokenPolicies 115 func testVaultRoleAndToken(v *testutil.TestVault, t *testing.T, vaultPolicies map[string]string, 116 data map[string]interface{}, tokenPolicies []string) string { 117 // Write the policies 118 sys := v.Client.Sys() 119 for p, data := range vaultPolicies { 120 if err := sys.PutPolicy(p, data); err != nil { 121 t.Fatalf("failed to create %q policy: %v", p, err) 122 } 123 } 124 125 // Build a role 126 l := v.Client.Logical() 127 l.Write("auth/token/roles/test", data) 128 129 // Create a new token with the role 130 a := v.Client.Auth().Token() 131 req := vapi.TokenCreateRequest{ 132 Policies: tokenPolicies, 133 } 134 s, err := a.CreateWithRole(&req, "test") 135 if err != nil { 136 t.Fatalf("failed to create child token: %v", err) 137 } 138 139 // Get the client token 140 if s == nil || s.Auth == nil { 141 t.Fatalf("bad secret response: %+v", s) 142 } 143 144 return s.Auth.ClientToken 145 } 146 147 func TestVaultClient_BadConfig(t *testing.T) { 148 conf := &config.VaultConfig{} 149 logger := log.New(os.Stderr, "", log.LstdFlags) 150 151 // Should be no error since Vault is not enabled 152 _, err := NewVaultClient(nil, logger, nil) 153 if err == nil || !strings.Contains(err.Error(), "valid") { 154 t.Fatalf("expected config error: %v", err) 155 } 156 157 tr := true 158 conf.Enabled = &tr 159 _, err = NewVaultClient(conf, logger, nil) 160 if err == nil || !strings.Contains(err.Error(), "token must be set") { 161 t.Fatalf("Expected token unset error: %v", err) 162 } 163 164 conf.Token = "123" 165 _, err = NewVaultClient(conf, logger, nil) 166 if err == nil || !strings.Contains(err.Error(), "address must be set") { 167 t.Fatalf("Expected address unset error: %v", err) 168 } 169 } 170 171 // Test that the Vault Client can establish a connection even if it is started 172 // before Vault is available. 173 func TestVaultClient_EstablishConnection(t *testing.T) { 174 v := testutil.NewTestVault(t) 175 defer v.Stop() 176 177 logger := log.New(os.Stderr, "", log.LstdFlags) 178 v.Config.ConnectionRetryIntv = 100 * time.Millisecond 179 client, err := NewVaultClient(v.Config, logger, nil) 180 if err != nil { 181 t.Fatalf("failed to build vault client: %v", err) 182 } 183 defer client.Stop() 184 185 // Sleep a little while and check that no connection has been established. 186 time.Sleep(100 * time.Duration(testutil.TestMultiplier()) * time.Millisecond) 187 188 if established, _ := client.ConnectionEstablished(); established { 189 t.Fatalf("ConnectionEstablished() returned true before Vault server started") 190 } 191 192 // Start Vault 193 v.Start() 194 195 waitForConnection(client, t) 196 } 197 198 func TestVaultClient_ValidateRole(t *testing.T) { 199 v := testutil.NewTestVault(t).Start() 200 defer v.Stop() 201 202 // Set the configs token in a new test role 203 vaultPolicies := map[string]string{ 204 "nomad-role-create": nomadRoleCreatePolicy, 205 "nomad-role-management": nomadRoleManagementPolicy, 206 } 207 data := map[string]interface{}{ 208 "allowed_policies": "default,root", 209 "orphan": true, 210 "renewable": true, 211 "explicit_max_ttl": 10, 212 } 213 v.Config.Token = testVaultRoleAndToken(v, t, vaultPolicies, data, nil) 214 215 logger := log.New(os.Stderr, "", log.LstdFlags) 216 v.Config.ConnectionRetryIntv = 100 * time.Millisecond 217 client, err := NewVaultClient(v.Config, logger, nil) 218 if err != nil { 219 t.Fatalf("failed to build vault client: %v", err) 220 } 221 defer client.Stop() 222 223 // Wait for an error 224 var conn bool 225 var connErr error 226 testutil.WaitForResult(func() (bool, error) { 227 conn, connErr = client.ConnectionEstablished() 228 if conn { 229 return false, fmt.Errorf("Should not connect") 230 } 231 232 if connErr == nil { 233 return false, fmt.Errorf("expect an error") 234 } 235 236 return true, nil 237 }, func(err error) { 238 t.Fatalf("bad: %v", err) 239 }) 240 241 errStr := connErr.Error() 242 if !strings.Contains(errStr, "not allow orphans") { 243 t.Fatalf("Expect orphan error") 244 } 245 if !strings.Contains(errStr, "explicit max ttl") { 246 t.Fatalf("Expect explicit max ttl error") 247 } 248 } 249 250 func TestVaultClient_ValidateRole_NonExistant(t *testing.T) { 251 v := testutil.NewTestVault(t).Start() 252 defer v.Stop() 253 254 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 255 v.Config.Token = v.RootToken 256 logger := log.New(os.Stderr, "", log.LstdFlags) 257 v.Config.ConnectionRetryIntv = 100 * time.Millisecond 258 v.Config.Role = "test-nonexistant" 259 client, err := NewVaultClient(v.Config, logger, nil) 260 if err != nil { 261 t.Fatalf("failed to build vault client: %v", err) 262 } 263 defer client.Stop() 264 265 // Wait for an error 266 var conn bool 267 var connErr error 268 testutil.WaitForResult(func() (bool, error) { 269 conn, connErr = client.ConnectionEstablished() 270 if conn { 271 return false, fmt.Errorf("Should not connect") 272 } 273 274 if connErr == nil { 275 return false, fmt.Errorf("expect an error") 276 } 277 278 return true, nil 279 }, func(err error) { 280 t.Fatalf("bad: %v", err) 281 }) 282 283 errStr := connErr.Error() 284 if !strings.Contains(errStr, "does not exist") { 285 t.Fatalf("Expect orphan error") 286 } 287 } 288 289 func TestVaultClient_ValidateToken(t *testing.T) { 290 v := testutil.NewTestVault(t).Start() 291 defer v.Stop() 292 293 // Set the configs token in a new test role 294 vaultPolicies := map[string]string{ 295 "nomad-role-create": nomadRoleCreatePolicy, 296 "token-lookup": tokenLookupPolicy, 297 } 298 data := map[string]interface{}{ 299 "allowed_policies": "token-lookup,nomad-role-create", 300 "period": 10, 301 } 302 v.Config.Token = testVaultRoleAndToken(v, t, vaultPolicies, data, []string{"token-lookup", "nomad-role-create"}) 303 304 logger := log.New(os.Stderr, "", log.LstdFlags) 305 v.Config.ConnectionRetryIntv = 100 * time.Millisecond 306 client, err := NewVaultClient(v.Config, logger, nil) 307 if err != nil { 308 t.Fatalf("failed to build vault client: %v", err) 309 } 310 defer client.Stop() 311 312 // Wait for an error 313 var conn bool 314 var connErr error 315 testutil.WaitForResult(func() (bool, error) { 316 conn, connErr = client.ConnectionEstablished() 317 if conn { 318 return false, fmt.Errorf("Should not connect") 319 } 320 321 if connErr == nil { 322 return false, fmt.Errorf("expect an error") 323 } 324 325 return true, nil 326 }, func(err error) { 327 t.Fatalf("bad: %v", err) 328 }) 329 330 errStr := connErr.Error() 331 if !strings.Contains(errStr, vaultTokenRevokePath) { 332 t.Fatalf("Expect orphan error") 333 } 334 if !strings.Contains(errStr, fmt.Sprintf(vaultRoleLookupPath, "test")) { 335 t.Fatalf("Expect explicit max ttl error") 336 } 337 if !strings.Contains(errStr, "token must have one of the following") { 338 t.Fatalf("Expect explicit max ttl error") 339 } 340 } 341 342 func TestVaultClient_SetActive(t *testing.T) { 343 v := testutil.NewTestVault(t).Start() 344 defer v.Stop() 345 346 logger := log.New(os.Stderr, "", log.LstdFlags) 347 client, err := NewVaultClient(v.Config, logger, nil) 348 if err != nil { 349 t.Fatalf("failed to build vault client: %v", err) 350 } 351 defer client.Stop() 352 353 waitForConnection(client, t) 354 355 // Do a lookup and expect an error about not being active 356 _, err = client.LookupToken(context.Background(), "123") 357 if err == nil || !strings.Contains(err.Error(), "not active") { 358 t.Fatalf("Expected not-active error: %v", err) 359 } 360 361 client.SetActive(true) 362 363 // Do a lookup of ourselves 364 _, err = client.LookupToken(context.Background(), v.RootToken) 365 if err != nil { 366 t.Fatalf("Unexpected error: %v", err) 367 } 368 } 369 370 // Test that we can update the config and things keep working 371 func TestVaultClient_SetConfig(t *testing.T) { 372 v := testutil.NewTestVault(t).Start() 373 defer v.Stop() 374 375 v2 := testutil.NewTestVault(t).Start() 376 defer v2.Stop() 377 378 // Set the configs token in a new test role 379 v2.Config.Token = defaultTestVaultWhitelistRoleAndToken(v2, t, 20) 380 381 logger := log.New(os.Stderr, "", log.LstdFlags) 382 client, err := NewVaultClient(v.Config, logger, nil) 383 if err != nil { 384 t.Fatalf("failed to build vault client: %v", err) 385 } 386 defer client.Stop() 387 388 waitForConnection(client, t) 389 390 if client.tokenData == nil || len(client.tokenData.Policies) != 1 { 391 t.Fatalf("unexpected token: %v", client.tokenData) 392 } 393 394 // Update the config 395 if err := client.SetConfig(v2.Config); err != nil { 396 t.Fatalf("SetConfig failed: %v", err) 397 } 398 399 waitForConnection(client, t) 400 401 if client.tokenData == nil || len(client.tokenData.Policies) != 3 { 402 t.Fatalf("unexpected token: %v", client.tokenData) 403 } 404 } 405 406 // Test that we can disable vault 407 func TestVaultClient_SetConfig_Disable(t *testing.T) { 408 v := testutil.NewTestVault(t).Start() 409 defer v.Stop() 410 411 logger := log.New(os.Stderr, "", log.LstdFlags) 412 client, err := NewVaultClient(v.Config, logger, nil) 413 if err != nil { 414 t.Fatalf("failed to build vault client: %v", err) 415 } 416 defer client.Stop() 417 418 waitForConnection(client, t) 419 420 if client.tokenData == nil || len(client.tokenData.Policies) != 1 { 421 t.Fatalf("unexpected token: %v", client.tokenData) 422 } 423 424 // Disable vault 425 f := false 426 config := config.VaultConfig{ 427 Enabled: &f, 428 } 429 430 // Update the config 431 if err := client.SetConfig(&config); err != nil { 432 t.Fatalf("SetConfig failed: %v", err) 433 } 434 435 if client.Enabled() || client.Running() { 436 t.Fatalf("SetConfig should have stopped client") 437 } 438 } 439 440 func TestVaultClient_RenewalLoop(t *testing.T) { 441 v := testutil.NewTestVault(t).Start() 442 defer v.Stop() 443 444 // Set the configs token in a new test role 445 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 446 447 // Start the client 448 logger := log.New(os.Stderr, "", log.LstdFlags) 449 client, err := NewVaultClient(v.Config, logger, nil) 450 if err != nil { 451 t.Fatalf("failed to build vault client: %v", err) 452 } 453 defer client.Stop() 454 455 // Sleep 8 seconds and ensure we have a non-zero TTL 456 time.Sleep(8 * time.Second) 457 458 // Get the current TTL 459 a := v.Client.Auth().Token() 460 s2, err := a.Lookup(v.Config.Token) 461 if err != nil { 462 t.Fatalf("failed to lookup token: %v", err) 463 } 464 465 ttl := parseTTLFromLookup(s2, t) 466 if ttl == 0 { 467 t.Fatalf("token renewal failed; ttl %v", ttl) 468 } 469 } 470 471 func parseTTLFromLookup(s *vapi.Secret, t *testing.T) int64 { 472 if s == nil { 473 t.Fatalf("nil secret") 474 } else if s.Data == nil { 475 t.Fatalf("nil data block in secret") 476 } 477 478 ttlRaw, ok := s.Data["ttl"] 479 if !ok { 480 t.Fatalf("no ttl") 481 } 482 483 ttlNumber, ok := ttlRaw.(json.Number) 484 if !ok { 485 t.Fatalf("failed to convert ttl %q to json Number", ttlRaw) 486 } 487 488 ttl, err := ttlNumber.Int64() 489 if err != nil { 490 t.Fatalf("Failed to get ttl from json.Number: %v", err) 491 } 492 493 return ttl 494 } 495 496 func TestVaultClient_LookupToken_Invalid(t *testing.T) { 497 tr := true 498 conf := &config.VaultConfig{ 499 Enabled: &tr, 500 Addr: "http://foobar:12345", 501 Token: structs.GenerateUUID(), 502 } 503 504 // Enable vault but use a bad address so it never establishes a conn 505 logger := log.New(os.Stderr, "", log.LstdFlags) 506 client, err := NewVaultClient(conf, logger, nil) 507 if err != nil { 508 t.Fatalf("failed to build vault client: %v", err) 509 } 510 client.SetActive(true) 511 defer client.Stop() 512 513 _, err = client.LookupToken(context.Background(), "foo") 514 if err == nil || !strings.Contains(err.Error(), "established") { 515 t.Fatalf("Expected error because connection to Vault hasn't been made: %v", err) 516 } 517 } 518 519 func TestVaultClient_LookupToken_Root(t *testing.T) { 520 v := testutil.NewTestVault(t).Start() 521 defer v.Stop() 522 523 logger := log.New(os.Stderr, "", log.LstdFlags) 524 client, err := NewVaultClient(v.Config, logger, nil) 525 if err != nil { 526 t.Fatalf("failed to build vault client: %v", err) 527 } 528 client.SetActive(true) 529 defer client.Stop() 530 531 waitForConnection(client, t) 532 533 // Lookup ourselves 534 s, err := client.LookupToken(context.Background(), v.Config.Token) 535 if err != nil { 536 t.Fatalf("self lookup failed: %v", err) 537 } 538 539 policies, err := PoliciesFrom(s) 540 if err != nil { 541 t.Fatalf("failed to parse policies: %v", err) 542 } 543 544 expected := []string{"root"} 545 if !reflect.DeepEqual(policies, expected) { 546 t.Fatalf("Unexpected policies; got %v; want %v", policies, expected) 547 } 548 549 // Create a token with a different set of policies 550 expected = []string{"default"} 551 req := vapi.TokenCreateRequest{ 552 Policies: expected, 553 } 554 s, err = v.Client.Auth().Token().Create(&req) 555 if err != nil { 556 t.Fatalf("failed to create child token: %v", err) 557 } 558 559 // Get the client token 560 if s == nil || s.Auth == nil { 561 t.Fatalf("bad secret response: %+v", s) 562 } 563 564 // Lookup new child 565 s, err = client.LookupToken(context.Background(), s.Auth.ClientToken) 566 if err != nil { 567 t.Fatalf("self lookup failed: %v", err) 568 } 569 570 policies, err = PoliciesFrom(s) 571 if err != nil { 572 t.Fatalf("failed to parse policies: %v", err) 573 } 574 575 if !reflect.DeepEqual(policies, expected) { 576 t.Fatalf("Unexpected policies; got %v; want %v", policies, expected) 577 } 578 } 579 580 func TestVaultClient_LookupToken_Role(t *testing.T) { 581 v := testutil.NewTestVault(t).Start() 582 defer v.Stop() 583 584 // Set the configs token in a new test role 585 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 586 587 logger := log.New(os.Stderr, "", log.LstdFlags) 588 client, err := NewVaultClient(v.Config, logger, nil) 589 if err != nil { 590 t.Fatalf("failed to build vault client: %v", err) 591 } 592 client.SetActive(true) 593 defer client.Stop() 594 595 waitForConnection(client, t) 596 597 // Lookup ourselves 598 s, err := client.LookupToken(context.Background(), v.Config.Token) 599 if err != nil { 600 t.Fatalf("self lookup failed: %v", err) 601 } 602 603 policies, err := PoliciesFrom(s) 604 if err != nil { 605 t.Fatalf("failed to parse policies: %v", err) 606 } 607 608 expected := []string{"default", "nomad-role-create", "nomad-role-management"} 609 if !reflect.DeepEqual(policies, expected) { 610 t.Fatalf("Unexpected policies; got %v; want %v", policies, expected) 611 } 612 613 // Create a token with a different set of policies 614 expected = []string{"default"} 615 req := vapi.TokenCreateRequest{ 616 Policies: expected, 617 } 618 s, err = v.Client.Auth().Token().Create(&req) 619 if err != nil { 620 t.Fatalf("failed to create child token: %v", err) 621 } 622 623 // Get the client token 624 if s == nil || s.Auth == nil { 625 t.Fatalf("bad secret response: %+v", s) 626 } 627 628 // Lookup new child 629 s, err = client.LookupToken(context.Background(), s.Auth.ClientToken) 630 if err != nil { 631 t.Fatalf("self lookup failed: %v", err) 632 } 633 634 policies, err = PoliciesFrom(s) 635 if err != nil { 636 t.Fatalf("failed to parse policies: %v", err) 637 } 638 639 if !reflect.DeepEqual(policies, expected) { 640 t.Fatalf("Unexpected policies; got %v; want %v", policies, expected) 641 } 642 } 643 644 func TestVaultClient_LookupToken_RateLimit(t *testing.T) { 645 v := testutil.NewTestVault(t).Start() 646 defer v.Stop() 647 648 logger := log.New(os.Stderr, "", log.LstdFlags) 649 client, err := NewVaultClient(v.Config, logger, nil) 650 if err != nil { 651 t.Fatalf("failed to build vault client: %v", err) 652 } 653 client.SetActive(true) 654 defer client.Stop() 655 client.setLimit(rate.Limit(1.0)) 656 657 waitForConnection(client, t) 658 659 // Spin up many requests. These should block 660 ctx, cancel := context.WithCancel(context.Background()) 661 662 cancels := 0 663 numRequests := 10 664 unblock := make(chan struct{}) 665 for i := 0; i < numRequests; i++ { 666 go func() { 667 // Lookup ourselves 668 _, err := client.LookupToken(ctx, v.Config.Token) 669 if err != nil { 670 if err == context.Canceled { 671 cancels += 1 672 return 673 } 674 t.Fatalf("self lookup failed: %v", err) 675 return 676 } 677 678 // Cancel the context 679 close(unblock) 680 }() 681 } 682 683 select { 684 case <-time.After(5 * time.Second): 685 t.Fatalf("timeout") 686 case <-unblock: 687 cancel() 688 } 689 690 desired := numRequests - 1 691 testutil.WaitForResult(func() (bool, error) { 692 if cancels != desired { 693 return false, fmt.Errorf("Incorrect number of cancels; got %d; want %d", cancels, desired) 694 } 695 696 return true, nil 697 }, func(err error) { 698 t.Fatalf("Connection not established") 699 }) 700 } 701 702 func TestVaultClient_CreateToken_Root(t *testing.T) { 703 v := testutil.NewTestVault(t).Start() 704 defer v.Stop() 705 706 logger := log.New(os.Stderr, "", log.LstdFlags) 707 client, err := NewVaultClient(v.Config, logger, nil) 708 if err != nil { 709 t.Fatalf("failed to build vault client: %v", err) 710 } 711 client.SetActive(true) 712 defer client.Stop() 713 714 waitForConnection(client, t) 715 716 // Create an allocation that requires a Vault policy 717 a := mock.Alloc() 718 task := a.Job.TaskGroups[0].Tasks[0] 719 task.Vault = &structs.Vault{Policies: []string{"default"}} 720 721 s, err := client.CreateToken(context.Background(), a, task.Name) 722 if err != nil { 723 t.Fatalf("CreateToken failed: %v", err) 724 } 725 726 // Ensure that created secret is a wrapped token 727 if s == nil || s.WrapInfo == nil { 728 t.Fatalf("Bad secret: %#v", s) 729 } 730 731 d, err := time.ParseDuration(vaultTokenCreateTTL) 732 if err != nil { 733 t.Fatalf("bad: %v", err) 734 } 735 736 if s.WrapInfo.WrappedAccessor == "" { 737 t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor) 738 } else if s.WrapInfo.Token == "" { 739 t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor) 740 } else if s.WrapInfo.TTL != int(d.Seconds()) { 741 t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor) 742 } 743 } 744 745 func TestVaultClient_CreateToken_Whitelist_Role(t *testing.T) { 746 v := testutil.NewTestVault(t).Start() 747 defer v.Stop() 748 749 // Set the configs token in a new test role 750 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 751 752 // Start the client 753 logger := log.New(os.Stderr, "", log.LstdFlags) 754 client, err := NewVaultClient(v.Config, logger, nil) 755 if err != nil { 756 t.Fatalf("failed to build vault client: %v", err) 757 } 758 client.SetActive(true) 759 defer client.Stop() 760 761 waitForConnection(client, t) 762 763 // Create an allocation that requires a Vault policy 764 a := mock.Alloc() 765 task := a.Job.TaskGroups[0].Tasks[0] 766 task.Vault = &structs.Vault{Policies: []string{"default"}} 767 768 s, err := client.CreateToken(context.Background(), a, task.Name) 769 if err != nil { 770 t.Fatalf("CreateToken failed: %v", err) 771 } 772 773 // Ensure that created secret is a wrapped token 774 if s == nil || s.WrapInfo == nil { 775 t.Fatalf("Bad secret: %#v", s) 776 } 777 778 d, err := time.ParseDuration(vaultTokenCreateTTL) 779 if err != nil { 780 t.Fatalf("bad: %v", err) 781 } 782 783 if s.WrapInfo.WrappedAccessor == "" { 784 t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor) 785 } else if s.WrapInfo.Token == "" { 786 t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor) 787 } else if s.WrapInfo.TTL != int(d.Seconds()) { 788 t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor) 789 } 790 } 791 792 func TestVaultClient_CreateToken_Root_Target_Role(t *testing.T) { 793 v := testutil.NewTestVault(t).Start() 794 defer v.Stop() 795 796 // Create the test role 797 defaultTestVaultWhitelistRoleAndToken(v, t, 5) 798 799 // Target the test role 800 v.Config.Role = "test" 801 802 // Start the client 803 logger := log.New(os.Stderr, "", log.LstdFlags) 804 client, err := NewVaultClient(v.Config, logger, nil) 805 if err != nil { 806 t.Fatalf("failed to build vault client: %v", err) 807 } 808 client.SetActive(true) 809 defer client.Stop() 810 811 waitForConnection(client, t) 812 813 // Create an allocation that requires a Vault policy 814 a := mock.Alloc() 815 task := a.Job.TaskGroups[0].Tasks[0] 816 task.Vault = &structs.Vault{Policies: []string{"default"}} 817 818 s, err := client.CreateToken(context.Background(), a, task.Name) 819 if err != nil { 820 t.Fatalf("CreateToken failed: %v", err) 821 } 822 823 // Ensure that created secret is a wrapped token 824 if s == nil || s.WrapInfo == nil { 825 t.Fatalf("Bad secret: %#v", s) 826 } 827 828 d, err := time.ParseDuration(vaultTokenCreateTTL) 829 if err != nil { 830 t.Fatalf("bad: %v", err) 831 } 832 833 if s.WrapInfo.WrappedAccessor == "" { 834 t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor) 835 } else if s.WrapInfo.Token == "" { 836 t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor) 837 } else if s.WrapInfo.TTL != int(d.Seconds()) { 838 t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor) 839 } 840 } 841 842 func TestVaultClient_CreateToken_Blacklist_Role(t *testing.T) { 843 // Need to skip if test is 0.6.4 844 version, err := testutil.VaultVersion() 845 if err != nil { 846 t.Fatalf("failed to determine version: %v", err) 847 } 848 849 if strings.Contains(version, "v0.6.4") { 850 t.Skipf("Vault has a regression in v0.6.4 that this test hits") 851 } 852 853 v := testutil.NewTestVault(t).Start() 854 defer v.Stop() 855 856 // Set the configs token in a new test role 857 v.Config.Token = defaultTestVaultBlacklistRoleAndToken(v, t, 5) 858 v.Config.Role = "test" 859 860 // Start the client 861 logger := log.New(os.Stderr, "", log.LstdFlags) 862 client, err := NewVaultClient(v.Config, logger, nil) 863 if err != nil { 864 t.Fatalf("failed to build vault client: %v", err) 865 } 866 client.SetActive(true) 867 defer client.Stop() 868 869 waitForConnection(client, t) 870 871 // Create an allocation that requires a Vault policy 872 a := mock.Alloc() 873 task := a.Job.TaskGroups[0].Tasks[0] 874 task.Vault = &structs.Vault{Policies: []string{"secrets"}} 875 876 s, err := client.CreateToken(context.Background(), a, task.Name) 877 if err != nil { 878 t.Fatalf("CreateToken failed: %v", err) 879 } 880 881 // Ensure that created secret is a wrapped token 882 if s == nil || s.WrapInfo == nil { 883 t.Fatalf("Bad secret: %#v", s) 884 } 885 886 d, err := time.ParseDuration(vaultTokenCreateTTL) 887 if err != nil { 888 t.Fatalf("bad: %v", err) 889 } 890 891 if s.WrapInfo.WrappedAccessor == "" { 892 t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor) 893 } else if s.WrapInfo.Token == "" { 894 t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor) 895 } else if s.WrapInfo.TTL != int(d.Seconds()) { 896 t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor) 897 } 898 } 899 900 func TestVaultClient_CreateToken_Role_InvalidToken(t *testing.T) { 901 v := testutil.NewTestVault(t).Start() 902 defer v.Stop() 903 904 // Set the configs token in a new test role 905 defaultTestVaultWhitelistRoleAndToken(v, t, 5) 906 v.Config.Token = "foo-bar" 907 908 // Start the client 909 logger := log.New(os.Stderr, "", log.LstdFlags) 910 client, err := NewVaultClient(v.Config, logger, nil) 911 if err != nil { 912 t.Fatalf("failed to build vault client: %v", err) 913 } 914 client.SetActive(true) 915 defer client.Stop() 916 917 testutil.WaitForResult(func() (bool, error) { 918 established, err := client.ConnectionEstablished() 919 if established { 920 return false, fmt.Errorf("Shouldn't establish") 921 } 922 923 return err != nil, nil 924 }, func(err error) { 925 t.Fatalf("Connection not established") 926 }) 927 928 // Create an allocation that requires a Vault policy 929 a := mock.Alloc() 930 task := a.Job.TaskGroups[0].Tasks[0] 931 task.Vault = &structs.Vault{Policies: []string{"default"}} 932 933 _, err = client.CreateToken(context.Background(), a, task.Name) 934 if err == nil || !strings.Contains(err.Error(), "Connection to Vault failed") { 935 t.Fatalf("CreateToken should have failed: %v", err) 936 } 937 } 938 939 func TestVaultClient_CreateToken_Role_Unrecoverable(t *testing.T) { 940 v := testutil.NewTestVault(t).Start() 941 defer v.Stop() 942 943 // Set the configs token in a new test role 944 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 945 946 // Start the client 947 logger := log.New(os.Stderr, "", log.LstdFlags) 948 client, err := NewVaultClient(v.Config, logger, nil) 949 if err != nil { 950 t.Fatalf("failed to build vault client: %v", err) 951 } 952 client.SetActive(true) 953 defer client.Stop() 954 955 waitForConnection(client, t) 956 957 // Create an allocation that requires a Vault policy 958 a := mock.Alloc() 959 task := a.Job.TaskGroups[0].Tasks[0] 960 task.Vault = &structs.Vault{Policies: []string{"unknown_policy"}} 961 962 _, err = client.CreateToken(context.Background(), a, task.Name) 963 if err == nil { 964 t.Fatalf("CreateToken should have failed: %v", err) 965 } 966 967 _, ok := err.(structs.Recoverable) 968 if ok { 969 t.Fatalf("CreateToken should not be a recoverable error type: %v (%T)", err, err) 970 } 971 } 972 973 func TestVaultClient_CreateToken_Prestart(t *testing.T) { 974 v := testutil.NewTestVault(t) 975 defer v.Stop() 976 977 logger := log.New(os.Stderr, "", log.LstdFlags) 978 client, err := NewVaultClient(v.Config, logger, nil) 979 if err != nil { 980 t.Fatalf("failed to build vault client: %v", err) 981 } 982 client.SetActive(true) 983 defer client.Stop() 984 985 // Create an allocation that requires a Vault policy 986 a := mock.Alloc() 987 task := a.Job.TaskGroups[0].Tasks[0] 988 task.Vault = &structs.Vault{Policies: []string{"default"}} 989 990 _, err = client.CreateToken(context.Background(), a, task.Name) 991 if err == nil { 992 t.Fatalf("CreateToken should have failed: %v", err) 993 } 994 995 if rerr, ok := err.(*structs.RecoverableError); !ok { 996 t.Fatalf("Err should have been type recoverable error") 997 } else if ok && !rerr.IsRecoverable() { 998 t.Fatalf("Err should have been recoverable") 999 } 1000 } 1001 1002 func TestVaultClient_RevokeTokens_PreEstablishs(t *testing.T) { 1003 v := testutil.NewTestVault(t) 1004 logger := log.New(os.Stderr, "", log.LstdFlags) 1005 client, err := NewVaultClient(v.Config, logger, nil) 1006 if err != nil { 1007 t.Fatalf("failed to build vault client: %v", err) 1008 } 1009 client.SetActive(true) 1010 defer client.Stop() 1011 1012 // Create some VaultAccessors 1013 vas := []*structs.VaultAccessor{ 1014 mock.VaultAccessor(), 1015 mock.VaultAccessor(), 1016 } 1017 1018 if err := client.RevokeTokens(context.Background(), vas, false); err != nil { 1019 t.Fatalf("RevokeTokens failed: %v", err) 1020 } 1021 1022 // Wasn't committed 1023 if len(client.revoking) != 0 { 1024 t.Fatalf("didn't add to revoke loop") 1025 } 1026 1027 if err := client.RevokeTokens(context.Background(), vas, true); err != nil { 1028 t.Fatalf("RevokeTokens failed: %v", err) 1029 } 1030 1031 // Was committed 1032 if len(client.revoking) != 2 { 1033 t.Fatalf("didn't add to revoke loop") 1034 } 1035 1036 if client.Stats().TrackedForRevoke != 2 { 1037 t.Fatalf("didn't add to revoke loop") 1038 } 1039 } 1040 1041 func TestVaultClient_RevokeTokens_Root(t *testing.T) { 1042 v := testutil.NewTestVault(t).Start() 1043 defer v.Stop() 1044 1045 purged := 0 1046 purge := func(accessors []*structs.VaultAccessor) error { 1047 purged += len(accessors) 1048 return nil 1049 } 1050 1051 logger := log.New(os.Stderr, "", log.LstdFlags) 1052 client, err := NewVaultClient(v.Config, logger, purge) 1053 if err != nil { 1054 t.Fatalf("failed to build vault client: %v", err) 1055 } 1056 client.SetActive(true) 1057 defer client.Stop() 1058 1059 waitForConnection(client, t) 1060 1061 // Create some vault tokens 1062 auth := v.Client.Auth().Token() 1063 req := vapi.TokenCreateRequest{ 1064 Policies: []string{"default"}, 1065 } 1066 t1, err := auth.Create(&req) 1067 if err != nil { 1068 t.Fatalf("Failed to create vault token: %v", err) 1069 } 1070 if t1 == nil || t1.Auth == nil { 1071 t.Fatalf("bad secret response: %+v", t1) 1072 } 1073 t2, err := auth.Create(&req) 1074 if err != nil { 1075 t.Fatalf("Failed to create vault token: %v", err) 1076 } 1077 if t2 == nil || t2.Auth == nil { 1078 t.Fatalf("bad secret response: %+v", t2) 1079 } 1080 1081 // Create two VaultAccessors 1082 vas := []*structs.VaultAccessor{ 1083 &structs.VaultAccessor{Accessor: t1.Auth.Accessor}, 1084 &structs.VaultAccessor{Accessor: t2.Auth.Accessor}, 1085 } 1086 1087 // Issue a token revocation 1088 if err := client.RevokeTokens(context.Background(), vas, true); err != nil { 1089 t.Fatalf("RevokeTokens failed: %v", err) 1090 } 1091 1092 // Lookup the token and make sure we get an error 1093 if s, err := auth.Lookup(t1.Auth.ClientToken); err == nil { 1094 t.Fatalf("Revoked token lookup didn't fail: %+v", s) 1095 } 1096 if s, err := auth.Lookup(t2.Auth.ClientToken); err == nil { 1097 t.Fatalf("Revoked token lookup didn't fail: %+v", s) 1098 } 1099 1100 if purged != 2 { 1101 t.Fatalf("Expected purged 2; got %d", purged) 1102 } 1103 } 1104 1105 func TestVaultClient_RevokeTokens_Role(t *testing.T) { 1106 v := testutil.NewTestVault(t).Start() 1107 defer v.Stop() 1108 1109 // Set the configs token in a new test role 1110 v.Config.Token = defaultTestVaultWhitelistRoleAndToken(v, t, 5) 1111 1112 purged := 0 1113 purge := func(accessors []*structs.VaultAccessor) error { 1114 purged += len(accessors) 1115 return nil 1116 } 1117 1118 logger := log.New(os.Stderr, "", log.LstdFlags) 1119 client, err := NewVaultClient(v.Config, logger, purge) 1120 if err != nil { 1121 t.Fatalf("failed to build vault client: %v", err) 1122 } 1123 client.SetActive(true) 1124 defer client.Stop() 1125 1126 waitForConnection(client, t) 1127 1128 // Create some vault tokens 1129 auth := v.Client.Auth().Token() 1130 req := vapi.TokenCreateRequest{ 1131 Policies: []string{"default"}, 1132 } 1133 t1, err := auth.Create(&req) 1134 if err != nil { 1135 t.Fatalf("Failed to create vault token: %v", err) 1136 } 1137 if t1 == nil || t1.Auth == nil { 1138 t.Fatalf("bad secret response: %+v", t1) 1139 } 1140 t2, err := auth.Create(&req) 1141 if err != nil { 1142 t.Fatalf("Failed to create vault token: %v", err) 1143 } 1144 if t2 == nil || t2.Auth == nil { 1145 t.Fatalf("bad secret response: %+v", t2) 1146 } 1147 1148 // Create two VaultAccessors 1149 vas := []*structs.VaultAccessor{ 1150 &structs.VaultAccessor{Accessor: t1.Auth.Accessor}, 1151 &structs.VaultAccessor{Accessor: t2.Auth.Accessor}, 1152 } 1153 1154 // Issue a token revocation 1155 if err := client.RevokeTokens(context.Background(), vas, true); err != nil { 1156 t.Fatalf("RevokeTokens failed: %v", err) 1157 } 1158 1159 // Lookup the token and make sure we get an error 1160 if purged != 2 { 1161 t.Fatalf("Expected purged 2; got %d", purged) 1162 } 1163 if s, err := auth.Lookup(t1.Auth.ClientToken); err == nil { 1164 t.Fatalf("Revoked token lookup didn't fail: %+v", s) 1165 } 1166 if s, err := auth.Lookup(t2.Auth.ClientToken); err == nil { 1167 t.Fatalf("Revoked token lookup didn't fail: %+v", s) 1168 } 1169 } 1170 1171 func waitForConnection(v *vaultClient, t *testing.T) { 1172 testutil.WaitForResult(func() (bool, error) { 1173 return v.ConnectionEstablished() 1174 }, func(err error) { 1175 t.Fatalf("Connection not established") 1176 }) 1177 }