github.com/maier/nomad@v0.4.1-0.20161110003312-a9e3d0b8549d/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  	// authPolicy is a policy that allows token creation operations
    25  	authPolicy = `path "auth/token/create/test" {
    26  	capabilities = ["create", "update"]
    27  }
    28  
    29  path "auth/token/lookup/*" {
    30  	capabilities = ["read"]
    31  }
    32  
    33  path "auth/token/roles/test" {
    34  	capabilities = ["read"]
    35  }
    36  
    37  path "/auth/token/revoke-accessor/*" {
    38  	capabilities = ["update"]
    39  }
    40  `
    41  )
    42  
    43  func TestVaultClient_BadConfig(t *testing.T) {
    44  	conf := &config.VaultConfig{}
    45  	logger := log.New(os.Stderr, "", log.LstdFlags)
    46  
    47  	// Should be no error since Vault is not enabled
    48  	_, err := NewVaultClient(nil, logger, nil)
    49  	if err == nil || !strings.Contains(err.Error(), "valid") {
    50  		t.Fatalf("expected config error: %v", err)
    51  	}
    52  
    53  	tr := true
    54  	conf.Enabled = &tr
    55  	_, err = NewVaultClient(conf, logger, nil)
    56  	if err == nil || !strings.Contains(err.Error(), "token must be set") {
    57  		t.Fatalf("Expected token unset error: %v", err)
    58  	}
    59  
    60  	conf.Token = "123"
    61  	_, err = NewVaultClient(conf, logger, nil)
    62  	if err == nil || !strings.Contains(err.Error(), "address must be set") {
    63  		t.Fatalf("Expected address unset error: %v", err)
    64  	}
    65  }
    66  
    67  // Test that the Vault Client can establish a connection even if it is started
    68  // before Vault is available.
    69  func TestVaultClient_EstablishConnection(t *testing.T) {
    70  	v := testutil.NewTestVault(t)
    71  	defer v.Stop()
    72  
    73  	logger := log.New(os.Stderr, "", log.LstdFlags)
    74  	v.Config.ConnectionRetryIntv = 100 * time.Millisecond
    75  	client, err := NewVaultClient(v.Config, logger, nil)
    76  	if err != nil {
    77  		t.Fatalf("failed to build vault client: %v", err)
    78  	}
    79  	defer client.Stop()
    80  
    81  	// Sleep a little while and check that no connection has been established.
    82  	time.Sleep(100 * time.Duration(testutil.TestMultiplier()) * time.Millisecond)
    83  
    84  	if established, _ := client.ConnectionEstablished(); established {
    85  		t.Fatalf("ConnectionEstablished() returned true before Vault server started")
    86  	}
    87  
    88  	// Start Vault
    89  	v.Start()
    90  
    91  	waitForConnection(client, t)
    92  }
    93  
    94  func TestVaultClient_ValidateRole(t *testing.T) {
    95  	v := testutil.NewTestVault(t).Start()
    96  	defer v.Stop()
    97  
    98  	// Set the configs token in a new test role
    99  	data := map[string]interface{}{
   100  		"allowed_policies": "default,root",
   101  		"orphan":           true,
   102  		"renewable":        true,
   103  		"explicit_max_ttl": 10,
   104  	}
   105  	v.Config.Token = testVaultRoleAndToken(v, t, data)
   106  
   107  	logger := log.New(os.Stderr, "", log.LstdFlags)
   108  	v.Config.ConnectionRetryIntv = 100 * time.Millisecond
   109  	client, err := NewVaultClient(v.Config, logger, nil)
   110  	if err != nil {
   111  		t.Fatalf("failed to build vault client: %v", err)
   112  	}
   113  	defer client.Stop()
   114  
   115  	// Wait for an error
   116  	var conn bool
   117  	var connErr error
   118  	testutil.WaitForResult(func() (bool, error) {
   119  		conn, connErr = client.ConnectionEstablished()
   120  		if conn {
   121  			return false, fmt.Errorf("Should not connect")
   122  		}
   123  
   124  		if connErr == nil {
   125  			return false, fmt.Errorf("expect an error")
   126  		}
   127  
   128  		return true, nil
   129  	}, func(err error) {
   130  		t.Fatalf("bad: %v", err)
   131  	})
   132  
   133  	errStr := connErr.Error()
   134  	if !strings.Contains(errStr, "not allow orphans") {
   135  		t.Fatalf("Expect orphan error")
   136  	}
   137  	if !strings.Contains(errStr, "explicit max ttl") {
   138  		t.Fatalf("Expect explicit max ttl error")
   139  	}
   140  }
   141  
   142  func TestVaultClient_SetActive(t *testing.T) {
   143  	v := testutil.NewTestVault(t).Start()
   144  	defer v.Stop()
   145  
   146  	logger := log.New(os.Stderr, "", log.LstdFlags)
   147  	client, err := NewVaultClient(v.Config, logger, nil)
   148  	if err != nil {
   149  		t.Fatalf("failed to build vault client: %v", err)
   150  	}
   151  	defer client.Stop()
   152  
   153  	waitForConnection(client, t)
   154  
   155  	// Do a lookup and expect an error about not being active
   156  	_, err = client.LookupToken(context.Background(), "123")
   157  	if err == nil || !strings.Contains(err.Error(), "not active") {
   158  		t.Fatalf("Expected not-active error: %v", err)
   159  	}
   160  
   161  	client.SetActive(true)
   162  
   163  	// Do a lookup of ourselves
   164  	_, err = client.LookupToken(context.Background(), v.RootToken)
   165  	if err != nil {
   166  		t.Fatalf("Unexpected error: %v", err)
   167  	}
   168  }
   169  
   170  // Test that we can update the config and things keep working
   171  func TestVaultClient_SetConfig(t *testing.T) {
   172  	v := testutil.NewTestVault(t).Start()
   173  	defer v.Stop()
   174  
   175  	v2 := testutil.NewTestVault(t).Start()
   176  	defer v2.Stop()
   177  
   178  	// Set the configs token in a new test role
   179  	v2.Config.Token = defaultTestVaultRoleAndToken(v2, t, 20)
   180  
   181  	logger := log.New(os.Stderr, "", log.LstdFlags)
   182  	client, err := NewVaultClient(v.Config, logger, nil)
   183  	if err != nil {
   184  		t.Fatalf("failed to build vault client: %v", err)
   185  	}
   186  	defer client.Stop()
   187  
   188  	waitForConnection(client, t)
   189  
   190  	if client.tokenData == nil || len(client.tokenData.Policies) != 1 {
   191  		t.Fatalf("unexpected token: %v", client.tokenData)
   192  	}
   193  
   194  	// Update the config
   195  	if err := client.SetConfig(v2.Config); err != nil {
   196  		t.Fatalf("SetConfig failed: %v", err)
   197  	}
   198  
   199  	waitForConnection(client, t)
   200  
   201  	if client.tokenData == nil || len(client.tokenData.Policies) != 2 {
   202  		t.Fatalf("unexpected token: %v", client.tokenData)
   203  	}
   204  }
   205  
   206  // defaultTestVaultRoleAndToken creates a test Vault role and returns a token
   207  // created in that role
   208  func defaultTestVaultRoleAndToken(v *testutil.TestVault, t *testing.T, rolePeriod int) string {
   209  	d := make(map[string]interface{}, 2)
   210  	d["allowed_policies"] = "auth"
   211  	d["period"] = rolePeriod
   212  	return testVaultRoleAndToken(v, t, d)
   213  }
   214  
   215  // testVaultRoleAndToken creates a test Vault role with the specified data and
   216  // returns a token created in that role
   217  func testVaultRoleAndToken(v *testutil.TestVault, t *testing.T, data map[string]interface{}) string {
   218  	// Build the auth policy
   219  	sys := v.Client.Sys()
   220  	if err := sys.PutPolicy("auth", authPolicy); err != nil {
   221  		t.Fatalf("failed to create auth policy: %v", err)
   222  	}
   223  
   224  	// Build a role
   225  	l := v.Client.Logical()
   226  	l.Write("auth/token/roles/test", data)
   227  
   228  	// Create a new token with the role
   229  	a := v.Client.Auth().Token()
   230  	req := vapi.TokenCreateRequest{}
   231  	s, err := a.CreateWithRole(&req, "test")
   232  	if err != nil {
   233  		t.Fatalf("failed to create child token: %v", err)
   234  	}
   235  
   236  	// Get the client token
   237  	if s == nil || s.Auth == nil {
   238  		t.Fatalf("bad secret response: %+v", s)
   239  	}
   240  
   241  	return s.Auth.ClientToken
   242  }
   243  
   244  func TestVaultClient_RenewalLoop(t *testing.T) {
   245  	v := testutil.NewTestVault(t).Start()
   246  	defer v.Stop()
   247  
   248  	// Set the configs token in a new test role
   249  	v.Config.Token = defaultTestVaultRoleAndToken(v, t, 5)
   250  
   251  	// Start the client
   252  	logger := log.New(os.Stderr, "", log.LstdFlags)
   253  	client, err := NewVaultClient(v.Config, logger, nil)
   254  	if err != nil {
   255  		t.Fatalf("failed to build vault client: %v", err)
   256  	}
   257  	defer client.Stop()
   258  
   259  	// Sleep 8 seconds and ensure we have a non-zero TTL
   260  	time.Sleep(8 * time.Second)
   261  
   262  	// Get the current TTL
   263  	a := v.Client.Auth().Token()
   264  	s2, err := a.Lookup(v.Config.Token)
   265  	if err != nil {
   266  		t.Fatalf("failed to lookup token: %v", err)
   267  	}
   268  
   269  	ttl := parseTTLFromLookup(s2, t)
   270  	if ttl == 0 {
   271  		t.Fatalf("token renewal failed; ttl %v", ttl)
   272  	}
   273  }
   274  
   275  func parseTTLFromLookup(s *vapi.Secret, t *testing.T) int64 {
   276  	if s == nil {
   277  		t.Fatalf("nil secret")
   278  	} else if s.Data == nil {
   279  		t.Fatalf("nil data block in secret")
   280  	}
   281  
   282  	ttlRaw, ok := s.Data["ttl"]
   283  	if !ok {
   284  		t.Fatalf("no ttl")
   285  	}
   286  
   287  	ttlNumber, ok := ttlRaw.(json.Number)
   288  	if !ok {
   289  		t.Fatalf("failed to convert ttl %q to json Number", ttlRaw)
   290  	}
   291  
   292  	ttl, err := ttlNumber.Int64()
   293  	if err != nil {
   294  		t.Fatalf("Failed to get ttl from json.Number: %v", err)
   295  	}
   296  
   297  	return ttl
   298  }
   299  
   300  func TestVaultClient_LookupToken_Invalid(t *testing.T) {
   301  	tr := true
   302  	conf := &config.VaultConfig{
   303  		Enabled: &tr,
   304  		Addr:    "http://foobar:12345",
   305  		Token:   structs.GenerateUUID(),
   306  	}
   307  
   308  	// Enable vault but use a bad address so it never establishes a conn
   309  	logger := log.New(os.Stderr, "", log.LstdFlags)
   310  	client, err := NewVaultClient(conf, logger, nil)
   311  	if err != nil {
   312  		t.Fatalf("failed to build vault client: %v", err)
   313  	}
   314  	client.SetActive(true)
   315  	defer client.Stop()
   316  
   317  	_, err = client.LookupToken(context.Background(), "foo")
   318  	if err == nil || !strings.Contains(err.Error(), "established") {
   319  		t.Fatalf("Expected error because connection to Vault hasn't been made: %v", err)
   320  	}
   321  }
   322  
   323  func TestVaultClient_LookupToken_Root(t *testing.T) {
   324  	v := testutil.NewTestVault(t).Start()
   325  	defer v.Stop()
   326  
   327  	logger := log.New(os.Stderr, "", log.LstdFlags)
   328  	client, err := NewVaultClient(v.Config, logger, nil)
   329  	if err != nil {
   330  		t.Fatalf("failed to build vault client: %v", err)
   331  	}
   332  	client.SetActive(true)
   333  	defer client.Stop()
   334  
   335  	waitForConnection(client, t)
   336  
   337  	// Lookup ourselves
   338  	s, err := client.LookupToken(context.Background(), v.Config.Token)
   339  	if err != nil {
   340  		t.Fatalf("self lookup failed: %v", err)
   341  	}
   342  
   343  	policies, err := PoliciesFrom(s)
   344  	if err != nil {
   345  		t.Fatalf("failed to parse policies: %v", err)
   346  	}
   347  
   348  	expected := []string{"root"}
   349  	if !reflect.DeepEqual(policies, expected) {
   350  		t.Fatalf("Unexpected policies; got %v; want %v", policies, expected)
   351  	}
   352  
   353  	// Create a token with a different set of policies
   354  	expected = []string{"default"}
   355  	req := vapi.TokenCreateRequest{
   356  		Policies: expected,
   357  	}
   358  	s, err = v.Client.Auth().Token().Create(&req)
   359  	if err != nil {
   360  		t.Fatalf("failed to create child token: %v", err)
   361  	}
   362  
   363  	// Get the client token
   364  	if s == nil || s.Auth == nil {
   365  		t.Fatalf("bad secret response: %+v", s)
   366  	}
   367  
   368  	// Lookup new child
   369  	s, err = client.LookupToken(context.Background(), s.Auth.ClientToken)
   370  	if err != nil {
   371  		t.Fatalf("self lookup failed: %v", err)
   372  	}
   373  
   374  	policies, err = PoliciesFrom(s)
   375  	if err != nil {
   376  		t.Fatalf("failed to parse policies: %v", err)
   377  	}
   378  
   379  	if !reflect.DeepEqual(policies, expected) {
   380  		t.Fatalf("Unexpected policies; got %v; want %v", policies, expected)
   381  	}
   382  }
   383  
   384  func TestVaultClient_LookupToken_Role(t *testing.T) {
   385  	v := testutil.NewTestVault(t).Start()
   386  	defer v.Stop()
   387  
   388  	// Set the configs token in a new test role
   389  	v.Config.Token = defaultTestVaultRoleAndToken(v, t, 5)
   390  
   391  	logger := log.New(os.Stderr, "", log.LstdFlags)
   392  	client, err := NewVaultClient(v.Config, logger, nil)
   393  	if err != nil {
   394  		t.Fatalf("failed to build vault client: %v", err)
   395  	}
   396  	client.SetActive(true)
   397  	defer client.Stop()
   398  
   399  	waitForConnection(client, t)
   400  
   401  	// Lookup ourselves
   402  	s, err := client.LookupToken(context.Background(), v.Config.Token)
   403  	if err != nil {
   404  		t.Fatalf("self lookup failed: %v", err)
   405  	}
   406  
   407  	policies, err := PoliciesFrom(s)
   408  	if err != nil {
   409  		t.Fatalf("failed to parse policies: %v", err)
   410  	}
   411  
   412  	expected := []string{"auth", "default"}
   413  	if !reflect.DeepEqual(policies, expected) {
   414  		t.Fatalf("Unexpected policies; got %v; want %v", policies, expected)
   415  	}
   416  
   417  	// Create a token with a different set of policies
   418  	expected = []string{"default"}
   419  	req := vapi.TokenCreateRequest{
   420  		Policies: expected,
   421  	}
   422  	s, err = v.Client.Auth().Token().Create(&req)
   423  	if err != nil {
   424  		t.Fatalf("failed to create child token: %v", err)
   425  	}
   426  
   427  	// Get the client token
   428  	if s == nil || s.Auth == nil {
   429  		t.Fatalf("bad secret response: %+v", s)
   430  	}
   431  
   432  	// Lookup new child
   433  	s, err = client.LookupToken(context.Background(), s.Auth.ClientToken)
   434  	if err != nil {
   435  		t.Fatalf("self lookup failed: %v", err)
   436  	}
   437  
   438  	policies, err = PoliciesFrom(s)
   439  	if err != nil {
   440  		t.Fatalf("failed to parse policies: %v", err)
   441  	}
   442  
   443  	if !reflect.DeepEqual(policies, expected) {
   444  		t.Fatalf("Unexpected policies; got %v; want %v", policies, expected)
   445  	}
   446  }
   447  
   448  func TestVaultClient_LookupToken_RateLimit(t *testing.T) {
   449  	v := testutil.NewTestVault(t).Start()
   450  	defer v.Stop()
   451  
   452  	logger := log.New(os.Stderr, "", log.LstdFlags)
   453  	client, err := NewVaultClient(v.Config, logger, nil)
   454  	if err != nil {
   455  		t.Fatalf("failed to build vault client: %v", err)
   456  	}
   457  	client.SetActive(true)
   458  	defer client.Stop()
   459  	client.setLimit(rate.Limit(1.0))
   460  
   461  	waitForConnection(client, t)
   462  
   463  	// Spin up many requests. These should block
   464  	ctx, cancel := context.WithCancel(context.Background())
   465  
   466  	cancels := 0
   467  	numRequests := 10
   468  	unblock := make(chan struct{})
   469  	for i := 0; i < numRequests; i++ {
   470  		go func() {
   471  			// Ensure all the goroutines are made
   472  			time.Sleep(10 * time.Millisecond)
   473  
   474  			// Lookup ourselves
   475  			_, err := client.LookupToken(ctx, v.Config.Token)
   476  			if err != nil {
   477  				if err == context.Canceled {
   478  					cancels += 1
   479  					return
   480  				}
   481  				t.Fatalf("self lookup failed: %v", err)
   482  				return
   483  			}
   484  
   485  			// Cancel the context
   486  			cancel()
   487  			time.AfterFunc(1*time.Second, func() { close(unblock) })
   488  		}()
   489  	}
   490  
   491  	select {
   492  	case <-time.After(5 * time.Second):
   493  		t.Fatalf("timeout")
   494  	case <-unblock:
   495  	}
   496  
   497  	desired := numRequests - 1
   498  	if cancels != desired {
   499  		t.Fatalf("Incorrect number of cancels; got %d; want %d", cancels, desired)
   500  	}
   501  }
   502  
   503  func TestVaultClient_CreateToken_Root(t *testing.T) {
   504  	v := testutil.NewTestVault(t).Start()
   505  	defer v.Stop()
   506  
   507  	logger := log.New(os.Stderr, "", log.LstdFlags)
   508  	client, err := NewVaultClient(v.Config, logger, nil)
   509  	if err != nil {
   510  		t.Fatalf("failed to build vault client: %v", err)
   511  	}
   512  	client.SetActive(true)
   513  	defer client.Stop()
   514  
   515  	waitForConnection(client, t)
   516  
   517  	// Create an allocation that requires a Vault policy
   518  	a := mock.Alloc()
   519  	task := a.Job.TaskGroups[0].Tasks[0]
   520  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   521  
   522  	s, err := client.CreateToken(context.Background(), a, task.Name)
   523  	if err != nil {
   524  		t.Fatalf("CreateToken failed: %v", err)
   525  	}
   526  
   527  	// Ensure that created secret is a wrapped token
   528  	if s == nil || s.WrapInfo == nil {
   529  		t.Fatalf("Bad secret: %#v", s)
   530  	}
   531  
   532  	d, err := time.ParseDuration(vaultTokenCreateTTL)
   533  	if err != nil {
   534  		t.Fatalf("bad: %v", err)
   535  	}
   536  
   537  	if s.WrapInfo.WrappedAccessor == "" {
   538  		t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor)
   539  	} else if s.WrapInfo.Token == "" {
   540  		t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor)
   541  	} else if s.WrapInfo.TTL != int(d.Seconds()) {
   542  		t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor)
   543  	}
   544  }
   545  
   546  func TestVaultClient_CreateToken_Role(t *testing.T) {
   547  	v := testutil.NewTestVault(t).Start()
   548  	defer v.Stop()
   549  
   550  	// Set the configs token in a new test role
   551  	v.Config.Token = defaultTestVaultRoleAndToken(v, t, 5)
   552  
   553  	// Start the client
   554  	logger := log.New(os.Stderr, "", log.LstdFlags)
   555  	client, err := NewVaultClient(v.Config, logger, nil)
   556  	if err != nil {
   557  		t.Fatalf("failed to build vault client: %v", err)
   558  	}
   559  	client.SetActive(true)
   560  	defer client.Stop()
   561  
   562  	waitForConnection(client, t)
   563  
   564  	// Create an allocation that requires a Vault policy
   565  	a := mock.Alloc()
   566  	task := a.Job.TaskGroups[0].Tasks[0]
   567  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   568  
   569  	s, err := client.CreateToken(context.Background(), a, task.Name)
   570  	if err != nil {
   571  		t.Fatalf("CreateToken failed: %v", err)
   572  	}
   573  
   574  	// Ensure that created secret is a wrapped token
   575  	if s == nil || s.WrapInfo == nil {
   576  		t.Fatalf("Bad secret: %#v", s)
   577  	}
   578  
   579  	d, err := time.ParseDuration(vaultTokenCreateTTL)
   580  	if err != nil {
   581  		t.Fatalf("bad: %v", err)
   582  	}
   583  
   584  	if s.WrapInfo.WrappedAccessor == "" {
   585  		t.Fatalf("Bad accessor: %v", s.WrapInfo.WrappedAccessor)
   586  	} else if s.WrapInfo.Token == "" {
   587  		t.Fatalf("Bad token: %v", s.WrapInfo.WrappedAccessor)
   588  	} else if s.WrapInfo.TTL != int(d.Seconds()) {
   589  		t.Fatalf("Bad ttl: %v", s.WrapInfo.WrappedAccessor)
   590  	}
   591  }
   592  
   593  func TestVaultClient_CreateToken_Role_InvalidToken(t *testing.T) {
   594  	v := testutil.NewTestVault(t).Start()
   595  	defer v.Stop()
   596  
   597  	// Set the configs token in a new test role
   598  	defaultTestVaultRoleAndToken(v, t, 5)
   599  	v.Config.Token = "foo-bar"
   600  
   601  	// Start the client
   602  	logger := log.New(os.Stderr, "", log.LstdFlags)
   603  	client, err := NewVaultClient(v.Config, logger, nil)
   604  	if err != nil {
   605  		t.Fatalf("failed to build vault client: %v", err)
   606  	}
   607  	client.SetActive(true)
   608  	defer client.Stop()
   609  
   610  	testutil.WaitForResult(func() (bool, error) {
   611  		established, err := client.ConnectionEstablished()
   612  		if established {
   613  			return false, fmt.Errorf("Shouldn't establish")
   614  		}
   615  
   616  		return err != nil, nil
   617  	}, func(err error) {
   618  		t.Fatalf("Connection not established")
   619  	})
   620  
   621  	// Create an allocation that requires a Vault policy
   622  	a := mock.Alloc()
   623  	task := a.Job.TaskGroups[0].Tasks[0]
   624  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   625  
   626  	_, err = client.CreateToken(context.Background(), a, task.Name)
   627  	if err == nil || !strings.Contains(err.Error(), "Connection to Vault failed") {
   628  		t.Fatalf("CreateToken should have failed: %v", err)
   629  	}
   630  }
   631  
   632  func TestVaultClient_CreateToken_Role_Unrecoverable(t *testing.T) {
   633  	v := testutil.NewTestVault(t).Start()
   634  	defer v.Stop()
   635  
   636  	// Set the configs token in a new test role
   637  	v.Config.Token = defaultTestVaultRoleAndToken(v, t, 5)
   638  
   639  	// Start the client
   640  	logger := log.New(os.Stderr, "", log.LstdFlags)
   641  	client, err := NewVaultClient(v.Config, logger, nil)
   642  	if err != nil {
   643  		t.Fatalf("failed to build vault client: %v", err)
   644  	}
   645  	client.SetActive(true)
   646  	defer client.Stop()
   647  
   648  	waitForConnection(client, t)
   649  
   650  	// Create an allocation that requires a Vault policy
   651  	a := mock.Alloc()
   652  	task := a.Job.TaskGroups[0].Tasks[0]
   653  	task.Vault = &structs.Vault{Policies: []string{"unknown_policy"}}
   654  
   655  	_, err = client.CreateToken(context.Background(), a, task.Name)
   656  	if err == nil {
   657  		t.Fatalf("CreateToken should have failed: %v", err)
   658  	}
   659  
   660  	_, ok := err.(*structs.RecoverableError)
   661  	if ok {
   662  		t.Fatalf("CreateToken should not be a recoverable error type: %v", err)
   663  	}
   664  }
   665  
   666  func TestVaultClient_CreateToken_Prestart(t *testing.T) {
   667  	v := testutil.NewTestVault(t)
   668  	defer v.Stop()
   669  
   670  	logger := log.New(os.Stderr, "", log.LstdFlags)
   671  	client, err := NewVaultClient(v.Config, logger, nil)
   672  	if err != nil {
   673  		t.Fatalf("failed to build vault client: %v", err)
   674  	}
   675  	client.SetActive(true)
   676  	defer client.Stop()
   677  
   678  	// Create an allocation that requires a Vault policy
   679  	a := mock.Alloc()
   680  	task := a.Job.TaskGroups[0].Tasks[0]
   681  	task.Vault = &structs.Vault{Policies: []string{"default"}}
   682  
   683  	_, err = client.CreateToken(context.Background(), a, task.Name)
   684  	if err == nil {
   685  		t.Fatalf("CreateToken should have failed: %v", err)
   686  	}
   687  
   688  	if rerr, ok := err.(*structs.RecoverableError); !ok {
   689  		t.Fatalf("Err should have been type recoverable error")
   690  	} else if ok && !rerr.Recoverable {
   691  		t.Fatalf("Err should have been recoverable")
   692  	}
   693  }
   694  
   695  func TestVaultClient_RevokeTokens_PreEstablishs(t *testing.T) {
   696  	v := testutil.NewTestVault(t)
   697  	logger := log.New(os.Stderr, "", log.LstdFlags)
   698  	client, err := NewVaultClient(v.Config, logger, nil)
   699  	if err != nil {
   700  		t.Fatalf("failed to build vault client: %v", err)
   701  	}
   702  	client.SetActive(true)
   703  	defer client.Stop()
   704  
   705  	// Create some VaultAccessors
   706  	vas := []*structs.VaultAccessor{
   707  		mock.VaultAccessor(),
   708  		mock.VaultAccessor(),
   709  	}
   710  
   711  	if err := client.RevokeTokens(context.Background(), vas, false); err != nil {
   712  		t.Fatalf("RevokeTokens failed: %v", err)
   713  	}
   714  
   715  	// Wasn't committed
   716  	if len(client.revoking) != 0 {
   717  		t.Fatalf("didn't add to revoke loop")
   718  	}
   719  
   720  	if err := client.RevokeTokens(context.Background(), vas, true); err != nil {
   721  		t.Fatalf("RevokeTokens failed: %v", err)
   722  	}
   723  
   724  	// Was committed
   725  	if len(client.revoking) != 2 {
   726  		t.Fatalf("didn't add to revoke loop")
   727  	}
   728  }
   729  
   730  func TestVaultClient_RevokeTokens_Root(t *testing.T) {
   731  	v := testutil.NewTestVault(t).Start()
   732  	defer v.Stop()
   733  
   734  	purged := 0
   735  	purge := func(accessors []*structs.VaultAccessor) error {
   736  		purged += len(accessors)
   737  		return nil
   738  	}
   739  
   740  	logger := log.New(os.Stderr, "", log.LstdFlags)
   741  	client, err := NewVaultClient(v.Config, logger, purge)
   742  	if err != nil {
   743  		t.Fatalf("failed to build vault client: %v", err)
   744  	}
   745  	client.SetActive(true)
   746  	defer client.Stop()
   747  
   748  	waitForConnection(client, t)
   749  
   750  	// Create some vault tokens
   751  	auth := v.Client.Auth().Token()
   752  	req := vapi.TokenCreateRequest{
   753  		Policies: []string{"default"},
   754  	}
   755  	t1, err := auth.Create(&req)
   756  	if err != nil {
   757  		t.Fatalf("Failed to create vault token: %v", err)
   758  	}
   759  	if t1 == nil || t1.Auth == nil {
   760  		t.Fatalf("bad secret response: %+v", t1)
   761  	}
   762  	t2, err := auth.Create(&req)
   763  	if err != nil {
   764  		t.Fatalf("Failed to create vault token: %v", err)
   765  	}
   766  	if t2 == nil || t2.Auth == nil {
   767  		t.Fatalf("bad secret response: %+v", t2)
   768  	}
   769  
   770  	// Create two VaultAccessors
   771  	vas := []*structs.VaultAccessor{
   772  		&structs.VaultAccessor{Accessor: t1.Auth.Accessor},
   773  		&structs.VaultAccessor{Accessor: t2.Auth.Accessor},
   774  	}
   775  
   776  	// Issue a token revocation
   777  	if err := client.RevokeTokens(context.Background(), vas, true); err != nil {
   778  		t.Fatalf("RevokeTokens failed: %v", err)
   779  	}
   780  
   781  	// Lookup the token and make sure we get an error
   782  	if s, err := auth.Lookup(t1.Auth.ClientToken); err == nil {
   783  		t.Fatalf("Revoked token lookup didn't fail: %+v", s)
   784  	}
   785  	if s, err := auth.Lookup(t2.Auth.ClientToken); err == nil {
   786  		t.Fatalf("Revoked token lookup didn't fail: %+v", s)
   787  	}
   788  
   789  	if purged != 2 {
   790  		t.Fatalf("Expected purged 2; got %d", purged)
   791  	}
   792  }
   793  
   794  func TestVaultClient_RevokeTokens_Role(t *testing.T) {
   795  	v := testutil.NewTestVault(t).Start()
   796  	defer v.Stop()
   797  
   798  	// Set the configs token in a new test role
   799  	v.Config.Token = defaultTestVaultRoleAndToken(v, t, 5)
   800  
   801  	purged := 0
   802  	purge := func(accessors []*structs.VaultAccessor) error {
   803  		purged += len(accessors)
   804  		return nil
   805  	}
   806  
   807  	logger := log.New(os.Stderr, "", log.LstdFlags)
   808  	client, err := NewVaultClient(v.Config, logger, purge)
   809  	if err != nil {
   810  		t.Fatalf("failed to build vault client: %v", err)
   811  	}
   812  	client.SetActive(true)
   813  	defer client.Stop()
   814  
   815  	waitForConnection(client, t)
   816  
   817  	// Create some vault tokens
   818  	auth := v.Client.Auth().Token()
   819  	req := vapi.TokenCreateRequest{
   820  		Policies: []string{"default"},
   821  	}
   822  	t1, err := auth.Create(&req)
   823  	if err != nil {
   824  		t.Fatalf("Failed to create vault token: %v", err)
   825  	}
   826  	if t1 == nil || t1.Auth == nil {
   827  		t.Fatalf("bad secret response: %+v", t1)
   828  	}
   829  	t2, err := auth.Create(&req)
   830  	if err != nil {
   831  		t.Fatalf("Failed to create vault token: %v", err)
   832  	}
   833  	if t2 == nil || t2.Auth == nil {
   834  		t.Fatalf("bad secret response: %+v", t2)
   835  	}
   836  
   837  	// Create two VaultAccessors
   838  	vas := []*structs.VaultAccessor{
   839  		&structs.VaultAccessor{Accessor: t1.Auth.Accessor},
   840  		&structs.VaultAccessor{Accessor: t2.Auth.Accessor},
   841  	}
   842  
   843  	// Issue a token revocation
   844  	if err := client.RevokeTokens(context.Background(), vas, true); err != nil {
   845  		t.Fatalf("RevokeTokens failed: %v", err)
   846  	}
   847  
   848  	// Lookup the token and make sure we get an error
   849  	if s, err := auth.Lookup(t1.Auth.ClientToken); err == nil {
   850  		t.Fatalf("Revoked token lookup didn't fail: %+v", s)
   851  	}
   852  	if s, err := auth.Lookup(t2.Auth.ClientToken); err == nil {
   853  		t.Fatalf("Revoked token lookup didn't fail: %+v", s)
   854  	}
   855  
   856  	if purged != 2 {
   857  		t.Fatalf("Expected purged 2; got %d", purged)
   858  	}
   859  }
   860  
   861  func waitForConnection(v *vaultClient, t *testing.T) {
   862  	testutil.WaitForResult(func() (bool, error) {
   863  		return v.ConnectionEstablished()
   864  	}, func(err error) {
   865  		t.Fatalf("Connection not established")
   866  	})
   867  }